mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge mozilla-central to fx-team
This commit is contained in:
commit
0cfb6c0b29
@ -141,6 +141,7 @@ NotificationController::IsUpdatePending()
|
||||
void
|
||||
NotificationController::WillRefresh(mozilla::TimeStamp aTime)
|
||||
{
|
||||
PROFILER_LABEL_FUNC(js::ProfileEntry::Category::OTHER);
|
||||
Telemetry::AutoTimer<Telemetry::A11Y_UPDATE_TIME> updateTimer;
|
||||
|
||||
// If the document accessible that notification collector was created for is
|
||||
|
29
accessible/base/TextRange-inl.h
Normal file
29
accessible/base/TextRange-inl.h
Normal file
@ -0,0 +1,29 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_a11y_TextRange_inl_h__
|
||||
#define mozilla_a11y_TextRange_inl_h__
|
||||
|
||||
#include "TextRange.h"
|
||||
#include "HyperTextAccessible.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace a11y {
|
||||
|
||||
inline Accessible*
|
||||
TextRange::Container() const
|
||||
{
|
||||
uint32_t pos1 = 0, pos2 = 0;
|
||||
nsAutoTArray<Accessible*, 30> parents1, parents2;
|
||||
return CommonParent(mStartContainer, mEndContainer,
|
||||
&parents1, &pos1, &parents2, &pos2);
|
||||
}
|
||||
|
||||
|
||||
} // namespace a11y
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
@ -4,10 +4,9 @@
|
||||
* 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 "TextRange.h"
|
||||
#include "TextRange-inl.h"
|
||||
|
||||
#include "Accessible-inl.h"
|
||||
#include "HyperTextAccessible.h"
|
||||
#include "nsAccUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
@ -59,42 +58,6 @@ TextRange::TextRange(HyperTextAccessible* aRoot,
|
||||
{
|
||||
}
|
||||
|
||||
Accessible*
|
||||
TextRange::Container() const
|
||||
{
|
||||
if (mStartContainer == mEndContainer)
|
||||
return mStartContainer;
|
||||
|
||||
// Build the chain of parents
|
||||
Accessible* p1 = mStartContainer;
|
||||
Accessible* p2 = mEndContainer;
|
||||
nsAutoTArray<Accessible*, 30> parents1, parents2;
|
||||
do {
|
||||
parents1.AppendElement(p1);
|
||||
p1 = p1->Parent();
|
||||
} while (p1);
|
||||
do {
|
||||
parents2.AppendElement(p2);
|
||||
p2 = p2->Parent();
|
||||
} while (p2);
|
||||
|
||||
// Find where the parent chain differs
|
||||
uint32_t pos1 = parents1.Length();
|
||||
uint32_t pos2 = parents2.Length();
|
||||
Accessible* parent = nullptr;
|
||||
uint32_t len = 0;
|
||||
for (len = std::min(pos1, pos2); len > 0; --len) {
|
||||
Accessible* child1 = parents1.ElementAt(--pos1);
|
||||
Accessible* child2 = parents2.ElementAt(--pos2);
|
||||
if (child1 != child2)
|
||||
break;
|
||||
|
||||
parent = child1;
|
||||
}
|
||||
|
||||
return parent;
|
||||
}
|
||||
|
||||
void
|
||||
TextRange::EmbeddedChildren(nsTArray<Accessible*>* aChildren) const
|
||||
{
|
||||
@ -111,28 +74,11 @@ TextRange::EmbeddedChildren(nsTArray<Accessible*>* aChildren) const
|
||||
|
||||
Accessible* p1 = mStartContainer->GetChildAtOffset(mStartOffset);
|
||||
Accessible* p2 = mEndContainer->GetChildAtOffset(mEndOffset);
|
||||
|
||||
uint32_t pos1 = 0, pos2 = 0;
|
||||
nsAutoTArray<Accessible*, 30> parents1, parents2;
|
||||
do {
|
||||
parents1.AppendElement(p1);
|
||||
p1 = p1->Parent();
|
||||
} while (p1);
|
||||
do {
|
||||
parents2.AppendElement(p2);
|
||||
p2 = p2->Parent();
|
||||
} while (p2);
|
||||
|
||||
// Find deepest common container.
|
||||
uint32_t pos1 = parents1.Length();
|
||||
uint32_t pos2 = parents2.Length();
|
||||
Accessible* container = nullptr;
|
||||
for (uint32_t len = std::min(pos1, pos2); len > 0; --len) {
|
||||
Accessible* child1 = parents1.ElementAt(--pos1);
|
||||
Accessible* child2 = parents2.ElementAt(--pos2);
|
||||
if (child1 != child2)
|
||||
break;
|
||||
|
||||
container = child1;
|
||||
}
|
||||
Accessible* container =
|
||||
CommonParent(p1, p2, &parents1, &pos1, &parents2, &pos2);
|
||||
|
||||
// Traverse the tree up to the container and collect embedded objects.
|
||||
for (uint32_t idx = 0; idx < pos1 - 1; idx++) {
|
||||
@ -196,6 +142,95 @@ TextRange::Normalize(ETextUnit aUnit)
|
||||
|
||||
}
|
||||
|
||||
bool
|
||||
TextRange::Crop(Accessible* aContainer)
|
||||
{
|
||||
uint32_t boundaryPos = 0, containerPos = 0;
|
||||
nsAutoTArray<Accessible*, 30> boundaryParents, containerParents;
|
||||
|
||||
// Crop the start boundary.
|
||||
Accessible* container = nullptr;
|
||||
Accessible* boundary = mStartContainer->GetChildAtOffset(mStartOffset);
|
||||
if (boundary != aContainer) {
|
||||
CommonParent(boundary, aContainer, &boundaryParents, &boundaryPos,
|
||||
&containerParents, &containerPos);
|
||||
|
||||
if (boundaryPos == 0) {
|
||||
if (containerPos != 0) {
|
||||
// The container is contained by the start boundary, reduce the range to
|
||||
// the point starting at the container.
|
||||
aContainer->ToTextPoint(mStartContainer.StartAssignment(), &mStartOffset);
|
||||
static_cast<Accessible*>(mStartContainer)->AddRef();
|
||||
}
|
||||
else {
|
||||
// The start boundary and the container are siblings.
|
||||
container = aContainer;
|
||||
}
|
||||
}
|
||||
else if (containerPos != 0) {
|
||||
// The container does not contain the start boundary.
|
||||
boundary = boundaryParents[boundaryPos];
|
||||
container = containerParents[containerPos];
|
||||
}
|
||||
|
||||
if (container) {
|
||||
// If the range start is after the container, then make the range invalid.
|
||||
if (boundary->IndexInParent() > container->IndexInParent()) {
|
||||
return !!(mRoot = nullptr);
|
||||
}
|
||||
|
||||
// If the range starts before the container, then reduce the range to
|
||||
// the point starting at the container.
|
||||
if (boundary->IndexInParent() < container->IndexInParent()) {
|
||||
container->ToTextPoint(mStartContainer.StartAssignment(), &mStartOffset);
|
||||
mStartContainer.get()->AddRef();
|
||||
}
|
||||
}
|
||||
|
||||
boundaryParents.SetLengthAndRetainStorage(0);
|
||||
containerParents.SetLengthAndRetainStorage(0);
|
||||
}
|
||||
|
||||
boundary = mEndContainer->GetChildAtOffset(mEndOffset);
|
||||
if (boundary == aContainer) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Crop the end boundary.
|
||||
container = nullptr;
|
||||
CommonParent(boundary, aContainer, &boundaryParents, &boundaryPos,
|
||||
&containerParents, &containerPos);
|
||||
|
||||
if (boundaryPos == 0) {
|
||||
if (containerPos != 0) {
|
||||
aContainer->ToTextPoint(mEndContainer.StartAssignment(), &mEndOffset, false);
|
||||
static_cast<Accessible*>(mEndContainer)->AddRef();
|
||||
}
|
||||
else {
|
||||
container = aContainer;
|
||||
}
|
||||
}
|
||||
else if (containerPos != 0) {
|
||||
boundary = boundaryParents[boundaryPos];
|
||||
container = containerParents[containerPos];
|
||||
}
|
||||
|
||||
if (!container) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (boundary->IndexInParent() < container->IndexInParent()) {
|
||||
return !!(mRoot = nullptr);
|
||||
}
|
||||
|
||||
if (boundary->IndexInParent() > container->IndexInParent()) {
|
||||
container->ToTextPoint(mEndContainer.StartAssignment(), &mEndOffset, false);
|
||||
static_cast<Accessible*>(mEndContainer)->AddRef();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
TextRange::FindText(const nsAString& aText, EDirection aDirection,
|
||||
nsCaseTreatment aCaseSensitive, TextRange* aFoundRange) const
|
||||
@ -296,5 +331,46 @@ TextRange::MoveInternal(ETextUnit aUnit, int32_t aCount,
|
||||
|
||||
}
|
||||
|
||||
Accessible*
|
||||
TextRange::CommonParent(Accessible* aAcc1, Accessible* aAcc2,
|
||||
nsTArray<Accessible*>* aParents1, uint32_t* aPos1,
|
||||
nsTArray<Accessible*>* aParents2, uint32_t* aPos2) const
|
||||
{
|
||||
if (aAcc1 == aAcc2) {
|
||||
return aAcc1;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(aParents1->Length() == 0 || aParents2->Length() == 0,
|
||||
"Wrong arguments");
|
||||
|
||||
// Build the chain of parents.
|
||||
Accessible* p1 = aAcc1;
|
||||
Accessible* p2 = aAcc2;
|
||||
do {
|
||||
aParents1->AppendElement(p1);
|
||||
p1 = p1->Parent();
|
||||
} while (p1);
|
||||
do {
|
||||
aParents2->AppendElement(p2);
|
||||
p2 = p2->Parent();
|
||||
} while (p2);
|
||||
|
||||
// Find where the parent chain differs
|
||||
*aPos1 = aParents1->Length();
|
||||
*aPos2 = aParents2->Length();
|
||||
Accessible* parent = nullptr;
|
||||
uint32_t len = 0;
|
||||
for (len = std::min(*aPos1, *aPos2); len > 0; --len) {
|
||||
Accessible* child1 = aParents1->ElementAt(--(*aPos1));
|
||||
Accessible* child2 = aParents2->ElementAt(--(*aPos2));
|
||||
if (child1 != child2)
|
||||
break;
|
||||
|
||||
parent = child1;
|
||||
}
|
||||
|
||||
return parent;
|
||||
}
|
||||
|
||||
} // namespace a11y
|
||||
} // namespace mozilla
|
||||
|
@ -131,6 +131,12 @@ public:
|
||||
*/
|
||||
void Normalize(ETextUnit aUnit);
|
||||
|
||||
/**
|
||||
* Crops the range if it overlaps the given accessible element boundaries,
|
||||
* returns true if the range was cropped successfully.
|
||||
*/
|
||||
bool Crop(Accessible* aContainer);
|
||||
|
||||
enum EDirection {
|
||||
eBackward,
|
||||
eForward
|
||||
@ -243,6 +249,14 @@ private:
|
||||
HyperTextAccessible* aStopContainer = nullptr,
|
||||
int32_t aStopOffset = 0);
|
||||
|
||||
/**
|
||||
* A helper method returning a common parent for two given accessible
|
||||
* elements.
|
||||
*/
|
||||
Accessible* CommonParent(Accessible* aAcc1, Accessible* aAcc2,
|
||||
nsTArray<Accessible*>* aParents1, uint32_t* aPos1,
|
||||
nsTArray<Accessible*>* aParents2, uint32_t* aPos2) const;
|
||||
|
||||
RefPtr<HyperTextAccessible> mRoot;
|
||||
RefPtr<HyperTextAccessible> mStartContainer;
|
||||
RefPtr<HyperTextAccessible> mEndContainer;
|
||||
|
@ -2250,6 +2250,30 @@ Accessible::AnchorURIAt(uint32_t aAnchorIndex)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
Accessible::ToTextPoint(HyperTextAccessible** aContainer, int32_t* aOffset,
|
||||
bool aIsBefore) const
|
||||
{
|
||||
if (IsHyperText()) {
|
||||
*aContainer = const_cast<Accessible*>(this)->AsHyperText();
|
||||
*aOffset = aIsBefore ? 0 : (*aContainer)->CharacterCount();
|
||||
return;
|
||||
}
|
||||
|
||||
const Accessible* child = nullptr;
|
||||
const Accessible* parent = this;
|
||||
do {
|
||||
child = parent;
|
||||
parent = parent->Parent();
|
||||
} while (parent && !parent->IsHyperText());
|
||||
|
||||
if (parent) {
|
||||
*aContainer = const_cast<Accessible*>(parent)->AsHyperText();
|
||||
*aOffset = (*aContainer)->GetChildOffset(
|
||||
child->IndexInParent() + static_cast<int32_t>(!aIsBefore));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// SelectAccessible
|
||||
|
@ -758,6 +758,12 @@ public:
|
||||
*/
|
||||
virtual already_AddRefed<nsIURI> AnchorURIAt(uint32_t aAnchorIndex);
|
||||
|
||||
/**
|
||||
* Returns a text point for the accessible element.
|
||||
*/
|
||||
void ToTextPoint(HyperTextAccessible** aContainer, int32_t* aOffset,
|
||||
bool aIsBefore = true) const;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// SelectAccessible
|
||||
|
||||
|
@ -1769,7 +1769,7 @@ HyperTextAccessible::EnclosingRange(a11y::TextRange& aRange) const
|
||||
void
|
||||
HyperTextAccessible::SelectionRanges(nsTArray<a11y::TextRange>* aRanges) const
|
||||
{
|
||||
NS_ASSERTION(aRanges->Length() != 0, "TextRange array supposed to be empty");
|
||||
MOZ_ASSERT(aRanges->Length() == 0, "TextRange array supposed to be empty");
|
||||
|
||||
dom::Selection* sel = DOMSelection();
|
||||
if (!sel)
|
||||
|
@ -258,7 +258,7 @@ public:
|
||||
* @param aInvalidateAfter [in, optional] indicates whether invalidate
|
||||
* cached offsets for next siblings of the child
|
||||
*/
|
||||
int32_t GetChildOffset(Accessible* aChild,
|
||||
int32_t GetChildOffset(const Accessible* aChild,
|
||||
bool aInvalidateAfter = false) const
|
||||
{
|
||||
int32_t index = GetIndexOf(aChild);
|
||||
|
@ -11,6 +11,7 @@ GARBAGE += $(MIDL_GENERATED_FILES)
|
||||
MIDL_INTERFACES = \
|
||||
Accessible2.idl \
|
||||
Accessible2_2.idl \
|
||||
Accessible2_3.idl \
|
||||
AccessibleAction.idl \
|
||||
AccessibleApplication.idl \
|
||||
AccessibleComponent.idl \
|
||||
|
@ -13,7 +13,7 @@ interface nsIVariant;
|
||||
/**
|
||||
* A range representing a piece of text in the document.
|
||||
*/
|
||||
[scriptable, uuid(525b3401-8a67-4822-b35d-661065767cd8)]
|
||||
[scriptable, uuid(c4515623-55f9-4543-a3d5-c1e9afa588f4)]
|
||||
interface nsIAccessibleTextRange : nsISupports
|
||||
{
|
||||
readonly attribute nsIAccessibleText startContainer;
|
||||
@ -81,6 +81,11 @@ interface nsIAccessibleTextRange : nsISupports
|
||||
*/
|
||||
void normalize(in unsigned long aUnit);
|
||||
|
||||
/**
|
||||
* Crops the range by the given accessible element.
|
||||
*/
|
||||
boolean crop(in nsIAccessible aContainer);
|
||||
|
||||
/**
|
||||
* Return range enclosing the found text.
|
||||
*/
|
||||
|
@ -473,6 +473,10 @@ function testTextRange(aRange, aRangeDescr, aStartContainer, aStartOffset,
|
||||
is(aRange.endOffset, aEndOffset,
|
||||
"Wrong end offset of " + aRangeDescr);
|
||||
|
||||
if (aText === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
is(aRange.text, aText, "Wrong text of " + aRangeDescr);
|
||||
|
||||
var children = aRange.embeddedChildren;
|
||||
|
@ -1,3 +1,4 @@
|
||||
[DEFAULT]
|
||||
|
||||
[test_general.html]
|
||||
[test_selection.html]
|
||||
|
120
accessible/tests/mochitest/textrange/test_selection.html
Normal file
120
accessible/tests/mochitest/textrange/test_selection.html
Normal file
@ -0,0 +1,120 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Text Range selection tests</title>
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../common.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../text.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../layout.js"></script>
|
||||
<script type="application/javascript">
|
||||
|
||||
function doTest()
|
||||
{
|
||||
var sel = window.getSelection();
|
||||
var p = getNode("p1");
|
||||
var a = getNode("p2_a");
|
||||
|
||||
var range = document.createRange();
|
||||
sel.addRange(range);
|
||||
|
||||
// the accessible is contained by the range
|
||||
range.selectNode(p);
|
||||
|
||||
var a11yranges = getAccessible(document, [nsIAccessibleText]).selectionRanges;
|
||||
var a11yrange = a11yranges.queryElementAt(0, nsIAccessibleTextRange);
|
||||
|
||||
testTextRange(a11yrange, "selection range #1", document, 3, document, 4);
|
||||
|
||||
ok(a11yrange.crop(getAccessible(a)), "Range failed to crop #1.");
|
||||
testTextRange(a11yrange, "cropped range #1", a, 0, a, 5);
|
||||
|
||||
// the range is contained by the accessible
|
||||
range.selectNode(a);
|
||||
var a11yranges = getAccessible(document, [nsIAccessibleText]).selectionRanges;
|
||||
var a11yrange = a11yranges.queryElementAt(0, nsIAccessibleTextRange);
|
||||
|
||||
testTextRange(a11yrange, "selection range #2", p, 5, p, 6);
|
||||
|
||||
ok(a11yrange.crop(getAccessible(p)), "Range failed to crop #2.");
|
||||
testTextRange(a11yrange, "cropped range #2", p, 5, p, 6);
|
||||
|
||||
// the range starts before the accessible and ends inside it
|
||||
range.setStart(p, 0);
|
||||
range.setEndAfter(a.firstChild, 4);
|
||||
var a11yranges = getAccessible(document, [nsIAccessibleText]).selectionRanges;
|
||||
var a11yrange = a11yranges.queryElementAt(0, nsIAccessibleTextRange);
|
||||
|
||||
testTextRange(a11yrange, "selection range #3", p, 0, a, 4);
|
||||
|
||||
ok(a11yrange.crop(getAccessible(a)), "Range failed to crop #3.");
|
||||
testTextRange(a11yrange, "cropped range #3", a, 0, a, 4);
|
||||
|
||||
// the range starts inside the accessible and ends after it
|
||||
range.setStart(a.firstChild, 1);
|
||||
range.setEndAfter(p);
|
||||
var a11yranges = getAccessible(document, [nsIAccessibleText]).selectionRanges;
|
||||
var a11yrange = a11yranges.queryElementAt(0, nsIAccessibleTextRange);
|
||||
|
||||
testTextRange(a11yrange, "selection range #4", a, 1, document, 4);
|
||||
|
||||
ok(a11yrange.crop(getAccessible(a)), "Range failed to crop #4.");
|
||||
testTextRange(a11yrange, "cropped range #4", a, 1, a, 5);
|
||||
|
||||
// the range ends before the accessible
|
||||
range.setStart(p.firstChild, 0);
|
||||
range.setEnd(p.firstChild, 4);
|
||||
var a11yranges = getAccessible(document, [nsIAccessibleText]).selectionRanges;
|
||||
var a11yrange = a11yranges.queryElementAt(0, nsIAccessibleTextRange);
|
||||
|
||||
testTextRange(a11yrange, "selection range #5", p, 0, p, 4);
|
||||
ok(!a11yrange.crop(getAccessible(a)), "Crop #5 succeeded while it shouldn't");
|
||||
|
||||
// the range starts after the accessible
|
||||
range.setStart(p.lastChild, 0);
|
||||
range.setEnd(p.lastChild, 4);
|
||||
var a11yranges = getAccessible(document, [nsIAccessibleText]).selectionRanges;
|
||||
var a11yrange = a11yranges.queryElementAt(0, nsIAccessibleTextRange);
|
||||
|
||||
testTextRange(a11yrange, "selection range #6", p, 6, p, 10);
|
||||
|
||||
ok(!a11yrange.crop(getAccessible(a)), "Crop #6 succeeded while it shouldn't");
|
||||
|
||||
// crop a range by a table
|
||||
range.selectNode(getNode("c2"));
|
||||
var a11yranges = getAccessible(document, [nsIAccessibleText]).selectionRanges;
|
||||
var a11yrange = a11yranges.queryElementAt(0, nsIAccessibleTextRange);
|
||||
|
||||
testTextRange(a11yrange, "selection range #7", document, 4, document, 5);
|
||||
|
||||
ok(a11yrange.crop(getAccessible("table")), "Range failed to crop #7.");
|
||||
testTextRange(a11yrange, "cropped range #7", "c2", 5, "c2", 6);
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addA11yLoadEvent(doTest);
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<a target="_blank"
|
||||
title="Implement IAccessible2_3::selectionRanges"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=1233118">Bug 1233118</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
<p id="p1">text <a id="p2_a" href="www">link<img id="p2_img", src="../moz.png"></a> text</p>
|
||||
|
||||
<div id="c2">start<table id="table"><tr><td>cell</td></tr></table>end</div>
|
||||
</body>
|
||||
</html>
|
@ -8,6 +8,7 @@
|
||||
|
||||
#include "Accessible2_i.c"
|
||||
#include "Accessible2_2_i.c"
|
||||
#include "Accessible2_3_i.c"
|
||||
#include "AccessibleRole.h"
|
||||
#include "AccessibleStates.h"
|
||||
|
||||
@ -18,6 +19,7 @@
|
||||
#include "nsIAccessibleTypes.h"
|
||||
#include "mozilla/a11y/PDocAccessible.h"
|
||||
#include "Relation.h"
|
||||
#include "TextRange-inl.h"
|
||||
#include "nsAccessibilityService.h"
|
||||
|
||||
#include "nsIPersistentProperties2.h"
|
||||
@ -40,7 +42,9 @@ ia2Accessible::QueryInterface(REFIID iid, void** ppv)
|
||||
|
||||
*ppv = nullptr;
|
||||
|
||||
if (IID_IAccessible2_2 == iid)
|
||||
if (IID_IAccessible2_3 == iid)
|
||||
*ppv = static_cast<IAccessible2_3*>(this);
|
||||
else if (IID_IAccessible2_2 == iid)
|
||||
*ppv = static_cast<IAccessible2_2*>(this);
|
||||
else if (IID_IAccessible2 == iid && !Compatibility::IsIA2Off())
|
||||
*ppv = static_cast<IAccessible2*>(this);
|
||||
@ -749,6 +753,58 @@ ia2Accessible::get_relationTargetsOfType(BSTR aType,
|
||||
A11Y_TRYBLOCK_END
|
||||
}
|
||||
|
||||
STDMETHODIMP
|
||||
ia2Accessible::get_selectionRanges(IA2Range** aRanges,
|
||||
long *aNRanges)
|
||||
{
|
||||
A11Y_TRYBLOCK_BEGIN
|
||||
|
||||
if (!aRanges || !aNRanges || aNRanges <= 0)
|
||||
return E_INVALIDARG;
|
||||
|
||||
*aNRanges = 0;
|
||||
|
||||
AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
|
||||
if (acc->IsDefunct())
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
|
||||
nsAutoTArray<TextRange, 1> ranges;
|
||||
acc->Document()->SelectionRanges(&ranges);
|
||||
uint32_t len = ranges.Length();
|
||||
for (uint32_t idx = 0; idx < len; idx++) {
|
||||
if (!ranges[idx].Crop(acc)) {
|
||||
ranges.RemoveElementAt(idx);
|
||||
}
|
||||
}
|
||||
|
||||
*aNRanges = ranges.Length();
|
||||
*aRanges = static_cast<IA2Range*>(
|
||||
::CoTaskMemAlloc(sizeof(IA2Range) * *aNRanges));
|
||||
if (!*aRanges)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
for (uint32_t idx = 0; idx < static_cast<uint32_t>(*aNRanges); idx++) {
|
||||
AccessibleWrap* anchor =
|
||||
static_cast<AccessibleWrap*>(ranges[idx].StartContainer());
|
||||
(*aRanges)[idx].anchor = static_cast<IAccessible2*>(anchor);
|
||||
anchor->AddRef();
|
||||
|
||||
(*aRanges)[idx].anchorOffset = ranges[idx].StartOffset();
|
||||
|
||||
AccessibleWrap* active =
|
||||
static_cast<AccessibleWrap*>(ranges[idx].EndContainer());
|
||||
(*aRanges)[idx].active = static_cast<IAccessible2*>(active);
|
||||
active->AddRef();
|
||||
|
||||
(*aRanges)[idx].activeOffset = ranges[idx].EndOffset();
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
|
||||
A11Y_TRYBLOCK_END
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Helpers
|
||||
|
||||
|
@ -9,13 +9,13 @@
|
||||
|
||||
#include "nsISupports.h"
|
||||
|
||||
#include "Accessible2_2.h"
|
||||
#include "Accessible2_3.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace a11y {
|
||||
class Attribute;
|
||||
|
||||
class ia2Accessible : public IAccessible2_2
|
||||
class ia2Accessible : public IAccessible2_3
|
||||
{
|
||||
public:
|
||||
|
||||
@ -104,6 +104,11 @@ public:
|
||||
/* [out, retval] */ long* nTargets
|
||||
);
|
||||
|
||||
// IAccessible2_3
|
||||
virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_selectionRanges(
|
||||
/* [out, size_is(,*nRanges)] */ IA2Range** ranges,
|
||||
/* [out, retval] */ long *nRanges);
|
||||
|
||||
// Helper method
|
||||
static HRESULT ConvertToIA2Attributes(nsIPersistentProperties* aAttributes,
|
||||
BSTR* aIA2Attributes);
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
#include "xpcAccessibleTextRange.h"
|
||||
|
||||
#include "TextRange.h"
|
||||
#include "TextRange-inl.h"
|
||||
#include "xpcAccessibleDocument.h"
|
||||
|
||||
#include "nsIMutableArray.h"
|
||||
@ -170,6 +170,16 @@ xpcAccessibleTextRange::Normalize(uint32_t aUnit)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
xpcAccessibleTextRange::Crop(nsIAccessible* aContainer, bool* aSuccess)
|
||||
{
|
||||
Accessible* container = aContainer->ToInternalAccessible();
|
||||
NS_ENSURE_TRUE(container, NS_ERROR_INVALID_ARG);
|
||||
|
||||
*aSuccess = mRange.Crop(container);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
xpcAccessibleTextRange::FindText(const nsAString& aText, bool aIsBackward,
|
||||
bool aIsIgnoreCase,
|
||||
|
@ -49,6 +49,7 @@ public:
|
||||
NS_IMETHOD MoveStart(uint32_t aUnit, int32_t aCount) final override;
|
||||
NS_IMETHOD MoveEnd(uint32_t aUnit, int32_t aCount) final override;
|
||||
NS_IMETHOD Normalize(uint32_t aUnit) final override;
|
||||
NS_IMETHOD Crop(nsIAccessible* aContainer, bool* aSuccess) final override;
|
||||
NS_IMETHOD FindText(const nsAString& aText, bool aIsBackward, bool aIsIgnoreCase,
|
||||
nsIAccessibleTextRange** aRange) final override;
|
||||
NS_IMETHOD FindAttr(uint32_t aAttr, nsIVariant* aVal, bool aIsBackward,
|
||||
|
@ -21,7 +21,7 @@
|
||||
<!--
|
||||
B2G repositories for all targets
|
||||
-->
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="efd70ba6a54849dcef696abf1652cf74daa07899"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="619766a1ce78d50fb8a3b5a9e0821c335a0ed7ee"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="35dccb3127db8f39f20b985ad312d2cd44780669"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||
|
@ -21,12 +21,12 @@
|
||||
<!--
|
||||
B2G repositories for all targets
|
||||
-->
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="efd70ba6a54849dcef696abf1652cf74daa07899"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="619766a1ce78d50fb8a3b5a9e0821c335a0ed7ee"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="35dccb3127db8f39f20b985ad312d2cd44780669"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||
<!-- B2G specific things. -->
|
||||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<project name="platform_build" path="build" remote="b2g" revision="d3c9acb642baee501cff89e4efdb16b0c7480760">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
|
@ -21,12 +21,12 @@
|
||||
<!--
|
||||
B2G repositories for all targets
|
||||
-->
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="efd70ba6a54849dcef696abf1652cf74daa07899"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="619766a1ce78d50fb8a3b5a9e0821c335a0ed7ee"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="35dccb3127db8f39f20b985ad312d2cd44780669"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||
<!-- B2G specific things. -->
|
||||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<project name="platform_build" path="build" remote="b2g" revision="d3c9acb642baee501cff89e4efdb16b0c7480760">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
|
@ -21,7 +21,7 @@
|
||||
<!--
|
||||
B2G repositories for all targets
|
||||
-->
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="efd70ba6a54849dcef696abf1652cf74daa07899"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="619766a1ce78d50fb8a3b5a9e0821c335a0ed7ee"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="35dccb3127db8f39f20b985ad312d2cd44780669"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||
|
@ -21,7 +21,7 @@
|
||||
<!--
|
||||
B2G repositories for all targets
|
||||
-->
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="efd70ba6a54849dcef696abf1652cf74daa07899"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="619766a1ce78d50fb8a3b5a9e0821c335a0ed7ee"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="35dccb3127db8f39f20b985ad312d2cd44780669"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||
|
@ -21,12 +21,12 @@
|
||||
<!--
|
||||
B2G repositories for all targets
|
||||
-->
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="efd70ba6a54849dcef696abf1652cf74daa07899"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="619766a1ce78d50fb8a3b5a9e0821c335a0ed7ee"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="35dccb3127db8f39f20b985ad312d2cd44780669"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||
<!-- B2G specific things. -->
|
||||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<project name="platform_build" path="build" remote="b2g" revision="d3c9acb642baee501cff89e4efdb16b0c7480760">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
@ -137,7 +137,7 @@
|
||||
<default remote="caf" revision="refs/tags/android-4.4.2_r1" sync-j="4"/>
|
||||
<!-- Emulator specific things -->
|
||||
<project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="72ffdf71c68a96309212eb13d63560d66db14c9e"/>
|
||||
<project name="device_generic_goldfish" path="device/generic/goldfish" remote="b2g" revision="49f5591508df408fab7d7d8322681b004a2750f3"/>
|
||||
<project name="device_generic_goldfish" path="device/generic/goldfish" remote="b2g" revision="566810728cd485ff2f30766499d32ada7cbd487a"/>
|
||||
<project name="platform_bionic" path="bionic" remote="b2g" revision="3e85c4683c121530c1c3a48c696a569bf5f587e2"/>
|
||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="39bdda3051dd1d96da3ab369bc654290cb8d463c"/>
|
||||
<project name="platform/external/libnfc-nci" path="external/libnfc-nci" revision="f37bd545063039e30a92f2550ae78c0e6e4e2d08"/>
|
||||
@ -145,7 +145,7 @@
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="c0dd0098328f3992e1ca09d6d4355729243863d5"/>
|
||||
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="5f4b68c799927b6e078f987b12722c3a6ccd4a45"/>
|
||||
<project name="platform/development" path="development" revision="5968ff4e13e0d696ad8d972281fc27ae5a12829b"/>
|
||||
<project name="platform_prebuilts_qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="6a1bb59af65b6485b1090522f66fac95c3f9e22c"/>
|
||||
<project name="platform_prebuilts_qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="0c0c050518705d49531375012fa2b4e95e1b3693"/>
|
||||
<project name="android-sdk" path="sdk" remote="b2g" revision="0951179277915335251c5e11d242e4e1a8c2236f"/>
|
||||
<project name="darwinstreamingserver" path="system/darwinstreamingserver" remote="b2g" revision="cf85968c7f85e0ec36e72c87ceb4837a943b8af6"/>
|
||||
</manifest>
|
||||
|
@ -21,7 +21,7 @@
|
||||
<!--
|
||||
B2G repositories for all targets
|
||||
-->
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="efd70ba6a54849dcef696abf1652cf74daa07899"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="619766a1ce78d50fb8a3b5a9e0821c335a0ed7ee"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="35dccb3127db8f39f20b985ad312d2cd44780669"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||
|
@ -21,7 +21,7 @@
|
||||
<!--
|
||||
B2G repositories for all targets
|
||||
-->
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="efd70ba6a54849dcef696abf1652cf74daa07899"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="619766a1ce78d50fb8a3b5a9e0821c335a0ed7ee"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="35dccb3127db8f39f20b985ad312d2cd44780669"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||
|
@ -21,12 +21,12 @@
|
||||
<!--
|
||||
B2G repositories for all targets
|
||||
-->
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="efd70ba6a54849dcef696abf1652cf74daa07899"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="619766a1ce78d50fb8a3b5a9e0821c335a0ed7ee"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="35dccb3127db8f39f20b985ad312d2cd44780669"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||
<!-- B2G specific things. -->
|
||||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<project name="platform_build" path="build" remote="b2g" revision="d3c9acb642baee501cff89e4efdb16b0c7480760">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
|
@ -1,9 +1,9 @@
|
||||
{
|
||||
"git": {
|
||||
"git_revision": "efd70ba6a54849dcef696abf1652cf74daa07899",
|
||||
"git_revision": "619766a1ce78d50fb8a3b5a9e0821c335a0ed7ee",
|
||||
"remote": "https://git.mozilla.org/releases/gaia.git",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "687b7b7814ff8a089fda4c4d6be564305a0a2b69",
|
||||
"revision": "d74e738cd626558fb9dc289500ad28ae29deab03",
|
||||
"repo_path": "integration/gaia-central"
|
||||
}
|
||||
|
@ -21,12 +21,12 @@
|
||||
<!--
|
||||
B2G repositories for all targets
|
||||
-->
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="efd70ba6a54849dcef696abf1652cf74daa07899"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="619766a1ce78d50fb8a3b5a9e0821c335a0ed7ee"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="35dccb3127db8f39f20b985ad312d2cd44780669"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||
<!-- B2G specific things. -->
|
||||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<project name="platform_build" path="build" remote="b2g" revision="d3c9acb642baee501cff89e4efdb16b0c7480760">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
|
@ -21,7 +21,7 @@
|
||||
<!--
|
||||
B2G repositories for all targets
|
||||
-->
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="efd70ba6a54849dcef696abf1652cf74daa07899"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="619766a1ce78d50fb8a3b5a9e0821c335a0ed7ee"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="35dccb3127db8f39f20b985ad312d2cd44780669"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||
|
@ -21,7 +21,7 @@
|
||||
<!--
|
||||
B2G repositories for all targets
|
||||
-->
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="efd70ba6a54849dcef696abf1652cf74daa07899"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="619766a1ce78d50fb8a3b5a9e0821c335a0ed7ee"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="35dccb3127db8f39f20b985ad312d2cd44780669"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||
|
@ -1394,8 +1394,9 @@ pref("dom.identity.enabled", false);
|
||||
// Block insecure active content on https pages
|
||||
pref("security.mixed_content.block_active_content", true);
|
||||
|
||||
// Show degraded UI for http pages with password fields
|
||||
#ifdef NIGHTLY_BUILD
|
||||
// Show degraded UI for http pages with password fields.
|
||||
// Only for Nightly and Dev Edition for not, not for beta or release.
|
||||
#ifndef RELEASE_BUILD
|
||||
pref("security.insecure_password.ui.enabled", true);
|
||||
#else
|
||||
pref("security.insecure_password.ui.enabled", false);
|
||||
@ -1404,6 +1405,8 @@ pref("security.insecure_password.ui.enabled", false);
|
||||
// 1 = allow MITM for certificate pinning checks.
|
||||
pref("security.cert_pinning.enforcement_level", 1);
|
||||
|
||||
// NB: Changes to this pref affect CERT_CHAIN_SHA1_POLICY_STATUS telemetry.
|
||||
// See the comment in CertVerifier.cpp.
|
||||
// 0 = allow SHA-1
|
||||
pref("security.pki.sha1_enforcement_level", 0);
|
||||
|
||||
|
@ -554,7 +554,7 @@ add_task(function* test_offline_cache() {
|
||||
// Store something to the offline cache
|
||||
var appcacheserv = Cc["@mozilla.org/network/application-cache-service;1"]
|
||||
.getService(Ci.nsIApplicationCacheService);
|
||||
var appcachegroupid = appcacheserv.buildGroupID(makeURI(URL + "/manifest"), LoadContextInfo.default);
|
||||
var appcachegroupid = appcacheserv.buildGroupIDForInfo(makeURI(URL + "/manifest"), LoadContextInfo.default);
|
||||
var appcache = appcacheserv.createApplicationCache(appcachegroupid);
|
||||
var storage = Services.cache2.appCacheStorage(LoadContextInfo.default, appcache);
|
||||
|
||||
|
@ -14,37 +14,28 @@ support-files =
|
||||
webapi.html
|
||||
|
||||
[browser_426329.js]
|
||||
skip-if = e10s # Bug ?????? - Test uses load event and checks event.target.
|
||||
[browser_483086.js]
|
||||
[browser_addEngine.js]
|
||||
[browser_amazon.js]
|
||||
[browser_amazon_behavior.js]
|
||||
skip-if = e10s # Bug ?????? - some issue with progress listeners [JavaScript Error: "req.originalURI is null" {file: "chrome://mochitests/content/browser/browser/components/search/test/browser_bing_behavior.js" line: 127}]
|
||||
[browser_bing.js]
|
||||
[browser_bing_behavior.js]
|
||||
skip-if = e10s # Bug ?????? - some issue with progress listeners [JavaScript Error: "req.originalURI is null" {file: "chrome://mochitests/content/browser/browser/components/search/test/browser_bing_behavior.js" line: 127}]
|
||||
[browser_contextmenu.js]
|
||||
skip-if = e10s # Bug ?????? - Test touches content (content.window.getSelection().QueryInterface(Ci.nsISelectionPrivate)....)
|
||||
[browser_eBay.js]
|
||||
[browser_eBay_behavior.js]
|
||||
skip-if = e10s # Bug ?????? - some issue with progress listeners [JavaScript Error: "req.originalURI is null" {file: "chrome://mochitests/content/browser/browser/components/search/test/browser_bing_behavior.js" line: 127}]
|
||||
[browser_google.js]
|
||||
[browser_google_behavior.js]
|
||||
skip-if = e10s # Bug ?????? - some issue with progress listeners [JavaScript Error: "req.originalURI is null" {file: "chrome://mochitests/content/browser/browser/components/search/test/browser_bing_behavior.js" line: 127}]
|
||||
[browser_healthreport.js]
|
||||
[browser_hiddenOneOffs_cleanup.js]
|
||||
[browser_hiddenOneOffs_diacritics.js]
|
||||
[browser_oneOffHeader.js]
|
||||
skip-if = e10s # bug ?????? - Test alters the searchbar textbox value which causes issues with other tests in e10s.
|
||||
[browser_private_search_perwindowpb.js]
|
||||
skip-if = e10s # Bug ?????? - Test uses load event and checks event.target.
|
||||
[browser_yahoo.js]
|
||||
[browser_yahoo_behavior.js]
|
||||
skip-if = e10s # Bug ?????? - some issue with progress listeners [JavaScript Error: "req.originalURI is null" {file: "chrome://mochitests/content/browser/browser/components/search/test/browser_bing_behavior.js" line: 127}]
|
||||
[browser_abouthome_behavior.js]
|
||||
skip-if = e10s || true # Bug ??????, Bug 1100301 - leaks windows until shutdown when --run-by-dir
|
||||
skip-if = true # Bug ??????, Bug 1100301 - leaks windows until shutdown when --run-by-dir
|
||||
[browser_searchbar_openpopup.js]
|
||||
skip-if = os == "linux" || e10s # Linux has different focus behaviours and e10s seems to have timing issues.
|
||||
skip-if = os == "linux" # Linux has different focus behaviours.
|
||||
[browser_searchbar_keyboard_navigation.js]
|
||||
[browser_searchbar_smallpanel_keyboard_navigation.js]
|
||||
[browser_webapi.js]
|
||||
|
@ -1,14 +1,5 @@
|
||||
// Instead of loading ChromeUtils.js into the test scope in browser-test.js for all tests,
|
||||
// we only need ChromeUtils.js for a few files which is why we are using loadSubScript.
|
||||
var ChromeUtils = {};
|
||||
this._scriptLoader = Cc["@mozilla.org/moz/jssubscript-loader;1"].
|
||||
getService(Ci.mozIJSSubScriptLoader);
|
||||
this._scriptLoader.loadSubScript("chrome://mochikit/content/tests/SimpleTest/ChromeUtils.js", ChromeUtils);
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "FormHistory",
|
||||
"resource://gre/modules/FormHistory.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
|
||||
"resource://gre/modules/Promise.jsm");
|
||||
|
||||
function expectedURL(aSearchTerms) {
|
||||
const ENGINE_HTML_BASE = "http://mochi.test:8888/browser/browser/components/search/test/test.html";
|
||||
@ -53,73 +44,71 @@ function getMenuEntries() {
|
||||
return entries;
|
||||
}
|
||||
|
||||
function* countEntries(name, value) {
|
||||
let deferred = Promise.defer();
|
||||
let count = 0;
|
||||
let obj = name && value ? {fieldname: name, value: value} : {};
|
||||
FormHistory.count(obj,
|
||||
{ handleResult: function(result) { count = result; },
|
||||
handleError: function(error) { throw error; },
|
||||
handleCompletion: function(reason) {
|
||||
if (!reason) {
|
||||
deferred.resolve(count);
|
||||
function countEntries(name, value) {
|
||||
return new Promise(resolve => {
|
||||
let count = 0;
|
||||
let obj = name && value ? {fieldname: name, value: value} : {};
|
||||
FormHistory.count(obj,
|
||||
{ handleResult: function(result) { count = result; },
|
||||
handleError: function(error) { throw error; },
|
||||
handleCompletion: function(reason) {
|
||||
if (!reason) {
|
||||
resolve(count);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return deferred.promise;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
var searchBar;
|
||||
var searchButton;
|
||||
var searchEntries = ["test"];
|
||||
function* promiseSetEngine() {
|
||||
let deferred = Promise.defer();
|
||||
var ss = Services.search;
|
||||
function promiseSetEngine() {
|
||||
return new Promise(resolve => {
|
||||
var ss = Services.search;
|
||||
|
||||
function observer(aSub, aTopic, aData) {
|
||||
switch (aData) {
|
||||
case "engine-added":
|
||||
var engine = ss.getEngineByName("Bug 426329");
|
||||
ok(engine, "Engine was added.");
|
||||
ss.currentEngine = engine;
|
||||
break;
|
||||
case "engine-current":
|
||||
ok(ss.currentEngine.name == "Bug 426329", "currentEngine set");
|
||||
searchBar = BrowserSearch.searchBar;
|
||||
searchButton = document.getAnonymousElementByAttribute(searchBar,
|
||||
"anonid", "search-go-button");
|
||||
ok(searchButton, "got search-go-button");
|
||||
searchBar.value = "test";
|
||||
function observer(aSub, aTopic, aData) {
|
||||
switch (aData) {
|
||||
case "engine-added":
|
||||
var engine = ss.getEngineByName("Bug 426329");
|
||||
ok(engine, "Engine was added.");
|
||||
ss.currentEngine = engine;
|
||||
break;
|
||||
case "engine-current":
|
||||
ok(ss.currentEngine.name == "Bug 426329", "currentEngine set");
|
||||
searchBar = BrowserSearch.searchBar;
|
||||
searchButton = document.getAnonymousElementByAttribute(searchBar,
|
||||
"anonid", "search-go-button");
|
||||
ok(searchButton, "got search-go-button");
|
||||
searchBar.value = "test";
|
||||
|
||||
Services.obs.removeObserver(observer, "browser-search-engine-modified");
|
||||
deferred.resolve();
|
||||
break;
|
||||
}
|
||||
};
|
||||
Services.obs.removeObserver(observer, "browser-search-engine-modified");
|
||||
resolve();
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
Services.obs.addObserver(observer, "browser-search-engine-modified", false);
|
||||
ss.addEngine("http://mochi.test:8888/browser/browser/components/search/test/426329.xml",
|
||||
null, "data:image/x-icon,%00", false);
|
||||
|
||||
return deferred.promise;
|
||||
Services.obs.addObserver(observer, "browser-search-engine-modified", false);
|
||||
ss.addEngine("http://mochi.test:8888/browser/browser/components/search/test/426329.xml",
|
||||
null, "data:image/x-icon,%00", false);
|
||||
});
|
||||
}
|
||||
|
||||
function* promiseRemoveEngine() {
|
||||
let deferred = Promise.defer();
|
||||
var ss = Services.search;
|
||||
function promiseRemoveEngine() {
|
||||
return new Promise(resolve => {
|
||||
var ss = Services.search;
|
||||
|
||||
function observer(aSub, aTopic, aData) {
|
||||
if (aData == "engine-removed") {
|
||||
Services.obs.removeObserver(observer, "browser-search-engine-modified");
|
||||
deferred.resolve();
|
||||
}
|
||||
};
|
||||
function observer(aSub, aTopic, aData) {
|
||||
if (aData == "engine-removed") {
|
||||
Services.obs.removeObserver(observer, "browser-search-engine-modified");
|
||||
resolve();
|
||||
}
|
||||
};
|
||||
|
||||
Services.obs.addObserver(observer, "browser-search-engine-modified", false);
|
||||
var engine = ss.getEngineByName("Bug 426329");
|
||||
ss.removeEngine(engine);
|
||||
|
||||
return deferred.promise;
|
||||
Services.obs.addObserver(observer, "browser-search-engine-modified", false);
|
||||
var engine = ss.getEngineByName("Bug 426329");
|
||||
ss.removeEngine(engine);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -130,22 +119,15 @@ function* prepareTest() {
|
||||
preTabNo = gBrowser.tabs.length;
|
||||
searchBar = BrowserSearch.searchBar;
|
||||
|
||||
let windowFocused = Promise.defer();
|
||||
SimpleTest.waitForFocus(windowFocused.resolve, window);
|
||||
yield windowFocused.promise;
|
||||
yield SimpleTest.promiseFocus();
|
||||
|
||||
let deferred = Promise.defer();
|
||||
if (document.activeElement != searchBar) {
|
||||
searchBar.addEventListener("focus", function onFocus() {
|
||||
searchBar.removeEventListener("focus", onFocus);
|
||||
deferred.resolve();
|
||||
});
|
||||
gURLBar.focus();
|
||||
searchBar.focus();
|
||||
} else {
|
||||
deferred.resolve();
|
||||
}
|
||||
return deferred.promise;
|
||||
if (document.activeElement == searchBar)
|
||||
return;
|
||||
|
||||
let focusPromise = BrowserTestUtils.waitForEvent(searchBar, "focus");
|
||||
gURLBar.focus();
|
||||
searchBar.focus();
|
||||
yield focusPromise;
|
||||
}
|
||||
|
||||
add_task(function* testSetupEngine() {
|
||||
@ -153,90 +135,81 @@ add_task(function* testSetupEngine() {
|
||||
});
|
||||
|
||||
add_task(function* testReturn() {
|
||||
yield prepareTest();
|
||||
yield* prepareTest();
|
||||
EventUtils.synthesizeKey("VK_RETURN", {});
|
||||
let event = yield promiseOnLoad();
|
||||
yield BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
|
||||
|
||||
is(gBrowser.tabs.length, preTabNo, "Return key did not open new tab");
|
||||
is(event.originalTarget, preSelectedBrowser.contentDocument,
|
||||
"Return key loaded results in current tab");
|
||||
is(event.originalTarget.URL, expectedURL(searchBar.value), "testReturn opened correct search page");
|
||||
is(gBrowser.currentURI.spec, expectedURL(searchBar.value), "testReturn opened correct search page");
|
||||
});
|
||||
|
||||
add_task(function* testAltReturn() {
|
||||
yield prepareTest();
|
||||
EventUtils.synthesizeKey("VK_RETURN", { altKey: true });
|
||||
let event = yield promiseOnLoad();
|
||||
yield* prepareTest();
|
||||
yield BrowserTestUtils.openNewForegroundTab(gBrowser, () => {
|
||||
EventUtils.synthesizeKey("VK_RETURN", { altKey: true });
|
||||
});
|
||||
|
||||
is(gBrowser.tabs.length, preTabNo + 1, "Alt+Return key added new tab");
|
||||
isnot(event.originalTarget, preSelectedBrowser.contentDocument,
|
||||
"Alt+Return key loaded results in new tab");
|
||||
is(event.originalTarget, gBrowser.contentDocument,
|
||||
"Alt+Return key loaded results in foreground tab");
|
||||
is(event.originalTarget.URL, expectedURL(searchBar.value), "testAltReturn opened correct search page");
|
||||
is(gBrowser.currentURI.spec, expectedURL(searchBar.value), "testAltReturn opened correct search page");
|
||||
});
|
||||
|
||||
//Shift key has no effect for now, so skip it
|
||||
add_task(function* testShiftAltReturn() {
|
||||
return;
|
||||
|
||||
yield prepareTest();
|
||||
yield* prepareTest();
|
||||
|
||||
let url = expectedURL(searchBar.value);
|
||||
|
||||
let newTabPromise = BrowserTestUtils.waitForNewTab(gBrowser, url);
|
||||
EventUtils.synthesizeKey("VK_RETURN", { shiftKey: true, altKey: true });
|
||||
let event = yield promiseOnLoad();
|
||||
let newTab = yield newTabPromise;
|
||||
|
||||
is(gBrowser.tabs.length, preTabNo + 1, "Shift+Alt+Return key added new tab");
|
||||
isnot(event.originalTarget, preSelectedBrowser.contentDocument,
|
||||
"Shift+Alt+Return key loaded results in new tab");
|
||||
isnot(event.originalTarget, gBrowser.contentDocument,
|
||||
"Shift+Alt+Return key loaded results in background tab");
|
||||
is(event.originalTarget.URL, expectedURL(searchBar.value), "testShiftAltReturn opened correct search page");
|
||||
is(gBrowser.currentURI.spec, url, "testShiftAltReturn opened correct search page");
|
||||
});
|
||||
|
||||
add_task(function* testLeftClick() {
|
||||
yield prepareTest();
|
||||
yield* prepareTest();
|
||||
simulateClick({ button: 0 }, searchButton);
|
||||
let event = yield promiseOnLoad();
|
||||
yield BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
|
||||
is(gBrowser.tabs.length, preTabNo, "LeftClick did not open new tab");
|
||||
is(event.originalTarget, preSelectedBrowser.contentDocument,
|
||||
"LeftClick loaded results in current tab");
|
||||
is(event.originalTarget.URL, expectedURL(searchBar.value), "testLeftClick opened correct search page");
|
||||
is(gBrowser.currentURI.spec, expectedURL(searchBar.value), "testLeftClick opened correct search page");
|
||||
});
|
||||
|
||||
add_task(function* testMiddleClick() {
|
||||
yield prepareTest();
|
||||
simulateClick({ button: 1 }, searchButton);
|
||||
let event = yield promiseOnLoad();
|
||||
yield* prepareTest();
|
||||
yield BrowserTestUtils.openNewForegroundTab(gBrowser, () => {
|
||||
simulateClick({ button: 1 }, searchButton);
|
||||
});
|
||||
is(gBrowser.tabs.length, preTabNo + 1, "MiddleClick added new tab");
|
||||
isnot(event.originalTarget, preSelectedBrowser.contentDocument,
|
||||
"MiddleClick loaded results in new tab");
|
||||
is(event.originalTarget, gBrowser.contentDocument,
|
||||
"MiddleClick loaded results in foreground tab");
|
||||
is(event.originalTarget.URL, expectedURL(searchBar.value), "testMiddleClick opened correct search page");
|
||||
is(gBrowser.currentURI.spec, expectedURL(searchBar.value), "testMiddleClick opened correct search page");
|
||||
});
|
||||
|
||||
add_task(function* testShiftMiddleClick() {
|
||||
yield prepareTest();
|
||||
yield* prepareTest();
|
||||
|
||||
let url = expectedURL(searchBar.value);
|
||||
|
||||
let newTabPromise = BrowserTestUtils.waitForNewTab(gBrowser, url);
|
||||
simulateClick({ button: 1, shiftKey: true }, searchButton);
|
||||
let event = yield promiseOnLoad();
|
||||
let newTab = yield newTabPromise;
|
||||
|
||||
is(gBrowser.tabs.length, preTabNo + 1, "Shift+MiddleClick added new tab");
|
||||
isnot(event.originalTarget, preSelectedBrowser.contentDocument,
|
||||
"Shift+MiddleClick loaded results in new tab");
|
||||
isnot(event.originalTarget, gBrowser.contentDocument,
|
||||
"Shift+MiddleClick loaded results in background tab");
|
||||
is(event.originalTarget.URL, expectedURL(searchBar.value), "testShiftMiddleClick opened correct search page");
|
||||
is(newTab.linkedBrowser.currentURI.spec, url, "testShiftMiddleClick opened correct search page");
|
||||
});
|
||||
|
||||
add_task(function* testRightClick() {
|
||||
preTabNo = gBrowser.tabs.length;
|
||||
content.location.href = "about:blank";
|
||||
simulateClick({ button: 2 }, searchButton);
|
||||
let deferred = Promise.defer();
|
||||
setTimeout(function() {
|
||||
is(gBrowser.tabs.length, preTabNo, "RightClick did not open new tab");
|
||||
is(gBrowser.currentURI.spec, "about:blank", "RightClick did nothing");
|
||||
deferred.resolve();
|
||||
}, 5000);
|
||||
yield deferred.promise;
|
||||
gBrowser.selectedBrowser.loadURI("about:blank");
|
||||
yield new Promise(resolve => {
|
||||
setTimeout(function() {
|
||||
is(gBrowser.tabs.length, preTabNo, "RightClick did not open new tab");
|
||||
is(gBrowser.currentURI.spec, "about:blank", "RightClick did nothing");
|
||||
resolve();
|
||||
}, 5000);
|
||||
simulateClick({ button: 2 }, searchButton);
|
||||
});
|
||||
// The click in the searchbox focuses it, which opens the suggestion
|
||||
// panel. Clean up after ourselves.
|
||||
searchBar.textbox.popup.hidePopup();
|
||||
@ -252,7 +225,7 @@ add_task(function* testSearchHistory() {
|
||||
|
||||
add_task(function* testAutocomplete() {
|
||||
var popup = searchBar.textbox.popup;
|
||||
let popupShownPromise = promiseEvent(popup, "popupshown");
|
||||
let popupShownPromise = BrowserTestUtils.waitForEvent(popup, "popupshown");
|
||||
searchBar.textbox.showHistoryPopup();
|
||||
yield popupShownPromise;
|
||||
checkMenuEntries(searchEntries);
|
||||
@ -271,6 +244,6 @@ add_task(function* asyncCleanup() {
|
||||
while (gBrowser.tabs.length != 1) {
|
||||
gBrowser.removeTab(gBrowser.tabs[0], {animate: false});
|
||||
}
|
||||
content.location.href = "about:blank";
|
||||
gBrowser.selectedBrowser.loadURI("about:blank");
|
||||
yield promiseRemoveEngine();
|
||||
});
|
||||
|
@ -119,6 +119,9 @@ function test() {
|
||||
if (!(flags & docStart) || !webProgress.isTopLevel)
|
||||
return;
|
||||
|
||||
if (req.originalURI.spec == "about:blank")
|
||||
return;
|
||||
|
||||
info("received document start");
|
||||
|
||||
ok(req instanceof Ci.nsIChannel, "req is a channel");
|
||||
|
@ -136,6 +136,9 @@ function test() {
|
||||
if (!(flags & docStart) || !webProgress.isTopLevel)
|
||||
return;
|
||||
|
||||
if (req.originalURI.spec == "about:blank")
|
||||
return;
|
||||
|
||||
info("received document start");
|
||||
|
||||
ok(req instanceof Ci.nsIChannel, "req is a channel");
|
||||
|
@ -136,6 +136,9 @@ function test() {
|
||||
if (!(flags & docStart) || !webProgress.isTopLevel)
|
||||
return;
|
||||
|
||||
if (req.originalURI.spec == "about:blank")
|
||||
return;
|
||||
|
||||
info("received document start");
|
||||
|
||||
ok(req instanceof Ci.nsIChannel, "req is a channel");
|
||||
|
@ -4,9 +4,7 @@
|
||||
* Test searching for the selected text using the context menu
|
||||
*/
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
add_task(function* () {
|
||||
const ss = Services.search;
|
||||
const ENGINE_NAME = "Foo";
|
||||
var contextMenu;
|
||||
@ -22,90 +20,79 @@ function test() {
|
||||
resProt.setSubstitution("search-plugins",
|
||||
Services.io.newURI(url, null, null));
|
||||
|
||||
function observer(aSub, aTopic, aData) {
|
||||
switch (aData) {
|
||||
case "engine-added":
|
||||
var engine = ss.getEngineByName(ENGINE_NAME);
|
||||
ok(engine, "Engine was added.");
|
||||
ss.currentEngine = engine;
|
||||
envService.set("XPCSHELL_TEST_PROFILE_DIR", originalValue);
|
||||
resProt.setSubstitution("search-plugins", originalSubstitution);
|
||||
break;
|
||||
case "engine-current":
|
||||
is(ss.currentEngine.name, ENGINE_NAME, "currentEngine set");
|
||||
startTest();
|
||||
break;
|
||||
case "engine-removed":
|
||||
Services.obs.removeObserver(observer, "browser-search-engine-modified");
|
||||
finish();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Services.obs.addObserver(observer, "browser-search-engine-modified", false);
|
||||
ss.addEngine("resource://search-plugins/testEngine_mozsearch.xml",
|
||||
null, "data:image/x-icon,%00", false);
|
||||
|
||||
function startTest() {
|
||||
contextMenu = document.getElementById("contentAreaContextMenu");
|
||||
ok(contextMenu, "Got context menu XUL");
|
||||
|
||||
doOnloadOnce(testContextMenu);
|
||||
let tab = gBrowser.selectedTab = gBrowser.addTab("data:text/plain;charset=utf8,test%20search");
|
||||
registerCleanupFunction(function () {
|
||||
gBrowser.removeTab(tab);
|
||||
});
|
||||
}
|
||||
|
||||
function testContextMenu() {
|
||||
function rightClickOnDocument() {
|
||||
info("rightClickOnDocument: " + content.window.location);
|
||||
waitForBrowserContextMenu(checkContextMenu);
|
||||
var clickTarget = content.document.body;
|
||||
var eventDetails = { type: "contextmenu", button: 2 };
|
||||
EventUtils.synthesizeMouseAtCenter(clickTarget, eventDetails, content);
|
||||
}
|
||||
|
||||
// check the search menu item and then perform a search
|
||||
function checkContextMenu() {
|
||||
info("checkContextMenu");
|
||||
var searchItem = contextMenu.getElementsByAttribute("id", "context-searchselect")[0];
|
||||
ok(searchItem, "Got search context menu item");
|
||||
is(searchItem.label, 'Search ' + ENGINE_NAME + ' for "test search"', "Check context menu label");
|
||||
is(searchItem.disabled, false, "Check that search context menu item is enabled");
|
||||
doOnloadOnce(checkSearchURL);
|
||||
searchItem.click();
|
||||
contextMenu.hidePopup();
|
||||
}
|
||||
|
||||
function checkSearchURL(event) {
|
||||
is(event.originalTarget.URL,
|
||||
"http://mochi.test:8888/browser/browser/components/search/test/?test=test+search&ie=utf-8&channel=contextsearch",
|
||||
"Checking context menu search URL");
|
||||
// Remove the tab opened by the search
|
||||
gBrowser.removeCurrentTab();
|
||||
ss.removeEngine(ss.currentEngine);
|
||||
}
|
||||
|
||||
var selectionListener = {
|
||||
notifySelectionChanged: function(doc, sel, reason) {
|
||||
if (reason != Ci.nsISelectionListener.SELECTALL_REASON || sel.toString() != "test search")
|
||||
return;
|
||||
info("notifySelectionChanged: Text selected");
|
||||
content.window.getSelection().QueryInterface(Ci.nsISelectionPrivate).
|
||||
removeSelectionListener(selectionListener);
|
||||
SimpleTest.executeSoon(rightClickOnDocument);
|
||||
let searchDonePromise;
|
||||
yield new Promise(resolve => {
|
||||
function observer(aSub, aTopic, aData) {
|
||||
switch (aData) {
|
||||
case "engine-added":
|
||||
var engine = ss.getEngineByName(ENGINE_NAME);
|
||||
ok(engine, "Engine was added.");
|
||||
ss.currentEngine = engine;
|
||||
envService.set("XPCSHELL_TEST_PROFILE_DIR", originalValue);
|
||||
resProt.setSubstitution("search-plugins", originalSubstitution);
|
||||
break;
|
||||
case "engine-current":
|
||||
is(ss.currentEngine.name, ENGINE_NAME, "currentEngine set");
|
||||
resolve();
|
||||
break;
|
||||
case "engine-removed":
|
||||
Services.obs.removeObserver(observer, "browser-search-engine-modified");
|
||||
if (searchDonePromise) {
|
||||
searchDonePromise();
|
||||
}
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Delay the select all to avoid intermittent selection failures.
|
||||
setTimeout(function delaySelectAll() {
|
||||
info("delaySelectAll: " + content.window.location.toString());
|
||||
// add a listener to know when the selection takes effect
|
||||
content.window.getSelection().QueryInterface(Ci.nsISelectionPrivate).
|
||||
addSelectionListener(selectionListener);
|
||||
// select the text on the page
|
||||
goDoCommand('cmd_selectAll');
|
||||
}, 500);
|
||||
}
|
||||
}
|
||||
Services.obs.addObserver(observer, "browser-search-engine-modified", false);
|
||||
ss.addEngine("resource://search-plugins/testEngine_mozsearch.xml",
|
||||
null, "data:image/x-icon,%00", false);
|
||||
});
|
||||
|
||||
contextMenu = document.getElementById("contentAreaContextMenu");
|
||||
ok(contextMenu, "Got context menu XUL");
|
||||
|
||||
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "data:text/plain;charset=utf8,test%20search");
|
||||
|
||||
yield ContentTask.spawn(tab.linkedBrowser, "", function*() {
|
||||
return new Promise(resolve => {
|
||||
content.document.addEventListener("selectionchange", function selectionChanged() {
|
||||
content.document.removeEventListener("selectionchange", selectionChanged);
|
||||
resolve();
|
||||
});
|
||||
content.document.getSelection().selectAllChildren(content.document.body);
|
||||
});
|
||||
});
|
||||
|
||||
var eventDetails = { type: "contextmenu", button: 2 };
|
||||
|
||||
let popupPromise = BrowserTestUtils.waitForEvent(contextMenu, "popupshown");
|
||||
BrowserTestUtils.synthesizeMouseAtCenter("body", eventDetails, gBrowser.selectedBrowser);
|
||||
yield popupPromise;
|
||||
|
||||
info("checkContextMenu");
|
||||
var searchItem = contextMenu.getElementsByAttribute("id", "context-searchselect")[0];
|
||||
ok(searchItem, "Got search context menu item");
|
||||
is(searchItem.label, 'Search ' + ENGINE_NAME + ' for "test search"', "Check context menu label");
|
||||
is(searchItem.disabled, false, "Check that search context menu item is enabled");
|
||||
|
||||
yield BrowserTestUtils.openNewForegroundTab(gBrowser, () => {
|
||||
searchItem.click();
|
||||
});
|
||||
|
||||
is(gBrowser.currentURI.spec,
|
||||
"http://mochi.test:8888/browser/browser/components/search/test/?test=test+search&ie=utf-8&channel=contextsearch",
|
||||
"Checking context menu search URL");
|
||||
|
||||
contextMenu.hidePopup();
|
||||
|
||||
// Remove the tab opened by the search
|
||||
gBrowser.removeCurrentTab();
|
||||
|
||||
yield new Promise(resolve => {
|
||||
searchDonePromise = resolve;
|
||||
ss.removeEngine(ss.currentEngine);
|
||||
});
|
||||
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
@ -136,6 +136,9 @@ function test() {
|
||||
if (!(flags & docStart) || !webProgress.isTopLevel)
|
||||
return;
|
||||
|
||||
if (req.originalURI.spec == "about:blank")
|
||||
return;
|
||||
|
||||
info("received document start");
|
||||
|
||||
ok(req instanceof Ci.nsIChannel, "req is a channel");
|
||||
|
@ -134,6 +134,9 @@ function test() {
|
||||
if (!(flags & docStart) || !webProgress.isTopLevel)
|
||||
return;
|
||||
|
||||
if (req.originalURI.spec == "about:blank")
|
||||
return;
|
||||
|
||||
info("received document start");
|
||||
|
||||
ok(req instanceof Ci.nsIChannel, "req is a channel");
|
||||
|
@ -2,103 +2,67 @@
|
||||
// search in a private window, and then checks in the public window
|
||||
// whether there is an autocomplete entry for the private search.
|
||||
|
||||
function test() {
|
||||
add_task(function* () {
|
||||
// Don't use about:home as the homepage for new windows
|
||||
Services.prefs.setIntPref("browser.startup.page", 0);
|
||||
registerCleanupFunction(() => Services.prefs.clearUserPref("browser.startup.page"));
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
let engineURL =
|
||||
"http://mochi.test:8888/browser/browser/components/search/test/";
|
||||
let windowsToClose = [];
|
||||
registerCleanupFunction(function() {
|
||||
let engine = Services.search.getEngineByName("Bug 426329");
|
||||
Services.search.removeEngine(engine);
|
||||
windowsToClose.forEach(function(win) {
|
||||
win.close();
|
||||
});
|
||||
});
|
||||
|
||||
function onPageLoad(aWin, aCallback) {
|
||||
aWin.gBrowser.addEventListener("DOMContentLoaded", function load(aEvent) {
|
||||
let doc = aEvent.originalTarget;
|
||||
info(doc.location.href);
|
||||
if (doc.location.href.indexOf(engineURL) != -1) {
|
||||
aWin.gBrowser.removeEventListener("DOMContentLoaded", load, false);
|
||||
aCallback();
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
|
||||
function performSearch(aWin, aIsPrivate, aCallback) {
|
||||
function performSearch(aWin, aIsPrivate) {
|
||||
let searchBar = aWin.BrowserSearch.searchBar;
|
||||
ok(searchBar, "got search bar");
|
||||
onPageLoad(aWin, aCallback);
|
||||
|
||||
let loadPromise = BrowserTestUtils.browserLoaded(aWin.gBrowser.selectedBrowser);
|
||||
|
||||
searchBar.value = aIsPrivate ? "private test" : "public test";
|
||||
searchBar.focus();
|
||||
EventUtils.synthesizeKey("VK_RETURN", {}, aWin);
|
||||
|
||||
return loadPromise;
|
||||
}
|
||||
|
||||
function addEngine(aCallback) {
|
||||
let installCallback = {
|
||||
onSuccess: function (engine) {
|
||||
Services.search.currentEngine = engine;
|
||||
aCallback();
|
||||
},
|
||||
onError: function (errorCode) {
|
||||
ok(false, "failed to install engine: " + errorCode);
|
||||
}
|
||||
};
|
||||
Services.search.addEngine(engineURL + "426329.xml", null,
|
||||
"data:image/x-icon,%00", false, installCallback);
|
||||
}
|
||||
|
||||
function testOnWindow(aIsPrivate, aCallback) {
|
||||
let win = whenNewWindowLoaded({ private: aIsPrivate }, function() {
|
||||
waitForFocus(aCallback, win);
|
||||
});
|
||||
function* testOnWindow(aIsPrivate) {
|
||||
let win = yield BrowserTestUtils.openNewBrowserWindow({ private: aIsPrivate });
|
||||
yield SimpleTest.promiseFocus(win);
|
||||
windowsToClose.push(win);
|
||||
return win;
|
||||
}
|
||||
|
||||
addEngine(function() {
|
||||
testOnWindow(false, function(win) {
|
||||
performSearch(win, false, function() {
|
||||
testOnWindow(true, function(win) {
|
||||
performSearch(win, true, function() {
|
||||
testOnWindow(false, function(win) {
|
||||
checkSearchPopup(win, finish);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
yield promiseNewEngine("426329.xml", { iconURL: "data:image/x-icon,%00" });
|
||||
|
||||
function checkSearchPopup(aWin, aCallback) {
|
||||
let searchBar = aWin.BrowserSearch.searchBar;
|
||||
let newWindow = yield* testOnWindow(false);
|
||||
yield performSearch(newWindow, false);
|
||||
|
||||
newWindow = yield* testOnWindow(true);
|
||||
yield performSearch(newWindow, true);
|
||||
|
||||
newWindow = yield* testOnWindow(false);
|
||||
|
||||
let searchBar = newWindow.BrowserSearch.searchBar;
|
||||
searchBar.value = "p";
|
||||
searchBar.focus();
|
||||
|
||||
let popup = searchBar.textbox.popup;
|
||||
popup.addEventListener("popupshowing", function showing() {
|
||||
popup.removeEventListener("popupshowing", showing, false);
|
||||
|
||||
let entries = getMenuEntries(searchBar);
|
||||
for (let i = 0; i < entries.length; i++) {
|
||||
isnot(entries[i], "private test",
|
||||
"shouldn't see private autocomplete entries");
|
||||
}
|
||||
|
||||
searchBar.textbox.toggleHistoryPopup();
|
||||
searchBar.value = "";
|
||||
aCallback();
|
||||
}, false);
|
||||
|
||||
let popupPromise = BrowserTestUtils.waitForEvent(popup, "popupshown");
|
||||
searchBar.textbox.showHistoryPopup();
|
||||
}
|
||||
yield popupPromise;
|
||||
|
||||
let entries = getMenuEntries(searchBar);
|
||||
for (let i = 0; i < entries.length; i++) {
|
||||
isnot(entries[i], "private test",
|
||||
"shouldn't see private autocomplete entries");
|
||||
}
|
||||
|
||||
searchBar.textbox.toggleHistoryPopup();
|
||||
searchBar.value = "";
|
||||
|
||||
windowsToClose.forEach(function(win) {
|
||||
win.close();
|
||||
});
|
||||
});
|
||||
|
||||
function getMenuEntries(searchBar) {
|
||||
let entries = [];
|
||||
|
@ -381,20 +381,8 @@ add_task(function* test_tab_and_arrows() {
|
||||
});
|
||||
|
||||
add_task(function* test_open_search() {
|
||||
let tab = gBrowser.addTab();
|
||||
gBrowser.selectedTab = tab;
|
||||
|
||||
let deferred = Promise.defer();
|
||||
let browser = gBrowser.selectedBrowser;
|
||||
browser.addEventListener("load", function onload() {
|
||||
browser.removeEventListener("load", onload, true);
|
||||
deferred.resolve();
|
||||
}, true);
|
||||
|
||||
let rootDir = getRootDirectory(gTestPath);
|
||||
content.location = rootDir + "opensearch.html";
|
||||
|
||||
yield deferred.promise;
|
||||
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, rootDir + "opensearch.html");
|
||||
|
||||
let promise = promiseEvent(searchPopup, "popupshown");
|
||||
info("Opening search panel");
|
||||
|
@ -413,7 +413,7 @@ add_no_popup_task(function* search_go_doesnt_open_popup() {
|
||||
textbox.value = "foo";
|
||||
searchbar.updateGoButtonVisibility();
|
||||
|
||||
let promise = promiseOnLoad();
|
||||
let promise = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
|
||||
EventUtils.synthesizeMouseAtCenter(goButton, {});
|
||||
yield promise;
|
||||
|
||||
|
@ -309,20 +309,8 @@ add_task(function* test_tab_and_arrows() {
|
||||
});
|
||||
|
||||
add_task(function* test_open_search() {
|
||||
let tab = gBrowser.addTab();
|
||||
gBrowser.selectedTab = tab;
|
||||
|
||||
let deferred = Promise.defer();
|
||||
let browser = gBrowser.selectedBrowser;
|
||||
browser.addEventListener("load", function onload() {
|
||||
browser.removeEventListener("load", onload, true);
|
||||
deferred.resolve();
|
||||
}, true);
|
||||
|
||||
let rootDir = getRootDirectory(gTestPath);
|
||||
content.location = rootDir + "opensearch.html";
|
||||
|
||||
yield deferred.promise;
|
||||
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, rootDir + "opensearch.html");
|
||||
|
||||
let promise = promiseEvent(searchPopup, "popupshown");
|
||||
info("Opening search panel");
|
||||
|
@ -136,6 +136,9 @@ function test() {
|
||||
if (!(flags & docStart) || !webProgress.isTopLevel)
|
||||
return;
|
||||
|
||||
if (req.originalURI.spec == "about:blank")
|
||||
return;
|
||||
|
||||
info("received document start");
|
||||
|
||||
ok(req instanceof Ci.nsIChannel, "req is a channel");
|
||||
|
@ -1,20 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
|
||||
"resource://gre/modules/Promise.jsm");
|
||||
|
||||
function whenNewWindowLoaded(aOptions, aCallback) {
|
||||
let win = OpenBrowserWindow(aOptions);
|
||||
let focused = SimpleTest.promiseFocus(win);
|
||||
let startupFinished = TestUtils.topicObserved("browser-delayed-startup-finished",
|
||||
subject => subject == win).then(() => win);
|
||||
Promise.all([focused, startupFinished])
|
||||
.then(results => executeSoon(() => aCallback(results[1])));
|
||||
|
||||
return win;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively compare two objects and check that every property of expectedObj has the same value
|
||||
* on actualObj.
|
||||
@ -53,64 +39,16 @@ function getLocalizedPref(aPrefName, aDefault) {
|
||||
return aDefault;
|
||||
}
|
||||
|
||||
function waitForPopupShown(aPopupId, aCallback) {
|
||||
let popup = document.getElementById(aPopupId);
|
||||
info("waitForPopupShown: got popup: " + popup.id);
|
||||
function onPopupShown() {
|
||||
info("onPopupShown");
|
||||
removePopupShownListener();
|
||||
SimpleTest.executeSoon(aCallback);
|
||||
}
|
||||
function removePopupShownListener() {
|
||||
popup.removeEventListener("popupshown", onPopupShown);
|
||||
}
|
||||
popup.addEventListener("popupshown", onPopupShown);
|
||||
registerCleanupFunction(removePopupShownListener);
|
||||
}
|
||||
|
||||
function promiseEvent(aTarget, aEventName, aPreventDefault) {
|
||||
let deferred = Promise.defer();
|
||||
aTarget.addEventListener(aEventName, function onEvent(aEvent) {
|
||||
aTarget.removeEventListener(aEventName, onEvent, true);
|
||||
function cancelEvent(event) {
|
||||
if (aPreventDefault) {
|
||||
aEvent.preventDefault();
|
||||
event.preventDefault();
|
||||
}
|
||||
deferred.resolve();
|
||||
}, true);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function waitForBrowserContextMenu(aCallback) {
|
||||
waitForPopupShown(gBrowser.selectedBrowser.contextMenu, aCallback);
|
||||
}
|
||||
|
||||
function doOnloadOnce(aCallback) {
|
||||
function doOnloadOnceListener(aEvent) {
|
||||
info("doOnloadOnce: " + aEvent.originalTarget.location);
|
||||
removeDoOnloadOnceListener();
|
||||
SimpleTest.executeSoon(function doOnloadOnceCallback() {
|
||||
aCallback(aEvent);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
function removeDoOnloadOnceListener() {
|
||||
gBrowser.removeEventListener("load", doOnloadOnceListener, true);
|
||||
}
|
||||
gBrowser.addEventListener("load", doOnloadOnceListener, true);
|
||||
registerCleanupFunction(removeDoOnloadOnceListener);
|
||||
}
|
||||
|
||||
function* promiseOnLoad() {
|
||||
return new Promise(resolve => {
|
||||
gBrowser.addEventListener("load", function onLoadListener(aEvent) {
|
||||
let cw = aEvent.target.defaultView;
|
||||
let tab = gBrowser._getTabForContentWindow(cw);
|
||||
if (tab) {
|
||||
info("onLoadListener: " + aEvent.originalTarget.location);
|
||||
gBrowser.removeEventListener("load", onLoadListener, true);
|
||||
resolve(aEvent);
|
||||
}
|
||||
}, true);
|
||||
});
|
||||
return BrowserTestUtils.waitForEvent(aTarget, aEventName, false, cancelEvent);
|
||||
}
|
||||
|
||||
function promiseNewEngine(basename, options = {}) {
|
||||
@ -123,7 +61,7 @@ function promiseNewEngine(basename, options = {}) {
|
||||
onInitComplete: function() {
|
||||
let url = getRootDirectory(gTestPath) + basename;
|
||||
let current = Services.search.currentEngine;
|
||||
Services.search.addEngine(url, null, "", false, {
|
||||
Services.search.addEngine(url, null, options.iconURL || "", false, {
|
||||
onSuccess: function (engine) {
|
||||
info("Search engine added: " + basename);
|
||||
if (setAsCurrent) {
|
||||
|
@ -96,9 +96,6 @@ const MIN_VISIBLE_HISTORY_TILES = 8;
|
||||
// The max number of visible (not blocked) history tiles to test for inadjacency
|
||||
const MAX_VISIBLE_HISTORY_TILES = 15;
|
||||
|
||||
// Divide frecency by this amount for pings
|
||||
const PING_SCORE_DIVISOR = 10000;
|
||||
|
||||
// Allowed ping actions remotely stored as columns: case-insensitive [a-z0-9_]
|
||||
const PING_ACTIONS = ["block", "click", "pin", "sponsored", "sponsored_link", "unpin", "view"];
|
||||
|
||||
@ -566,50 +563,13 @@ var DirectoryLinksProvider = {
|
||||
}
|
||||
catch (ex) {}
|
||||
|
||||
// Only send pings when enhancing tiles with an endpoint and valid action
|
||||
// Bug 1240245 - We no longer send pings, but frequency capping and fetching
|
||||
// tests depend on the following actions, so references to PING remain.
|
||||
let invalidAction = PING_ACTIONS.indexOf(action) == -1;
|
||||
if (!newtabEnhanced || pingEndPoint == "" || invalidAction) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
let actionIndex;
|
||||
let data = {
|
||||
locale: this.locale,
|
||||
tiles: sites.reduce((tiles, site, pos) => {
|
||||
// Only add data for non-empty tiles
|
||||
if (site) {
|
||||
// Remember which tiles data triggered the action
|
||||
let {link} = site;
|
||||
let tilesIndex = tiles.length;
|
||||
if (triggeringSiteIndex == pos) {
|
||||
actionIndex = tilesIndex;
|
||||
}
|
||||
|
||||
// Make the payload in a way so keys can be excluded when stringified
|
||||
let id = link.directoryId;
|
||||
tiles.push({
|
||||
id: id || site.enhancedId,
|
||||
pin: site.isPinned() ? 1 : undefined,
|
||||
pos: pos != tilesIndex ? pos : undefined,
|
||||
past_impressions: pos == triggeringSiteIndex ? pastImpressions : undefined,
|
||||
score: Math.round(link.frecency / PING_SCORE_DIVISOR) || undefined,
|
||||
url: site.enhancedId && "",
|
||||
});
|
||||
}
|
||||
return tiles;
|
||||
}, []),
|
||||
};
|
||||
|
||||
// Provide a direct index to the tile triggering the action
|
||||
if (actionIndex !== undefined) {
|
||||
data[action] = actionIndex;
|
||||
}
|
||||
|
||||
// Package the data to be sent with the ping
|
||||
let ping = this._newXHR();
|
||||
ping.open("POST", pingEndPoint + (action == "view" ? "view" : "click"));
|
||||
ping.send(JSON.stringify(data));
|
||||
|
||||
return Task.spawn(function* () {
|
||||
// since we updated views/clicks we need write _frequencyCaps to disk
|
||||
yield this._writeFrequencyCapFile();
|
||||
|
@ -371,8 +371,6 @@ function TabWindow(win) {
|
||||
this.win = win;
|
||||
this.tabbrowser = win.gBrowser;
|
||||
|
||||
this.cacheDims();
|
||||
|
||||
this.previews = new Map();
|
||||
|
||||
for (let i = 0; i < this.tabEvents.length; i++)
|
||||
@ -394,6 +392,8 @@ function TabWindow(win) {
|
||||
|
||||
TabWindow.prototype = {
|
||||
_enabled: false,
|
||||
_cachedWidth: 0,
|
||||
_cachedHeight: 0,
|
||||
tabEvents: ["TabOpen", "TabClose", "TabSelect", "TabMove"],
|
||||
winEvents: ["resize"],
|
||||
|
||||
@ -404,8 +404,8 @@ TabWindow.prototype = {
|
||||
|
||||
this.tabbrowser.removeTabsProgressListener(this);
|
||||
|
||||
for (let i = 0; i < this.winEvents.length; i++)
|
||||
this.win.removeEventListener(this.winEvents[i], this, false);
|
||||
for (let i = 0; i < this.winEvents.length; i++)
|
||||
this.win.removeEventListener(this.winEvents[i], this, false);
|
||||
|
||||
for (let i = 0; i < this.tabEvents.length; i++)
|
||||
this.tabbrowser.tabContainer.removeEventListener(this.tabEvents[i], this, false);
|
||||
|
@ -716,113 +716,6 @@ add_task(function* test_frequencyCappedSites_click() {
|
||||
Services.prefs.setCharPref(kPingUrlPref, kPingUrl);
|
||||
});
|
||||
|
||||
add_task(function* test_reportSitesAction() {
|
||||
yield DirectoryLinksProvider.init();
|
||||
let deferred, expectedPath, expectedPost;
|
||||
let done = false;
|
||||
server.registerPrefixHandler(kPingPath, (aRequest, aResponse) => {
|
||||
if (done) {
|
||||
return;
|
||||
}
|
||||
|
||||
do_check_eq(aRequest.path, expectedPath);
|
||||
|
||||
let bodyStream = new BinaryInputStream(aRequest.bodyInputStream);
|
||||
let bodyObject = JSON.parse(NetUtil.readInputStreamToString(bodyStream, bodyStream.available()));
|
||||
isIdentical(bodyObject, expectedPost);
|
||||
|
||||
deferred.resolve();
|
||||
});
|
||||
|
||||
function sendPingAndTest(path, action, index) {
|
||||
deferred = Promise.defer();
|
||||
expectedPath = kPingPath + path;
|
||||
DirectoryLinksProvider.reportSitesAction(sites, action, index);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
// Start with a single pinned link at position 3
|
||||
let sites = [,,{
|
||||
isPinned: _ => true,
|
||||
link: {
|
||||
directoryId: 1,
|
||||
frecency: 30000,
|
||||
url: "http://directory1/",
|
||||
},
|
||||
}];
|
||||
|
||||
// Make sure we get the click ping for the directory link with fields we want
|
||||
// and unwanted fields removed by stringify/parse
|
||||
expectedPost = JSON.parse(JSON.stringify({
|
||||
click: 0,
|
||||
locale: "en-US",
|
||||
tiles: [{
|
||||
id: 1,
|
||||
pin: 1,
|
||||
pos: 2,
|
||||
score: 3,
|
||||
url: undefined,
|
||||
}],
|
||||
}));
|
||||
yield sendPingAndTest("click", "click", 2);
|
||||
|
||||
// Try a pin click ping
|
||||
delete expectedPost.click;
|
||||
expectedPost.pin = 0;
|
||||
yield sendPingAndTest("click", "pin", 2);
|
||||
|
||||
// Try a block click ping
|
||||
delete expectedPost.pin;
|
||||
expectedPost.block = 0;
|
||||
yield sendPingAndTest("click", "block", 2);
|
||||
|
||||
// A view ping has no actions
|
||||
delete expectedPost.block;
|
||||
expectedPost.view = 0;
|
||||
yield sendPingAndTest("view", "view", 2);
|
||||
|
||||
// Remove the identifier that makes it a directory link so just plain history
|
||||
delete sites[2].link.directoryId;
|
||||
delete expectedPost.tiles[0].id;
|
||||
yield sendPingAndTest("view", "view", 2);
|
||||
|
||||
// Add directory link at position 0
|
||||
sites[0] = {
|
||||
isPinned: _ => false,
|
||||
link: {
|
||||
directoryId: 1234,
|
||||
frecency: 1000,
|
||||
url: "http://directory/",
|
||||
}
|
||||
};
|
||||
expectedPost.tiles.unshift(JSON.parse(JSON.stringify({
|
||||
id: 1234,
|
||||
pin: undefined,
|
||||
pos: undefined,
|
||||
score: undefined,
|
||||
url: undefined,
|
||||
})));
|
||||
expectedPost.view = 1;
|
||||
yield sendPingAndTest("view", "view", 2);
|
||||
|
||||
// Make the history tile enhanced so it reports both id and url
|
||||
sites[2].enhancedId = "id from enhanced";
|
||||
expectedPost.tiles[1].id = "id from enhanced";
|
||||
expectedPost.tiles[1].url = "";
|
||||
yield sendPingAndTest("view", "view", 2);
|
||||
|
||||
// Click the 0th site / 0th tile
|
||||
delete expectedPost.view;
|
||||
expectedPost.click = 0;
|
||||
yield sendPingAndTest("click", "click", 0);
|
||||
|
||||
// Click the 2th site / 1th tile
|
||||
expectedPost.click = 1;
|
||||
yield sendPingAndTest("click", "click", 2);
|
||||
|
||||
done = true;
|
||||
});
|
||||
|
||||
add_task(function* test_fetchAndCacheLinks_local() {
|
||||
yield DirectoryLinksProvider.init();
|
||||
yield cleanJsonFile();
|
||||
@ -1901,110 +1794,6 @@ add_task(function* test_inadjecentSites() {
|
||||
yield promiseCleanDirectoryLinksProvider();
|
||||
});
|
||||
|
||||
add_task(function* test_reportPastImpressions() {
|
||||
let origIsTopPlacesSite = NewTabUtils.isTopPlacesSite;
|
||||
NewTabUtils.isTopPlacesSite = () => true;
|
||||
let origCurrentTopSiteCount = DirectoryLinksProvider._getCurrentTopSiteCount;
|
||||
DirectoryLinksProvider._getCurrentTopSiteCount = () => 8;
|
||||
|
||||
let testUrl = "http://frequency.capped/link";
|
||||
let targets = ["top.site.com"];
|
||||
let data = {
|
||||
suggested: [{
|
||||
type: "affiliate",
|
||||
frecent_sites: targets,
|
||||
url: testUrl,
|
||||
adgroup_name: "Test"
|
||||
}]
|
||||
};
|
||||
let dataURI = "data:application/json," + JSON.stringify(data);
|
||||
yield promiseSetupDirectoryLinksProvider({linksURL: dataURI});
|
||||
|
||||
// make DirectoryLinksProvider load json
|
||||
let loadPromise = Promise.defer();
|
||||
DirectoryLinksProvider.getLinks(_ => {loadPromise.resolve();});
|
||||
yield loadPromise.promise;
|
||||
|
||||
// setup ping handler
|
||||
let deferred, expectedPath, expectedAction, expectedImpressions;
|
||||
let done = false;
|
||||
server.registerPrefixHandler(kPingPath, (aRequest, aResponse) => {
|
||||
if (done) {
|
||||
return;
|
||||
}
|
||||
|
||||
do_check_eq(aRequest.path, expectedPath);
|
||||
|
||||
let bodyStream = new BinaryInputStream(aRequest.bodyInputStream);
|
||||
let bodyObject = JSON.parse(NetUtil.readInputStreamToString(bodyStream, bodyStream.available()));
|
||||
let expectedActionIndex = bodyObject[expectedAction];
|
||||
if (bodyObject.unpin) {
|
||||
// unpin should not report past_impressions
|
||||
do_check_false(bodyObject.tiles[expectedActionIndex].hasOwnProperty("past_impressions"));
|
||||
}
|
||||
else if (expectedImpressions) {
|
||||
do_check_eq(bodyObject.tiles[expectedActionIndex].past_impressions.total, expectedImpressions);
|
||||
do_check_eq(bodyObject.tiles[expectedActionIndex].past_impressions.daily, expectedImpressions);
|
||||
}
|
||||
else {
|
||||
do_check_eq(expectedPath, "/ping/view");
|
||||
do_check_false(bodyObject.tiles[expectedActionIndex].hasOwnProperty("past_impressions"));
|
||||
}
|
||||
|
||||
deferred.resolve();
|
||||
});
|
||||
|
||||
// setup ping sender
|
||||
function sendPingAndTest(path, action, index) {
|
||||
deferred = Promise.defer();
|
||||
expectedPath = kPingPath + path;
|
||||
expectedAction = action;
|
||||
DirectoryLinksProvider.reportSitesAction(sites, action, index);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
// Start with a view ping first
|
||||
let site = {
|
||||
isPinned: _ => false,
|
||||
link: {
|
||||
directoryId: 1,
|
||||
frecency: 30000,
|
||||
frecent_sites: targets,
|
||||
targetedSite: targets[0],
|
||||
url: testUrl
|
||||
}
|
||||
};
|
||||
let sites = [,
|
||||
{
|
||||
isPinned: _ => false,
|
||||
link: {type: "history", url: "https://foo.com"}
|
||||
},
|
||||
site
|
||||
];
|
||||
|
||||
yield sendPingAndTest("view", "view", 2);
|
||||
yield sendPingAndTest("view", "view", 2);
|
||||
yield sendPingAndTest("view", "view", 2);
|
||||
|
||||
expectedImpressions = DirectoryLinksProvider._frequencyCaps[testUrl].totalViews;
|
||||
do_check_eq(expectedImpressions, 3);
|
||||
|
||||
// now report pin, unpin, block and click
|
||||
sites.isPinned = _ => true;
|
||||
yield sendPingAndTest("click", "pin", 2);
|
||||
sites.isPinned = _ => false;
|
||||
yield sendPingAndTest("click", "unpin", 2);
|
||||
sites.isPinned = _ => false;
|
||||
yield sendPingAndTest("click", "click", 2);
|
||||
sites.isPinned = _ => false;
|
||||
yield sendPingAndTest("click", "block", 2);
|
||||
|
||||
// Cleanup.
|
||||
done = true;
|
||||
NewTabUtils.isTopPlacesSite = origIsTopPlacesSite;
|
||||
DirectoryLinksProvider._getCurrentTopSiteCount = origCurrentTopSiteCount;
|
||||
});
|
||||
|
||||
add_task(function* test_blockSuggestedTiles() {
|
||||
// Initial setup
|
||||
let suggestedTile = suggestedTile1;
|
||||
|
@ -231,7 +231,7 @@ define([MOZ_BUILD_BACKEND],
|
||||
BUILD_BACKENDS="RecursiveMake"
|
||||
|
||||
MOZ_ARG_ENABLE_STRING(build-backend,
|
||||
[ --enable-build-backend={AndroidEclipse,CppEclipse,VisualStudio,FasterMake,CompileDB,ChromeMap}
|
||||
[ --enable-build-backend={$($(dirname ]$[0)/$1/mach python -c "from mozbuild.backend import backends; print ','.join(sorted(backends))")}
|
||||
Enable additional build backends],
|
||||
[ BUILD_BACKENDS="RecursiveMake `echo $enableval | sed 's/,/ /g'`"])
|
||||
|
||||
|
@ -258,7 +258,10 @@ Elf::Elf(std::ifstream &file)
|
||||
segment->addSection(sections[j]);
|
||||
// Make sure that our view of segments corresponds to the original
|
||||
// ELF file.
|
||||
assert(segment->getFileSize() == phdr.p_filesz);
|
||||
// GNU gold likes to start some segments before the first section
|
||||
// they contain. https://sourceware.org/bugzilla/show_bug.cgi?id=19392
|
||||
unsigned int gold_adjustment = segment->getAddr() - phdr.p_vaddr;
|
||||
assert(segment->getFileSize() == phdr.p_filesz - gold_adjustment);
|
||||
// gold makes TLS segments end on an aligned virtual address, even
|
||||
// when the underlying section ends before that, while bfd ld
|
||||
// doesn't. It's fine if we don't keep that alignment.
|
||||
@ -267,7 +270,7 @@ Elf::Elf(std::ifstream &file)
|
||||
unsigned int align = segment->getAlign();
|
||||
memsize = (memsize + align - 1) & ~(align - 1);
|
||||
}
|
||||
assert(memsize == phdr.p_memsz);
|
||||
assert(memsize == phdr.p_memsz - gold_adjustment);
|
||||
segments.push_back(segment);
|
||||
}
|
||||
|
||||
|
5
config/external/nss/nss.symbols
vendored
5
config/external/nss/nss.symbols
vendored
@ -692,6 +692,11 @@ VFY_VerifyDataWithAlgorithmID
|
||||
VFY_VerifyDigestDirect
|
||||
_SGN_VerifyPKCS1DigestInfo
|
||||
__PK11_SetCertificateNickname
|
||||
# These symbols are not used by Firefox itself, but are used by Java's security
|
||||
# libraries, which in turn are used by Java applets/plugins/etc. Provide them
|
||||
# to make Java code happy.
|
||||
NSS_VersionCheck
|
||||
NSS_Initialize
|
||||
#ifdef NSS_EXTRA_SYMBOLS_FILE
|
||||
#include @NSS_EXTRA_SYMBOLS_FILE@
|
||||
#endif
|
||||
|
@ -1581,7 +1581,3 @@ include $(MOZILLA_DIR)/config/makefiles/autotargets.mk
|
||||
ifneq ($(NULL),$(AUTO_DEPS))
|
||||
default all libs tools export:: $(AUTO_DEPS)
|
||||
endif
|
||||
|
||||
export:: $(GENERATED_FILES)
|
||||
|
||||
GARBAGE += $(GENERATED_FILES)
|
||||
|
@ -139,7 +139,7 @@ DIST="$MOZ_BUILD_ROOT/dist"
|
||||
|
||||
MOZ_PYTHON
|
||||
|
||||
MOZ_BUILD_BACKEND
|
||||
MOZ_BUILD_BACKEND(.)
|
||||
|
||||
MOZ_DEFAULT_COMPILER
|
||||
|
||||
@ -2288,6 +2288,11 @@ ia64*-hpux*)
|
||||
# At least one MSVC header and several headers in-tree have
|
||||
# unused typedefs, so turn this on.
|
||||
CXXFLAGS="$CXXFLAGS -Wno-unused-local-typedef"
|
||||
# Several JS engine header files use __declspec(dllimport) on
|
||||
# classes, and clang-cl helpfully warns about its non-support
|
||||
# for such cases. We're not particularly worried about that,
|
||||
# so ignore that warning.
|
||||
CXXFLAGS="$CXXFLAGS -Wno-ignored-attributes"
|
||||
fi
|
||||
# make 'foo == bar;' error out
|
||||
CFLAGS="$CFLAGS -we4553"
|
||||
|
@ -70,6 +70,9 @@ function BrowserLoader(baseURI, window) {
|
||||
return require(uri);
|
||||
},
|
||||
globals: {
|
||||
// Allow modules to use the window's console to ensure logs appear in a
|
||||
// tab toolbox, if one exists, instead of just the browser console.
|
||||
console: window.console,
|
||||
// Make sure 'define' function exists. This allows reusing AMD modules.
|
||||
define: function(callback) {
|
||||
callback(this.require, this.exports, this.module);
|
||||
|
@ -9,10 +9,12 @@
|
||||
|
||||
DEF_TEST(DoesCrossZoneBoundaries, {
|
||||
// Create a new global to get a new zone.
|
||||
JS::CompartmentOptions options;
|
||||
JS::RootedObject newGlobal(cx, JS_NewGlobalObject(cx,
|
||||
getGlobalClass(),
|
||||
nullptr,
|
||||
JS::FireOnNewGlobalHook));
|
||||
JS::FireOnNewGlobalHook,
|
||||
options));
|
||||
ASSERT_TRUE(newGlobal);
|
||||
JS::Zone* newZone = nullptr;
|
||||
{
|
||||
|
@ -9,10 +9,12 @@
|
||||
|
||||
DEF_TEST(DoesntCrossZoneBoundaries, {
|
||||
// Create a new global to get a new zone.
|
||||
JS::CompartmentOptions options;
|
||||
JS::RootedObject newGlobal(cx, JS_NewGlobalObject(cx,
|
||||
getGlobalClass(),
|
||||
nullptr,
|
||||
JS::FireOnNewGlobalHook));
|
||||
JS::FireOnNewGlobalHook,
|
||||
options));
|
||||
ASSERT_TRUE(newGlobal);
|
||||
JS::Zone* newZone = nullptr;
|
||||
{
|
||||
|
@ -143,9 +143,10 @@ EffectCompositor::RequestRestyle(dom::Element* aElement,
|
||||
auto& elementsToRestyle = mElementsToRestyle[aCascadeLevel];
|
||||
PseudoElementHashKey key = { aElement, aPseudoType };
|
||||
|
||||
if (aRestyleType == RestyleType::Throttled &&
|
||||
!elementsToRestyle.Contains(key)) {
|
||||
elementsToRestyle.Put(key, false);
|
||||
if (aRestyleType == RestyleType::Throttled) {
|
||||
if (!elementsToRestyle.Contains(key)) {
|
||||
elementsToRestyle.Put(key, false);
|
||||
}
|
||||
mPresContext->Document()->SetNeedStyleFlush();
|
||||
} else {
|
||||
// Get() returns 0 if the element is not found. It will also return
|
||||
|
@ -4,5 +4,6 @@ support-files =
|
||||
../../imptests/testharness.js
|
||||
../../imptests/testharnessreport.js
|
||||
[chrome/test_animation_observers.html]
|
||||
[chrome/test_restyles.html]
|
||||
[chrome/test_running_on_compositor.html]
|
||||
skip-if = buildapp == 'b2g'
|
||||
|
328
dom/animation/test/chrome/test_restyles.html
Normal file
328
dom/animation/test/chrome/test_restyles.html
Normal file
@ -0,0 +1,328 @@
|
||||
<!doctype html>
|
||||
<head>
|
||||
<meta charset=utf-8>
|
||||
<title>Tests restyles caused by animations</title>
|
||||
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script src="chrome://mochikit/content/tests/SimpleTest/SpawnTask.js"></script>
|
||||
<script src="chrome://mochikit/content/tests/SimpleTest/paint_listener.js"></script>
|
||||
<script src="../testcommon.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
|
||||
<style>
|
||||
@keyframes opacity {
|
||||
from { opacity: 1; }
|
||||
to { opacity: 0; }
|
||||
}
|
||||
@keyframes background-color {
|
||||
from { background-color: red; }
|
||||
to { background-color: blue; }
|
||||
}
|
||||
@keyframes rotate {
|
||||
from { transform: rotate(0deg); }
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
div {
|
||||
/* Element needs geometry to be eligible for layerization */
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background-color: white;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
function observeStyling(frameCount, onFrame) {
|
||||
var docShell = window.QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor)
|
||||
.getInterface(SpecialPowers.Ci.nsIWebNavigation)
|
||||
.QueryInterface(SpecialPowers.Ci.nsIDocShell);
|
||||
|
||||
docShell.recordProfileTimelineMarkers = true;
|
||||
docShell.popProfileTimelineMarkers();
|
||||
|
||||
return new Promise(function(resolve) {
|
||||
return waitForAnimationFrames(frameCount, onFrame).then(function() {
|
||||
var markers = docShell.popProfileTimelineMarkers();
|
||||
docShell.recordProfileTimelineMarkers = false;
|
||||
var stylingMarkers = markers.filter(function(marker, index) {
|
||||
return marker.name == 'Styles';
|
||||
});
|
||||
resolve(stylingMarkers);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
const OMTAPrefKey = 'layers.offmainthreadcomposition.async-animations';
|
||||
var omtaEnabled = SpecialPowers.DOMWindowUtils.layerManagerRemote &&
|
||||
SpecialPowers.getBoolPref(OMTAPrefKey);
|
||||
|
||||
function add_task_if_omta_enabled(test) {
|
||||
if (!omtaEnabled) {
|
||||
info(test.name + " is skipped because OMTA is disabled");
|
||||
return;
|
||||
}
|
||||
add_task(test);
|
||||
}
|
||||
|
||||
// We need to wait for all paints before running tests to avoid contaminations
|
||||
// from styling of this document itself.
|
||||
waitForAllPaints(function() {
|
||||
add_task_if_omta_enabled(function* no_restyling_for_compositor_animations() {
|
||||
var div = addDiv(null, { style: 'animation: opacity 100s' });
|
||||
var animation = div.getAnimations()[0];
|
||||
|
||||
yield animation.ready;
|
||||
ok(animation.isRunningOnCompositor);
|
||||
|
||||
var markers = yield observeStyling(5);
|
||||
is(markers.length, 0,
|
||||
'CSS animations running on the compositor should not update style ' +
|
||||
'on the main thread');
|
||||
div.remove(div);
|
||||
});
|
||||
|
||||
add_task_if_omta_enabled(function* no_restyling_for_compositor_transitions() {
|
||||
var div = addDiv(null, { style: 'transition: opacity 100s; opacity: 0' });
|
||||
getComputedStyle(div).opacity;
|
||||
div.style.opacity = 1;
|
||||
|
||||
var animation = div.getAnimations()[0];
|
||||
|
||||
yield animation.ready;
|
||||
ok(animation.isRunningOnCompositor);
|
||||
|
||||
var markers = yield observeStyling(5);
|
||||
is(markers.length, 0,
|
||||
'CSS transitions running on the compositor should not update style ' +
|
||||
'on the main thread');
|
||||
div.remove(div);
|
||||
});
|
||||
|
||||
add_task_if_omta_enabled(function* no_restyling_when_animation_duration_is_changed() {
|
||||
var div = addDiv(null, { style: 'animation: opacity 100s' });
|
||||
var animation = div.getAnimations()[0];
|
||||
|
||||
yield animation.ready;
|
||||
ok(animation.isRunningOnCompositor);
|
||||
|
||||
div.animationDuration = '200s';
|
||||
|
||||
var markers = yield observeStyling(5);
|
||||
is(markers.length, 0,
|
||||
'Animations running on the compositor should not update style ' +
|
||||
'on the main thread');
|
||||
div.remove(div);
|
||||
});
|
||||
|
||||
add_task_if_omta_enabled(function* only_one_restyling_after_finish_is_called() {
|
||||
var div = addDiv(null, { style: 'animation: opacity 100s' });
|
||||
var animation = div.getAnimations()[0];
|
||||
|
||||
yield animation.ready;
|
||||
ok(animation.isRunningOnCompositor);
|
||||
|
||||
animation.finish();
|
||||
|
||||
var markers = yield observeStyling(5);
|
||||
is(markers.length, 1,
|
||||
'Animations running on the compositor should only update style ' +
|
||||
'once after finish() is called');
|
||||
div.remove(div);
|
||||
});
|
||||
|
||||
add_task(function* no_restyling_mouse_movement_on_finished_transition() {
|
||||
var div = addDiv(null, { style: 'transition: opacity 1ms; opacity: 0' });
|
||||
getComputedStyle(div).opacity;
|
||||
div.style.opacity = 1;
|
||||
|
||||
var animation = div.getAnimations()[0];
|
||||
var initialRect = div.getBoundingClientRect();
|
||||
|
||||
yield animation.finished;
|
||||
|
||||
var mouseX = initialRect.left + initialRect.width / 2;
|
||||
var mouseY = initialRect.top + initialRect.height / 2;
|
||||
var markers = yield observeStyling(5, function() {
|
||||
// We can't use synthesizeMouse here since synthesizeMouse causes
|
||||
// layout flush.
|
||||
synthesizeMouseAtPoint(mouseX++, mouseY++,
|
||||
{ type: 'mousemove' }, window);
|
||||
});
|
||||
|
||||
is(markers.length, 0,
|
||||
'Bug 1219236: Finished transitions should never cause restyles ' +
|
||||
'when mouse is moved on the animations');
|
||||
div.remove(div);
|
||||
});
|
||||
|
||||
add_task(function* no_restyling_mouse_movement_on_finished_animation() {
|
||||
var div = addDiv(null, { style: 'animation: opacity 1ms' });
|
||||
var animation = div.getAnimations()[0];
|
||||
|
||||
var initialRect = div.getBoundingClientRect();
|
||||
|
||||
yield animation.finished;
|
||||
|
||||
var mouseX = initialRect.left + initialRect.width / 2;
|
||||
var mouseY = initialRect.top + initialRect.height / 2;
|
||||
var markers = yield observeStyling(5, function() {
|
||||
// We can't use synthesizeMouse here since synthesizeMouse causes
|
||||
// layout flush.
|
||||
synthesizeMouseAtPoint(mouseX++, mouseY++,
|
||||
{ type: 'mousemove' }, window);
|
||||
});
|
||||
|
||||
is(markers.length, 0,
|
||||
'Bug 1219236: Finished animations should never cause restyles ' +
|
||||
'when mouse is moved on the animations');
|
||||
div.remove(div);
|
||||
});
|
||||
|
||||
add_task_if_omta_enabled(function* no_restyling_compositor_animations_out_of_view_element() {
|
||||
var div = addDiv(null,
|
||||
{ style: 'animation: opacity 100s; transform: translateY(-400px);' });
|
||||
var animation = div.getAnimations()[0];
|
||||
|
||||
yield animation.ready;
|
||||
ok(!animation.isRunningOnCompositor);
|
||||
|
||||
var markers = yield observeStyling(5);
|
||||
|
||||
todo_is(markers.length, 0,
|
||||
'Bug 1166500: Animations running on the compositor in out of ' +
|
||||
'view element should never cause restyles');
|
||||
div.remove(div);
|
||||
});
|
||||
|
||||
add_task(function* no_restyling_main_thread_animations_out_of_view_element() {
|
||||
var div = addDiv(null,
|
||||
{ style: 'animation: background-color 100s; transform: translateY(-400px);' });
|
||||
var animation = div.getAnimations()[0];
|
||||
|
||||
yield animation.ready;
|
||||
var markers = yield observeStyling(5);
|
||||
|
||||
todo_is(markers.length, 0,
|
||||
'Bug 1166500: Animations running on the main-thread in out of ' +
|
||||
'view element should never cause restyles');
|
||||
div.remove(div);
|
||||
});
|
||||
|
||||
/*
|
||||
Disabled for now since, on Android, the opacity animation runs on the
|
||||
compositor even if it is scrolled out of view.
|
||||
We will fix this in bug 1166500 or a follow-up bug
|
||||
add_task_if_omta_enabled(function* no_restyling_compositor_animations_in_scrolled_out_element() {
|
||||
var parentElement = addDiv(null,
|
||||
{ style: 'overflow-y: scroll; height: 20px;' });
|
||||
var div = addDiv(null,
|
||||
{ style: 'animation: opacity 100s; position: relative; top: 100px;' });
|
||||
parentElement.appendChild(div);
|
||||
var animation = div.getAnimations()[0];
|
||||
|
||||
yield animation.ready;
|
||||
ok(!animation.isRunningOnCompositor);
|
||||
|
||||
var markers = yield observeStyling(5);
|
||||
|
||||
todo_is(markers.length, 0,
|
||||
'Bug 1166500: Animations running on the compositor in elements ' +
|
||||
'which are scrolled out should never cause restyles');
|
||||
parentElement.remove(div);
|
||||
});
|
||||
*/
|
||||
|
||||
add_task(function* no_restyling_main_thread_animations_in_scrolled_out_element() {
|
||||
var parentElement = addDiv(null,
|
||||
{ style: 'overflow-y: scroll; height: 20px;' });
|
||||
var div = addDiv(null,
|
||||
{ style: 'animation: background-color 100s; position: relative; top: 100px;' });
|
||||
parentElement.appendChild(div);
|
||||
var animation = div.getAnimations()[0];
|
||||
|
||||
yield animation.ready;
|
||||
var markers = yield observeStyling(5);
|
||||
|
||||
todo_is(markers.length, 0,
|
||||
'Bug 1166500: Animations running on the main-thread in elements ' +
|
||||
'which are scrolled out should never cause restyles');
|
||||
parentElement.remove(div);
|
||||
});
|
||||
|
||||
/*
|
||||
Disabled for now since, on Android and B2G, the opacity animation runs on the
|
||||
compositor even if the associated element has visibility:hidden.
|
||||
We will fix this in bug 1237454 or a follow-up bug.
|
||||
add_task_if_omta_enabled(function* no_restyling_compositor_animations_in_visiblily_hidden_element() {
|
||||
var div = addDiv(null,
|
||||
{ style: 'animation: opacity 100s; visibility: hidden' });
|
||||
var animation = div.getAnimations()[0];
|
||||
|
||||
yield animation.ready;
|
||||
ok(!animation.isRunningOnCompositor);
|
||||
|
||||
var markers = yield observeStyling(5);
|
||||
|
||||
todo_is(markers.length, 0,
|
||||
'Bug 1237454: Animations running on the compositor in ' +
|
||||
'visibility hidden element should never cause restyles');
|
||||
div.remove(div);
|
||||
});
|
||||
*/
|
||||
|
||||
add_task(function* no_restyling_main_thread_animations_in_visiblily_hidden_element() {
|
||||
var div = addDiv(null,
|
||||
{ style: 'animation: background-color 100s; visibility: hidden' });
|
||||
var animation = div.getAnimations()[0];
|
||||
|
||||
yield animation.ready;
|
||||
var markers = yield observeStyling(5);
|
||||
|
||||
todo_is(markers.length, 0,
|
||||
'Bug 1237454: Animations running on the main-thread in ' +
|
||||
'visibility hidden element should never cause restyles');
|
||||
div.remove(div);
|
||||
});
|
||||
|
||||
add_task_if_omta_enabled(function* no_restyling_compositor_animations_after_pause_is_called() {
|
||||
var div = addDiv(null, { style: 'animation: opacity 100s' });
|
||||
var animation = div.getAnimations()[0];
|
||||
|
||||
yield animation.ready;
|
||||
ok(animation.isRunningOnCompositor);
|
||||
|
||||
animation.pause();
|
||||
|
||||
yield animation.ready;
|
||||
|
||||
var markers = yield observeStyling(5);
|
||||
is(markers.length, 0,
|
||||
'Bug 1232563: Paused animations running on the compositor should ' +
|
||||
'never cause restyles once after pause() is called');
|
||||
div.remove(div);
|
||||
});
|
||||
|
||||
add_task(function* no_restyling_matn_thread_animations_after_pause_is_called() {
|
||||
var div = addDiv(null, { style: 'animation: background-color 100s' });
|
||||
var animation = div.getAnimations()[0];
|
||||
|
||||
yield animation.ready;
|
||||
|
||||
animation.pause();
|
||||
|
||||
yield animation.ready;
|
||||
|
||||
var markers = yield observeStyling(5);
|
||||
is(markers.length, 0,
|
||||
'Bug 1232563: Paused animations running on the main-thread should ' +
|
||||
'never cause restyles after pause() is called');
|
||||
div.remove(div);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
@ -41,13 +41,19 @@ function waitForFrame() {
|
||||
/**
|
||||
* Returns a Promise that is resolved after the given number of consecutive
|
||||
* animation frames have occured (using requestAnimationFrame callbacks).
|
||||
*
|
||||
* @param frameCount The number of animation frames.
|
||||
* @param onFrame An optional function to be processed in each animation frame.
|
||||
*/
|
||||
function waitForAnimationFrames(frameCount) {
|
||||
function waitForAnimationFrames(frameCount, onFrame) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
function handleFrame() {
|
||||
if (--frameCount <= 0) {
|
||||
resolve();
|
||||
} else {
|
||||
if (onFrame && typeof onFrame === 'function') {
|
||||
onFrame();
|
||||
}
|
||||
window.requestAnimationFrame(handleFrame); // wait another frame
|
||||
}
|
||||
}
|
||||
|
@ -2051,7 +2051,7 @@ this.DOMApplicationRegistry = {
|
||||
Services.scriptSecurityManager.createCodebasePrincipal(appURI,
|
||||
{appId: aApp.localId});
|
||||
let cacheUpdate = updateSvc.scheduleAppUpdate(
|
||||
appcacheURI, docURI, principal, aApp.localId, false, aProfileDir);
|
||||
appcacheURI, docURI, principal, aProfileDir);
|
||||
|
||||
// We save the download details for potential further usage like
|
||||
// cancelling it.
|
||||
@ -2205,7 +2205,7 @@ this.DOMApplicationRegistry = {
|
||||
Services.scriptSecurityManager.createCodebasePrincipal(appURI,
|
||||
{appId: aApp.localId});
|
||||
updateSvc.checkForUpdate(Services.io.newURI(helper.fullAppcachePath(), null, null),
|
||||
principal, app.localId, false, updateObserver);
|
||||
principal, updateObserver);
|
||||
});
|
||||
return;
|
||||
}
|
||||
@ -2479,8 +2479,7 @@ this.DOMApplicationRegistry = {
|
||||
{appId: aApp.localId});
|
||||
|
||||
updateSvc.checkForUpdate(Services.io.newURI(manifest.fullAppcachePath(), null, null),
|
||||
principal, aApp.localId, false,
|
||||
(aSubject, aTopic, aData) => updateDeferred.resolve(aTopic));
|
||||
principal, (aSubject, aTopic, aData) => updateDeferred.resolve(aTopic));
|
||||
|
||||
let topic = yield updateDeferred.promise;
|
||||
|
||||
|
@ -142,7 +142,7 @@ private:
|
||||
DOMMatrixReadOnly& operator=(const DOMMatrixReadOnly&) = delete;
|
||||
};
|
||||
|
||||
class DOMMatrix final : public DOMMatrixReadOnly
|
||||
class DOMMatrix : public DOMMatrixReadOnly
|
||||
{
|
||||
public:
|
||||
explicit DOMMatrix(nsISupports* aParent)
|
||||
@ -244,8 +244,10 @@ public:
|
||||
DOMMatrix* SkewYSelf(double aSy);
|
||||
DOMMatrix* InvertSelf();
|
||||
DOMMatrix* SetMatrixValue(const nsAString& aTransformList, ErrorResult& aRv);
|
||||
private:
|
||||
protected:
|
||||
void Ensure3DMatrix();
|
||||
|
||||
virtual ~DOMMatrix() {}
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
@ -2915,7 +2915,7 @@ Element::PreHandleEventForLinks(EventChainPreVisitor& aVisitor)
|
||||
// Set the status bar similarly for mouseover and focus
|
||||
case eMouseOver:
|
||||
aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
|
||||
// FALL THROUGH
|
||||
MOZ_FALLTHROUGH;
|
||||
case eFocus: {
|
||||
InternalFocusEvent* focusEvent = aVisitor.mEvent->AsFocusEvent();
|
||||
if (!focusEvent || !focusEvent->isRefocus) {
|
||||
@ -2930,7 +2930,7 @@ Element::PreHandleEventForLinks(EventChainPreVisitor& aVisitor)
|
||||
}
|
||||
case eMouseOut:
|
||||
aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
|
||||
// FALL THROUGH
|
||||
MOZ_FALLTHROUGH;
|
||||
case eBlur:
|
||||
rv = LeaveLink(aVisitor.mPresContext);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
|
@ -958,23 +958,23 @@ BlobImplFile::LookupAndCacheIsDirectory()
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// BlobImplEmptyFile implementation
|
||||
// EmptyBlobImpl implementation
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED0(BlobImplEmptyFile, BlobImpl)
|
||||
NS_IMPL_ISUPPORTS_INHERITED0(EmptyBlobImpl, BlobImpl)
|
||||
|
||||
already_AddRefed<BlobImpl>
|
||||
BlobImplEmptyFile::CreateSlice(uint64_t aStart, uint64_t aLength,
|
||||
const nsAString& aContentType,
|
||||
ErrorResult& aRv)
|
||||
EmptyBlobImpl::CreateSlice(uint64_t aStart, uint64_t aLength,
|
||||
const nsAString& aContentType,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(!aStart && !aLength);
|
||||
RefPtr<BlobImpl> impl = new BlobImplEmptyFile(aContentType);
|
||||
RefPtr<BlobImpl> impl = new EmptyBlobImpl(aContentType);
|
||||
return impl.forget();
|
||||
}
|
||||
|
||||
void
|
||||
BlobImplEmptyFile::GetInternalStream(nsIInputStream** aStream,
|
||||
ErrorResult& aRv)
|
||||
EmptyBlobImpl::GetInternalStream(nsIInputStream** aStream,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
nsresult rv = NS_NewCStringInputStream(aStream, EmptyCString());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
|
@ -70,6 +70,7 @@ public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(Blob, nsIDOMBlob)
|
||||
|
||||
// This creates a Blob or a File based on the type of BlobImpl.
|
||||
static Blob*
|
||||
Create(nsISupports* aParent, BlobImpl* aImpl);
|
||||
|
||||
@ -833,13 +834,13 @@ private:
|
||||
bool mIsTemporary;
|
||||
};
|
||||
|
||||
class BlobImplEmptyFile final : public BlobImplBase
|
||||
class EmptyBlobImpl final : public BlobImplBase
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
explicit BlobImplEmptyFile(const nsAString& aContentType)
|
||||
: BlobImplBase(EmptyString(), aContentType, 0 /* aLength */)
|
||||
explicit EmptyBlobImpl(const nsAString& aContentType)
|
||||
: BlobImplBase(aContentType, 0 /* aLength */)
|
||||
{}
|
||||
|
||||
virtual void GetInternalStream(nsIInputStream** aStream,
|
||||
@ -855,7 +856,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
~BlobImplEmptyFile() {}
|
||||
~EmptyBlobImpl() {}
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
@ -98,9 +98,9 @@ FileReader::RootResultArrayBuffer()
|
||||
|
||||
//FileReader constructors/initializers
|
||||
|
||||
FileReader::FileReader(nsPIDOMWindow* aWindow,
|
||||
FileReader::FileReader(nsIGlobalObject* aGlobal,
|
||||
WorkerPrivate* aWorkerPrivate)
|
||||
: DOMEventTargetHelper(aWindow)
|
||||
: DOMEventTargetHelper(aGlobal)
|
||||
, mFileData(nullptr)
|
||||
, mDataLen(0)
|
||||
, mDataFormat(FILE_AS_BINARY)
|
||||
@ -114,8 +114,8 @@ FileReader::FileReader(nsPIDOMWindow* aWindow,
|
||||
, mBusyCount(0)
|
||||
, mWorkerPrivate(aWorkerPrivate)
|
||||
{
|
||||
MOZ_ASSERT_IF(!NS_IsMainThread(), mWorkerPrivate && !aWindow);
|
||||
MOZ_ASSERT_IF(NS_IsMainThread(), !mWorkerPrivate);
|
||||
MOZ_ASSERT(aGlobal);
|
||||
MOZ_ASSERT(NS_IsMainThread() == !mWorkerPrivate);
|
||||
SetDOMStringToNull(mResult);
|
||||
}
|
||||
|
||||
@ -128,8 +128,7 @@ FileReader::~FileReader()
|
||||
/* static */ already_AddRefed<FileReader>
|
||||
FileReader::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv)
|
||||
{
|
||||
// The owner can be null when this object is used by chrome code.
|
||||
nsCOMPtr<nsPIDOMWindow> owner = do_QueryInterface(aGlobal.GetAsSupports());
|
||||
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
|
||||
WorkerPrivate* workerPrivate = nullptr;
|
||||
|
||||
if (!NS_IsMainThread()) {
|
||||
@ -138,14 +137,7 @@ FileReader::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv)
|
||||
MOZ_ASSERT(workerPrivate);
|
||||
}
|
||||
|
||||
RefPtr<FileReader> fileReader = new FileReader(owner, workerPrivate);
|
||||
|
||||
if (!owner && nsContentUtils::ThreadsafeIsCallerChrome()) {
|
||||
// Instead of grabbing some random global from the context stack,
|
||||
// let's use the default one (junk scope) for now.
|
||||
// We should move away from this Init...
|
||||
fileReader->BindToOwner(xpc::NativeGlobal(xpc::PrivilegedJunkScope()));
|
||||
}
|
||||
RefPtr<FileReader> fileReader = new FileReader(global, workerPrivate);
|
||||
|
||||
return fileReader.forget();
|
||||
}
|
||||
@ -242,17 +234,7 @@ FileReader::DoOnLoadEnd(nsresult aStatus,
|
||||
switch (mDataFormat) {
|
||||
case FILE_AS_ARRAYBUFFER: {
|
||||
AutoJSAPI jsapi;
|
||||
nsCOMPtr<nsIGlobalObject> globalObject;
|
||||
|
||||
if (NS_IsMainThread()) {
|
||||
globalObject = do_QueryInterface(GetParentObject());
|
||||
} else {
|
||||
MOZ_ASSERT(mWorkerPrivate);
|
||||
MOZ_ASSERT(mBusyCount);
|
||||
globalObject = mWorkerPrivate->GlobalScope();
|
||||
}
|
||||
|
||||
if (!globalObject || !jsapi.Init(globalObject)) {
|
||||
if (!jsapi.Init(GetParentObject())) {
|
||||
FreeFileData();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
@ -365,6 +347,14 @@ FileReader::ReadFileContent(Blob& aBlob,
|
||||
Abort(error);
|
||||
error.SuppressException();
|
||||
|
||||
if (mReadyState == LOADING) {
|
||||
// A nested ReadAsSomething() as been called during one of the events
|
||||
// dispatched by Abort(). We have to terminate this operation in order to
|
||||
// continue the nested one.
|
||||
aRv.Throw(NS_ERROR_ABORT);
|
||||
return;
|
||||
}
|
||||
|
||||
mError = nullptr;
|
||||
SetDOMStringToNull(mResult);
|
||||
mTransferred = 0;
|
||||
|
@ -46,7 +46,7 @@ class FileReader final : public DOMEventTargetHelper,
|
||||
friend class FileReaderDecreaseBusyCounter;
|
||||
|
||||
public:
|
||||
FileReader(nsPIDOMWindow* aWindow,
|
||||
FileReader(nsIGlobalObject* aGlobal,
|
||||
workers::WorkerPrivate* aWorkerPrivate);
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
@ -23,32 +23,16 @@ FormData::FormData(nsISupports* aOwner)
|
||||
|
||||
namespace {
|
||||
|
||||
// Implements steps 3 and 4 of the "create an entry" algorithm of FormData.
|
||||
already_AddRefed<File>
|
||||
CreateNewFileInstance(Blob& aBlob, const Optional<nsAString>& aFilename,
|
||||
ErrorResult& aRv)
|
||||
already_AddRefed<Blob>
|
||||
GetBlobForFormDataStorage(Blob& aBlob, const Optional<nsAString>& aFilename,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
// Step 3 "If value is a Blob object and not a File object, set value to
|
||||
// a new File object, representing the same bytes, whose name attribute value
|
||||
// is "blob"."
|
||||
// Step 4 "If value is a File object and filename is given, set value to
|
||||
// a new File object, representing the same bytes, whose name attribute
|
||||
// value is filename."
|
||||
nsAutoString filename;
|
||||
if (aFilename.WasPassed()) {
|
||||
filename = aFilename.Value();
|
||||
} else {
|
||||
// If value is already a File and filename is not passed, the spec says not
|
||||
// to create a new instance.
|
||||
RefPtr<File> file = aBlob.ToFile();
|
||||
if (file) {
|
||||
return file.forget();
|
||||
}
|
||||
|
||||
filename = NS_LITERAL_STRING("blob");
|
||||
if (!aFilename.WasPassed()) {
|
||||
RefPtr<Blob> blob = &aBlob;
|
||||
return blob.forget();
|
||||
}
|
||||
|
||||
RefPtr<File> file = aBlob.ToFile(filename, aRv);
|
||||
RefPtr<File> file = aBlob.ToFile(aFilename.Value(), aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -78,7 +62,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(FormData)
|
||||
|
||||
for (uint32_t i = 0, len = tmp->mFormData.Length(); i < len; ++i) {
|
||||
ImplCycleCollectionTraverse(cb, tmp->mFormData[i].value,
|
||||
"mFormData[i].GetAsFile()", 0);
|
||||
"mFormData[i].GetAsBlob()", 0);
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
@ -116,14 +100,14 @@ FormData::Append(const nsAString& aName, const nsAString& aValue,
|
||||
void
|
||||
FormData::Append(const nsAString& aName, Blob& aBlob,
|
||||
const Optional<nsAString>& aFilename,
|
||||
ErrorResult& aRv)
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
RefPtr<File> file = CreateNewFileInstance(aBlob, aFilename, aRv);
|
||||
RefPtr<Blob> blob = GetBlobForFormDataStorage(aBlob, aFilename, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
|
||||
AddNameFilePair(aName, file);
|
||||
AddNameBlobPair(aName, blob);
|
||||
}
|
||||
|
||||
void
|
||||
@ -140,7 +124,7 @@ FormData::Delete(const nsAString& aName)
|
||||
|
||||
void
|
||||
FormData::Get(const nsAString& aName,
|
||||
Nullable<OwningFileOrUSVString>& aOutValue)
|
||||
Nullable<OwningBlobOrUSVString>& aOutValue)
|
||||
{
|
||||
for (uint32_t i = 0; i < mFormData.Length(); ++i) {
|
||||
if (aName.Equals(mFormData[i].name)) {
|
||||
@ -154,11 +138,11 @@ FormData::Get(const nsAString& aName,
|
||||
|
||||
void
|
||||
FormData::GetAll(const nsAString& aName,
|
||||
nsTArray<OwningFileOrUSVString>& aValues)
|
||||
nsTArray<OwningBlobOrUSVString>& aValues)
|
||||
{
|
||||
for (uint32_t i = 0; i < mFormData.Length(); ++i) {
|
||||
if (aName.Equals(mFormData[i].name)) {
|
||||
OwningFileOrUSVString* element = aValues.AppendElement();
|
||||
OwningBlobOrUSVString* element = aValues.AppendElement();
|
||||
*element = mFormData[i].value;
|
||||
}
|
||||
}
|
||||
@ -177,12 +161,12 @@ FormData::Has(const nsAString& aName)
|
||||
}
|
||||
|
||||
nsresult
|
||||
FormData::AddNameFilePair(const nsAString& aName, File* aFile)
|
||||
FormData::AddNameBlobPair(const nsAString& aName, Blob* aBlob)
|
||||
{
|
||||
MOZ_ASSERT(aFile);
|
||||
MOZ_ASSERT(aBlob);
|
||||
|
||||
FormDataTuple* data = mFormData.AppendElement();
|
||||
SetNameFilePair(data, aName, aFile);
|
||||
SetNameBlobPair(data, aName, aBlob);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -215,12 +199,12 @@ FormData::Set(const nsAString& aName, Blob& aBlob,
|
||||
{
|
||||
FormDataTuple* tuple = RemoveAllOthersAndGetFirstFormDataTuple(aName);
|
||||
if (tuple) {
|
||||
RefPtr<File> file = CreateNewFileInstance(aBlob, aFilename, aRv);
|
||||
RefPtr<Blob> blob = GetBlobForFormDataStorage(aBlob, aFilename, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
|
||||
SetNameFilePair(tuple, aName, file);
|
||||
SetNameBlobPair(tuple, aName, blob);
|
||||
} else {
|
||||
Append(aName, aBlob, aFilename, aRv);
|
||||
}
|
||||
@ -251,7 +235,7 @@ FormData::GetKeyAtIndex(uint32_t aIndex) const
|
||||
return mFormData[aIndex].name;
|
||||
}
|
||||
|
||||
const OwningFileOrUSVString&
|
||||
const OwningBlobOrUSVString&
|
||||
FormData::GetValueAtIndex(uint32_t aIndex) const
|
||||
{
|
||||
MOZ_ASSERT(aIndex < mFormData.Length());
|
||||
@ -269,15 +253,15 @@ FormData::SetNameValuePair(FormDataTuple* aData,
|
||||
}
|
||||
|
||||
void
|
||||
FormData::SetNameFilePair(FormDataTuple* aData,
|
||||
FormData::SetNameBlobPair(FormDataTuple* aData,
|
||||
const nsAString& aName,
|
||||
File* aFile)
|
||||
Blob* aBlob)
|
||||
{
|
||||
MOZ_ASSERT(aData);
|
||||
MOZ_ASSERT(aFile);
|
||||
MOZ_ASSERT(aBlob);
|
||||
|
||||
aData->name = aName;
|
||||
aData->value.SetAsFile() = aFile;
|
||||
aData->value.SetAsBlob() = aBlob;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
@ -358,8 +342,21 @@ FormData::GetSendInfo(nsIInputStream** aBody, uint64_t* aContentLength,
|
||||
nsFSMultipartFormData fs(NS_LITERAL_CSTRING("UTF-8"), nullptr);
|
||||
|
||||
for (uint32_t i = 0; i < mFormData.Length(); ++i) {
|
||||
if (mFormData[i].value.IsFile()) {
|
||||
fs.AddNameFilePair(mFormData[i].name, mFormData[i].value.GetAsFile());
|
||||
if (mFormData[i].value.IsBlob()) {
|
||||
RefPtr<File> file = mFormData[i].value.GetAsBlob()->ToFile();
|
||||
if (file) {
|
||||
fs.AddNameBlobPair(mFormData[i].name, file);
|
||||
continue;
|
||||
}
|
||||
|
||||
ErrorResult rv;
|
||||
file =
|
||||
mFormData[i].value.GetAsBlob()->ToFile(NS_LITERAL_STRING("blob"), rv);
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
return rv.StealNSResult();
|
||||
}
|
||||
|
||||
fs.AddNameBlobPair(mFormData[i].name, file);
|
||||
} else if (mFormData[i].value.IsUSVString()) {
|
||||
fs.AddNameValuePair(mFormData[i].name,
|
||||
mFormData[i].value.GetAsUSVString());
|
||||
|
@ -35,7 +35,7 @@ private:
|
||||
struct FormDataTuple
|
||||
{
|
||||
nsString name;
|
||||
OwningFileOrUSVString value;
|
||||
OwningBlobOrUSVString value;
|
||||
};
|
||||
|
||||
// Returns the FormDataTuple to modify. This may be null, in which case
|
||||
@ -47,9 +47,9 @@ private:
|
||||
const nsAString& aName,
|
||||
const nsAString& aValue);
|
||||
|
||||
void SetNameFilePair(FormDataTuple* aData,
|
||||
void SetNameBlobPair(FormDataTuple* aData,
|
||||
const nsAString& aName,
|
||||
File* aFile);
|
||||
Blob* aBlob);
|
||||
|
||||
public:
|
||||
explicit FormData(nsISupports* aOwner = nullptr);
|
||||
@ -84,9 +84,9 @@ public:
|
||||
|
||||
void Delete(const nsAString& aName);
|
||||
|
||||
void Get(const nsAString& aName, Nullable<OwningFileOrUSVString>& aOutValue);
|
||||
void Get(const nsAString& aName, Nullable<OwningBlobOrUSVString>& aOutValue);
|
||||
|
||||
void GetAll(const nsAString& aName, nsTArray<OwningFileOrUSVString>& aValues);
|
||||
void GetAll(const nsAString& aName, nsTArray<OwningBlobOrUSVString>& aValues);
|
||||
|
||||
bool Has(const nsAString& aName);
|
||||
|
||||
@ -100,7 +100,7 @@ public:
|
||||
|
||||
const nsAString& GetKeyAtIndex(uint32_t aIndex) const;
|
||||
|
||||
const OwningFileOrUSVString& GetValueAtIndex(uint32_t aIndex) const;
|
||||
const OwningBlobOrUSVString& GetValueAtIndex(uint32_t aIndex) const;
|
||||
|
||||
// nsFormSubmission
|
||||
virtual nsresult
|
||||
@ -114,11 +114,11 @@ public:
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
virtual nsresult AddNameFilePair(const nsAString& aName,
|
||||
File* aFile) override;
|
||||
virtual nsresult AddNameBlobPair(const nsAString& aName,
|
||||
Blob* aBlob) override;
|
||||
|
||||
typedef bool (*FormDataEntryCallback)(const nsString& aName,
|
||||
const OwningFileOrUSVString& aValue,
|
||||
const OwningBlobOrUSVString& aValue,
|
||||
void* aClosure);
|
||||
|
||||
uint32_t
|
||||
|
@ -836,14 +836,13 @@ ReadFormData(JSContext* aCx,
|
||||
|
||||
RefPtr<BlobImpl> blobImpl =
|
||||
aHolder->BlobImpls()[indexOrLengthOfString];
|
||||
MOZ_ASSERT(blobImpl->IsFile());
|
||||
|
||||
RefPtr<File> file =
|
||||
File::Create(aHolder->ParentDuringRead(), blobImpl);
|
||||
MOZ_ASSERT(file);
|
||||
RefPtr<Blob> blob =
|
||||
Blob::Create(aHolder->ParentDuringRead(), blobImpl);
|
||||
MOZ_ASSERT(blob);
|
||||
|
||||
ErrorResult rv;
|
||||
formData->Append(name, *file, thirdArg, rv);
|
||||
formData->Append(name, *blob, thirdArg, rv);
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -912,7 +911,7 @@ WriteFormData(JSStructuredCloneWriter* aWriter,
|
||||
{ }
|
||||
|
||||
static bool
|
||||
Write(const nsString& aName, const OwningFileOrUSVString& aValue,
|
||||
Write(const nsString& aName, const OwningBlobOrUSVString& aValue,
|
||||
void* aClosure)
|
||||
{
|
||||
Closure* closure = static_cast<Closure*>(aClosure);
|
||||
@ -920,8 +919,8 @@ WriteFormData(JSStructuredCloneWriter* aWriter,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (aValue.IsFile()) {
|
||||
BlobImpl* blobImpl = aValue.GetAsFile()->Impl();
|
||||
if (aValue.IsBlob()) {
|
||||
BlobImpl* blobImpl = aValue.GetAsBlob()->Impl();
|
||||
if (!JS_WriteUint32Pair(closure->mWriter, SCTAG_DOM_BLOB,
|
||||
closure->mHolder->BlobImpls().Length())) {
|
||||
return false;
|
||||
|
192
dom/base/WebKitCSSMatrix.cpp
Normal file
192
dom/base/WebKitCSSMatrix.cpp
Normal file
@ -0,0 +1,192 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/dom/WebKitCSSMatrix.h"
|
||||
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
#include "mozilla/dom/WebKitCSSMatrixBinding.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
static const double sRadPerDegree = 2.0 * M_PI / 360.0;
|
||||
|
||||
bool
|
||||
WebKitCSSMatrix::FeatureEnabled(JSContext* aCx, JSObject* aObj)
|
||||
{
|
||||
return Preferences::GetBool("layout.css.DOMMatrix.enabled", false) &&
|
||||
Preferences::GetBool("layout.css.prefixes.webkit", false);
|
||||
}
|
||||
|
||||
already_AddRefed<WebKitCSSMatrix>
|
||||
WebKitCSSMatrix::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv)
|
||||
{
|
||||
RefPtr<WebKitCSSMatrix> obj = new WebKitCSSMatrix(aGlobal.GetAsSupports());
|
||||
return obj.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<WebKitCSSMatrix>
|
||||
WebKitCSSMatrix::Constructor(const GlobalObject& aGlobal,
|
||||
const nsAString& aTransformList, ErrorResult& aRv)
|
||||
{
|
||||
RefPtr<WebKitCSSMatrix> obj = new WebKitCSSMatrix(aGlobal.GetAsSupports());
|
||||
obj = obj->SetMatrixValue(aTransformList, aRv);
|
||||
return obj.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<WebKitCSSMatrix>
|
||||
WebKitCSSMatrix::Constructor(const GlobalObject& aGlobal,
|
||||
const DOMMatrixReadOnly& aOther, ErrorResult& aRv)
|
||||
{
|
||||
RefPtr<WebKitCSSMatrix> obj = new WebKitCSSMatrix(aGlobal.GetAsSupports(),
|
||||
aOther);
|
||||
return obj.forget();
|
||||
}
|
||||
|
||||
JSObject*
|
||||
WebKitCSSMatrix::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
return WebKitCSSMatrixBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
WebKitCSSMatrix*
|
||||
WebKitCSSMatrix::SetMatrixValue(const nsAString& aTransformList,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
DOMMatrix::SetMatrixValue(aTransformList, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
already_AddRefed<WebKitCSSMatrix>
|
||||
WebKitCSSMatrix::Multiply(const WebKitCSSMatrix& other) const
|
||||
{
|
||||
RefPtr<WebKitCSSMatrix> retval = new WebKitCSSMatrix(mParent, *this);
|
||||
retval->MultiplySelf(other);
|
||||
|
||||
return retval.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<WebKitCSSMatrix>
|
||||
WebKitCSSMatrix::Inverse() const
|
||||
{
|
||||
RefPtr<WebKitCSSMatrix> retval = new WebKitCSSMatrix(mParent, *this);
|
||||
retval->InvertSelf();
|
||||
|
||||
return retval.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<WebKitCSSMatrix>
|
||||
WebKitCSSMatrix::Translate(double aTx,
|
||||
double aTy,
|
||||
double aTz) const
|
||||
{
|
||||
RefPtr<WebKitCSSMatrix> retval = new WebKitCSSMatrix(mParent, *this);
|
||||
retval->TranslateSelf(aTx, aTy, aTz);
|
||||
|
||||
return retval.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<WebKitCSSMatrix>
|
||||
WebKitCSSMatrix::Scale(double aScaleX,
|
||||
const Optional<double>& aScaleY,
|
||||
double aScaleZ) const
|
||||
{
|
||||
double scaleX = aScaleX;
|
||||
double scaleY = aScaleY.WasPassed() ? aScaleY.Value() : scaleX;
|
||||
double scaleZ = aScaleZ;
|
||||
|
||||
RefPtr<WebKitCSSMatrix> retval = new WebKitCSSMatrix(mParent, *this);
|
||||
retval->ScaleNonUniformSelf(scaleX, scaleY, scaleZ);
|
||||
|
||||
return retval.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<WebKitCSSMatrix>
|
||||
WebKitCSSMatrix::Rotate(double aRotX,
|
||||
const Optional<double>& aRotY,
|
||||
const Optional<double>& aRotZ) const
|
||||
{
|
||||
double rotX = aRotX;
|
||||
double rotY;
|
||||
double rotZ;
|
||||
|
||||
if (!aRotY.WasPassed() && !aRotZ.WasPassed()) {
|
||||
rotZ = rotX;
|
||||
rotX = 0;
|
||||
rotY = 0;
|
||||
} else {
|
||||
rotY = aRotY.WasPassed() ? aRotY.Value() : 0;
|
||||
rotZ = aRotZ.WasPassed() ? aRotZ.Value() : 0;
|
||||
}
|
||||
|
||||
RefPtr<WebKitCSSMatrix> retval = new WebKitCSSMatrix(mParent, *this);
|
||||
retval->Rotate3dSelf(rotX, rotY, rotZ);
|
||||
|
||||
return retval.forget();
|
||||
}
|
||||
|
||||
WebKitCSSMatrix*
|
||||
WebKitCSSMatrix::Rotate3dSelf(double aRotX,
|
||||
double aRotY,
|
||||
double aRotZ)
|
||||
{
|
||||
if (aRotX != 0 || aRotY != 0) {
|
||||
Ensure3DMatrix();
|
||||
}
|
||||
|
||||
if (mMatrix3D) {
|
||||
if (fmod(aRotZ, 360) != 0) {
|
||||
mMatrix3D->RotateZ(aRotZ * sRadPerDegree);
|
||||
}
|
||||
if (fmod(aRotY, 360) != 0) {
|
||||
mMatrix3D->RotateY(aRotY * sRadPerDegree);
|
||||
}
|
||||
if (fmod(aRotX, 360) != 0) {
|
||||
mMatrix3D->RotateX(aRotX * sRadPerDegree);
|
||||
}
|
||||
} else if (fmod(aRotZ, 360) != 0) {
|
||||
mMatrix2D->PreRotate(aRotZ * sRadPerDegree);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
already_AddRefed<WebKitCSSMatrix>
|
||||
WebKitCSSMatrix::RotateAxisAngle(double aX,
|
||||
double aY,
|
||||
double aZ,
|
||||
double aAngle) const
|
||||
{
|
||||
RefPtr<WebKitCSSMatrix> retval = new WebKitCSSMatrix(mParent, *this);
|
||||
retval->RotateAxisAngleSelf(aX, aY, aZ, aAngle);
|
||||
|
||||
return retval.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<WebKitCSSMatrix>
|
||||
WebKitCSSMatrix::SkewX(double aSx) const
|
||||
{
|
||||
RefPtr<WebKitCSSMatrix> retval = new WebKitCSSMatrix(mParent, *this);
|
||||
retval->SkewXSelf(aSx);
|
||||
|
||||
return retval.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<WebKitCSSMatrix>
|
||||
WebKitCSSMatrix::SkewY(double aSy) const
|
||||
{
|
||||
RefPtr<WebKitCSSMatrix> retval = new WebKitCSSMatrix(mParent, *this);
|
||||
retval->SkewYSelf(aSy);
|
||||
|
||||
return retval.forget();
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
70
dom/base/WebKitCSSMatrix.h
Normal file
70
dom/base/WebKitCSSMatrix.h
Normal file
@ -0,0 +1,70 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_webkitcssmatrix_h__
|
||||
#define mozilla_dom_webkitcssmatrix_h__
|
||||
|
||||
#include "mozilla/dom/DOMMatrix.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class WebKitCSSMatrix final : public DOMMatrix
|
||||
{
|
||||
public:
|
||||
explicit WebKitCSSMatrix(nsISupports* aParent)
|
||||
: DOMMatrix(aParent)
|
||||
{}
|
||||
|
||||
WebKitCSSMatrix(nsISupports* aParent, const DOMMatrixReadOnly& other)
|
||||
: DOMMatrix(aParent, other)
|
||||
{}
|
||||
|
||||
static bool FeatureEnabled(JSContext* aCx, JSObject* aObj);
|
||||
|
||||
static already_AddRefed<WebKitCSSMatrix>
|
||||
Constructor(const GlobalObject& aGlobal, ErrorResult& aRv);
|
||||
static already_AddRefed<WebKitCSSMatrix>
|
||||
Constructor(const GlobalObject& aGlobal,
|
||||
const nsAString& aTransformList, ErrorResult& aRv);
|
||||
static already_AddRefed<WebKitCSSMatrix>
|
||||
Constructor(const GlobalObject& aGlobal,
|
||||
const DOMMatrixReadOnly& aOther, ErrorResult& aRv);
|
||||
|
||||
nsISupports* GetParentObject() const { return mParent; }
|
||||
virtual JSObject* WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
WebKitCSSMatrix* SetMatrixValue(const nsAString& aTransformList,
|
||||
ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<WebKitCSSMatrix> Multiply(const WebKitCSSMatrix& aOther) const;
|
||||
already_AddRefed<WebKitCSSMatrix> Inverse() const;
|
||||
already_AddRefed<WebKitCSSMatrix> Translate(double aTx,
|
||||
double aTy,
|
||||
double aTz) const;
|
||||
already_AddRefed<WebKitCSSMatrix> Scale(double aScaleX,
|
||||
const Optional<double>& aScaleY,
|
||||
double aScaleZ) const;
|
||||
already_AddRefed<WebKitCSSMatrix> Rotate(double aRotX,
|
||||
const Optional<double>& aRotY,
|
||||
const Optional<double>& aRotZ) const;
|
||||
already_AddRefed<WebKitCSSMatrix> RotateAxisAngle(double aX,
|
||||
double aY,
|
||||
double aZ,
|
||||
double aAngle) const;
|
||||
already_AddRefed<WebKitCSSMatrix> SkewX(double aSx) const;
|
||||
already_AddRefed<WebKitCSSMatrix> SkewY(double aSy) const;
|
||||
protected:
|
||||
WebKitCSSMatrix* Rotate3dSelf(double aRotX,
|
||||
double aRotY,
|
||||
double aRotZ);
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_dom_webkitcssmatrix_h__ */
|
@ -7,6 +7,7 @@
|
||||
#include "WindowNamedPropertiesHandler.h"
|
||||
#include "mozilla/dom/EventTargetBinding.h"
|
||||
#include "mozilla/dom/WindowBinding.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsDOMClassInfo.h"
|
||||
#include "nsGlobalWindow.h"
|
||||
#include "nsHTMLDocument.h"
|
||||
|
28
dom/base/crashtests/1230422.html
Normal file
28
dom/base/crashtests/1230422.html
Normal file
@ -0,0 +1,28 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
|
||||
var a = new FileReader();
|
||||
|
||||
function f() {
|
||||
a.removeEventListener("loadend", f);
|
||||
g();
|
||||
}
|
||||
|
||||
function g() {
|
||||
a.readAsBinaryString(new Blob());
|
||||
}
|
||||
|
||||
a.addEventListener("loadend", f);
|
||||
|
||||
try {
|
||||
g();
|
||||
g();
|
||||
} catch(e) {}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -205,3 +205,4 @@ load structured_clone_container_throws.html
|
||||
HTTP(..) load xhr_abortinprogress.html
|
||||
load xhr_empty_datauri.html
|
||||
load xhr_html_nullresponse.html
|
||||
load 1230422.html
|
||||
|
@ -212,6 +212,7 @@ EXPORTS.mozilla.dom += [
|
||||
'TreeWalker.h',
|
||||
'URL.h',
|
||||
'URLSearchParams.h',
|
||||
'WebKitCSSMatrix.h',
|
||||
'WebSocket.h',
|
||||
'WindowOrientationObserver.h',
|
||||
]
|
||||
@ -359,6 +360,7 @@ UNIFIED_SOURCES += [
|
||||
'TreeWalker.cpp',
|
||||
'URL.cpp',
|
||||
'URLSearchParams.cpp',
|
||||
'WebKitCSSMatrix.cpp',
|
||||
'WebSocket.cpp',
|
||||
'WindowNamedPropertiesHandler.cpp',
|
||||
'WindowOrientationObserver.cpp',
|
||||
|
@ -445,9 +445,9 @@ nsContentPermissionUtils::NotifyRemoveContentPermissionRequestChild(
|
||||
NS_IMPL_ISUPPORTS(nsContentPermissionRequester, nsIContentPermissionRequester)
|
||||
|
||||
nsContentPermissionRequester::nsContentPermissionRequester(nsPIDOMWindow* aWindow)
|
||||
: mWindow(aWindow)
|
||||
: mWindow(do_GetWeakReference(aWindow))
|
||||
, mListener(new VisibilityChangeListener(aWindow))
|
||||
{
|
||||
mListener = new VisibilityChangeListener(mWindow);
|
||||
}
|
||||
|
||||
nsContentPermissionRequester::~nsContentPermissionRequester()
|
||||
@ -461,12 +461,12 @@ nsContentPermissionRequester::GetVisibility(nsIContentPermissionRequestCallback*
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCallback);
|
||||
|
||||
if (!mWindow) {
|
||||
MOZ_ASSERT(false);
|
||||
nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
|
||||
if (!window) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShell> docshell = mWindow->GetDocShell();
|
||||
nsCOMPtr<nsIDocShell> docshell = window->GetDocShell();
|
||||
if (!docshell) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
@ -127,7 +127,7 @@ public:
|
||||
private:
|
||||
virtual ~nsContentPermissionRequester();
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> mWindow;
|
||||
nsWeakPtr mWindow;
|
||||
RefPtr<VisibilityChangeListener> mListener;
|
||||
};
|
||||
|
||||
|
@ -105,6 +105,7 @@
|
||||
#include "nsDocument.h"
|
||||
#include "HTMLImageElement.h"
|
||||
#include "mozilla/css/ImageLoader.h"
|
||||
#include "mozilla/layers/APZCTreeManager.h" // for layers::ZoomToRectBehavior
|
||||
|
||||
#ifdef XP_WIN
|
||||
#undef GetClassName
|
||||
@ -2421,6 +2422,59 @@ nsDOMWindowUtils::FlushApzRepaints(bool* aOutResult)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::ZoomToFocusedInput()
|
||||
{
|
||||
nsIWidget* widget = GetWidget();
|
||||
if (!widget) {
|
||||
return NS_OK;
|
||||
}
|
||||
// If APZ is not enabled, this function is a no-op.
|
||||
if (!widget->AsyncPanZoomEnabled()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsFocusManager* fm = nsFocusManager::GetFocusManager();
|
||||
if (!fm) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIContent* content = fm->GetFocusedContent();
|
||||
if (!content) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIPresShell* shell = APZCCallbackHelper::GetRootContentDocumentPresShellForContent(content);
|
||||
if (!shell) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIScrollableFrame* rootScrollFrame = shell->GetRootScrollFrameAsScrollable();
|
||||
if (!rootScrollFrame) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIDocument* document = shell->GetDocument();
|
||||
if (!document) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
uint32_t presShellId;
|
||||
FrameMetrics::ViewID viewId;
|
||||
if (APZCCallbackHelper::GetOrCreateScrollIdentifiers(document->GetDocumentElement(), &presShellId, &viewId)) {
|
||||
uint32_t flags = layers::DISABLE_ZOOM_OUT;
|
||||
if (!Preferences::GetBool("formhelper.autozoom")) {
|
||||
flags |= layers::PAN_INTO_VIEW_ONLY;
|
||||
}
|
||||
|
||||
CSSRect bounds = nsLayoutUtils::GetBoundingContentRect(content, rootScrollFrame);
|
||||
bounds.Inflate(15.0f, 0.0f);
|
||||
widget->ZoomToRect(presShellId, viewId, bounds, flags);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::ComputeAnimationDistance(nsIDOMElement* aElement,
|
||||
const nsAString& aProperty,
|
||||
|
@ -6592,6 +6592,7 @@ nsIDocument::ImportNode(nsINode& aNode, bool aDeep, ErrorResult& rv) const
|
||||
if (ShadowRoot::FromNode(imported)) {
|
||||
break;
|
||||
}
|
||||
MOZ_FALLTHROUGH;
|
||||
}
|
||||
case nsIDOMNode::ATTRIBUTE_NODE:
|
||||
case nsIDOMNode::ELEMENT_NODE:
|
||||
@ -7628,6 +7629,7 @@ nsIDocument::AdoptNode(nsINode& aAdoptedNode, ErrorResult& rv)
|
||||
rv.Throw(NS_ERROR_DOM_HIERARCHY_REQUEST_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
MOZ_FALLTHROUGH;
|
||||
}
|
||||
case nsIDOMNode::ELEMENT_NODE:
|
||||
case nsIDOMNode::PROCESSING_INSTRUCTION_NODE:
|
||||
@ -7919,6 +7921,7 @@ nsDocument::GetViewportInfo(const ScreenIntSize& aDisplaySize)
|
||||
mValidMaxScale = !maxScaleStr.IsEmpty() && NS_SUCCEEDED(scaleMaxErrorCode);
|
||||
|
||||
mViewportType = Specified;
|
||||
MOZ_FALLTHROUGH;
|
||||
}
|
||||
case Specified:
|
||||
default:
|
||||
|
@ -1100,6 +1100,9 @@ nsDocumentEncoder::EncodeToStringWithMaxLength(uint32_t aMaxLength,
|
||||
static const size_t bufferSize = 2048;
|
||||
if (!mCachedBuffer) {
|
||||
mCachedBuffer = nsStringBuffer::Alloc(bufferSize).take();
|
||||
if (NS_WARN_IF(!mCachedBuffer)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
NS_ASSERTION(!mCachedBuffer->IsReadonly(),
|
||||
"DocumentEncoder shouldn't keep reference to non-readonly buffer!");
|
||||
|
@ -781,6 +781,7 @@ bool
|
||||
nsFrameLoader::ShowRemoteFrame(const ScreenIntSize& size,
|
||||
nsSubDocumentFrame *aFrame)
|
||||
{
|
||||
PROFILER_LABEL_FUNC(js::ProfileEntry::Category::GRAPHICS);
|
||||
NS_ASSERTION(IsRemoteFrame(), "ShowRemote only makes sense on remote frames.");
|
||||
|
||||
if (!mRemoteBrowser && !TryRemoteBrowser()) {
|
||||
|
@ -7601,6 +7601,7 @@ nsGlobalWindow::RevisePopupAbuseLevel(PopupControlState aControl)
|
||||
case openOverridden:
|
||||
if (PopupWhitelisted())
|
||||
abuse = PopupControlState(abuse - 1);
|
||||
break;
|
||||
case openAllowed: break;
|
||||
default:
|
||||
NS_WARNING("Strange PopupControlState!");
|
||||
|
@ -1335,6 +1335,8 @@ nsJSContext::ShrinkGCBuffersNow()
|
||||
static void
|
||||
FinishAnyIncrementalGC()
|
||||
{
|
||||
PROFILER_LABEL_FUNC(js::ProfileEntry::Category::GC);
|
||||
|
||||
if (sCCLockedOut) {
|
||||
// We're in the middle of an incremental GC, so finish it.
|
||||
JS::PrepareForIncrementalGC(sRuntime);
|
||||
|
@ -3102,6 +3102,7 @@ nsObjectLoadingContent::DoStopPlugin(nsPluginInstanceOwner* aInstanceOwner,
|
||||
NS_IMETHODIMP
|
||||
nsObjectLoadingContent::StopPluginInstance()
|
||||
{
|
||||
PROFILER_LABEL_FUNC(js::ProfileEntry::Category::OTHER);
|
||||
// Clear any pending events
|
||||
mPendingInstantiateEvent = nullptr;
|
||||
mPendingCheckPluginStopEvent = nullptr;
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "nsIContent.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDocumentEncoder.h"
|
||||
#include "nsIParserService.h"
|
||||
#include "nsNameSpaceManager.h"
|
||||
#include "nsTextFragment.h"
|
||||
#include "nsString.h"
|
||||
@ -1429,7 +1430,7 @@ nsXMLContentSerializer::AppendFormatedWrapped_WhitespaceSequence(
|
||||
case ' ':
|
||||
case '\t':
|
||||
sawBlankOrTab = true;
|
||||
// no break
|
||||
MOZ_FALLTHROUGH;
|
||||
case '\n':
|
||||
++aPos;
|
||||
// do not increase mColPos,
|
||||
|
@ -272,12 +272,16 @@ skip-if = buildapp == 'b2g' # Requires webgl support
|
||||
[test_async_setTimeout_stack_across_globals.html]
|
||||
[test_audioWindowUtils.html]
|
||||
[test_audioNotification.html]
|
||||
tags = audiochannel
|
||||
skip-if = buildapp == 'mulet'
|
||||
[test_audioNotificationStream.html]
|
||||
tags = audiochannel
|
||||
skip-if = buildapp == 'mulet'
|
||||
[test_audioNotificationStopOnNavigation.html]
|
||||
tags = audiochannel
|
||||
skip-if = buildapp == 'mulet'
|
||||
[test_audioNotificationWithEarlyPlay.html]
|
||||
tags = audiochannel
|
||||
skip-if = buildapp == 'mulet'
|
||||
[test_bug1091883.html]
|
||||
[test_bug116083.html]
|
||||
@ -321,15 +325,21 @@ skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' || e1
|
||||
[test_navigator_resolve_identity.html]
|
||||
[test_navigator_language.html]
|
||||
[test_noAudioNotification.html]
|
||||
tags = audiochannel
|
||||
[test_noAudioNotificationOnMutedElement.html]
|
||||
tags = audiochannel
|
||||
[test_noAudioNotificationOnMutedOrVolume0Element.html]
|
||||
tags = audiochannel
|
||||
[test_noAudioNotificationOnVolume0Element.html]
|
||||
tags = audiochannel
|
||||
[test_noWebAudioNotification.html]
|
||||
tags = audiochannel
|
||||
[test_openDialogChromeOnly.html]
|
||||
[test_open_null_features.html]
|
||||
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Fails on b2g-desktop, tracked in bug 1011874
|
||||
[test_postMessage_solidus.html]
|
||||
[test_pluginAudioNotification.html]
|
||||
tags = audiochannel
|
||||
skip-if = (buildapp == 'b2g' || buildapp == 'mulet' || toolkit == 'android') # Plugins don't work on Android and/or B2G/Mulet
|
||||
[test_screen_orientation.html]
|
||||
[test_orientation_alternate.html]
|
||||
@ -355,8 +365,10 @@ skip-if = e10s || buildapp == 'b2g' # Bug 1156489.
|
||||
[test_urlSearchParams_utf8.html]
|
||||
[test_urlutils_stringify.html]
|
||||
[test_webaudioNotification.html]
|
||||
tags = audiochannel
|
||||
skip-if = buildapp == 'mulet'
|
||||
[test_webaudioNotificationStopOnNavigation.html]
|
||||
tags = audiochannel
|
||||
skip-if = buildapp == 'mulet'
|
||||
[test_window_constructor.html]
|
||||
[test_window_cross_origin_props.html]
|
||||
|
@ -16,9 +16,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=789315
|
||||
<script type="text/javascript">
|
||||
var obj = new FormData(document.getElementById('a')).get('b');
|
||||
|
||||
ok(obj instanceof File, "This should return an empty File");
|
||||
ok(obj instanceof Blob, "This should return an empty Blob");
|
||||
is(obj.size, 0, "Size should be 0");
|
||||
is(obj.name, "", "Name should be an empty string");
|
||||
is(obj.type, "application/octet-stream", "Type should be application/octet-stream");
|
||||
|
||||
var o = obj.slice(10, 100, "foo/bar");
|
||||
|
@ -8772,7 +8772,7 @@ class CGMemberJITInfo(CGThing):
|
||||
{
|
||||
{ ${opName} },
|
||||
{ prototypes::id::${name} },
|
||||
PrototypeTraits<prototypes::id::${name}>::Depth,
|
||||
{ PrototypeTraits<prototypes::id::${name}>::Depth },
|
||||
JSJitInfo::${opType},
|
||||
JSJitInfo::${aliasSet}, /* aliasSet. Not relevant for setters. */
|
||||
${returnType}, /* returnType. Not relevant for setters. */
|
||||
@ -9152,7 +9152,7 @@ class CGStaticMethodJitinfo(CGGeneric):
|
||||
"\n"
|
||||
"static const JSJitInfo %s_methodinfo = {\n"
|
||||
" { (JSJitGetterOp)%s },\n"
|
||||
" { prototypes::id::_ID_Count }, 0, JSJitInfo::StaticMethod,\n"
|
||||
" { prototypes::id::_ID_Count }, { 0 }, JSJitInfo::StaticMethod,\n"
|
||||
" JSJitInfo::AliasEverything, JSVAL_TYPE_MISSING, false, false,\n"
|
||||
" false, false, 0\n"
|
||||
"};\n" %
|
||||
|
@ -139,8 +139,3 @@ if CONFIG['MOZ_SIMPLEPUSH']:
|
||||
PYTHON_UNIT_TESTS += [
|
||||
'mozwebidlcodegen/test/test_mozwebidlcodegen.py',
|
||||
]
|
||||
|
||||
if CONFIG['GNU_CC']:
|
||||
CXXFLAGS += [
|
||||
'-Wno-uninitialized',
|
||||
]
|
||||
|
@ -52,8 +52,3 @@ LOCAL_INCLUDES += [
|
||||
'/js/xpconnect/src',
|
||||
'/js/xpconnect/wrappers',
|
||||
]
|
||||
|
||||
if CONFIG['GNU_CC']:
|
||||
CXXFLAGS += [
|
||||
'-Wno-uninitialized',
|
||||
]
|
||||
|
@ -112,11 +112,6 @@ BluetoothGatt::Connect(ErrorResult& aRv)
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
BT_ENSURE_TRUE_REJECT(bs, promise, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
BluetoothUuid appUuid;
|
||||
BT_ENSURE_TRUE_REJECT(NS_SUCCEEDED(StringToUuid(mAppUuid, appUuid)),
|
||||
promise,
|
||||
NS_ERROR_DOM_OPERATION_ERR);
|
||||
|
||||
BluetoothAddress deviceAddr;
|
||||
BT_ENSURE_TRUE_REJECT(
|
||||
NS_SUCCEEDED(StringToAddress(mDeviceAddr, deviceAddr)),
|
||||
@ -131,6 +126,11 @@ BluetoothGatt::Connect(ErrorResult& aRv)
|
||||
RegisterBluetoothSignalHandler(mAppUuid, this);
|
||||
}
|
||||
|
||||
BluetoothUuid appUuid;
|
||||
BT_ENSURE_TRUE_REJECT(NS_SUCCEEDED(StringToUuid(mAppUuid, appUuid)),
|
||||
promise,
|
||||
NS_ERROR_DOM_OPERATION_ERR);
|
||||
|
||||
UpdateConnectionState(BluetoothConnectionState::Connecting);
|
||||
bs->ConnectGattClientInternal(
|
||||
appUuid, deviceAddr, new BluetoothVoidReplyRunnable(nullptr, promise));
|
||||
|
@ -13,4 +13,6 @@ support-files =
|
||||
multipleAudioChannels_manifest.webapp^headers^
|
||||
|
||||
[test_browserElement_MultipleAudioChannels.html]
|
||||
[test_browserElement_NotifyChannel.html]
|
||||
tags = audiochannel
|
||||
[test_browserElement_NotifyChannel.html]
|
||||
tags = audiochannel
|
@ -13,6 +13,7 @@ support-files =
|
||||
browserElement_OpenTab.js
|
||||
|
||||
[test_browserElement_oop_AudioChannelSeeking.html]
|
||||
tags = audiochannel
|
||||
[test_browserElement_oop_getStructuredData.html]
|
||||
[test_browserElement_oop_Viewmode.html]
|
||||
[test_browserElement_oop_ThemeColor.html]
|
||||
@ -29,6 +30,7 @@ skip-if = (toolkit == 'gonk' && !debug)
|
||||
[test_browserElement_oop_AppWindowNamespace.html]
|
||||
skip-if = (toolkit == 'gonk' && !debug)
|
||||
[test_browserElement_oop_AudioChannelMutedByDefault.html]
|
||||
tags = audiochannel
|
||||
[test_browserElement_oop_Auth.html]
|
||||
skip-if = (toolkit == 'gonk' && !debug)
|
||||
[test_browserElement_oop_BackForward.html]
|
||||
@ -121,9 +123,12 @@ disabled = bug 924771
|
||||
disabled = bug 924771
|
||||
[test_browserElement_oop_GetContentDimensions.html]
|
||||
[test_browserElement_oop_AudioChannel.html]
|
||||
tags = audiochannel
|
||||
[test_browserElement_oop_AudioChannel_nested.html]
|
||||
tags = audiochannel
|
||||
[test_browserElement_oop_SetNFCFocus.html]
|
||||
[test_browserElement_oop_getWebManifest.html]
|
||||
[test_browserElement_oop_OpenWindowEmpty.html]
|
||||
skip-if = (toolkit == 'gonk') # Test doesn't work on B2G emulator
|
||||
[test_browserElement_oop_ActiveStateChangeOnChangingMutedOrVolume.html]
|
||||
tags = audiochannel
|
@ -160,6 +160,7 @@ support-files =
|
||||
[test_browserElement_NoPermission.html]
|
||||
[test_browserElement_inproc_Alert.html]
|
||||
[test_browserElement_inproc_AudioChannelSeeking.html]
|
||||
tags = audiochannel
|
||||
[test_browserElement_inproc_Viewmode.html]
|
||||
[test_browserElement_inproc_ThemeColor.html]
|
||||
skip-if = buildapp == 'b2g'
|
||||
@ -169,6 +170,7 @@ skip-if = toolkit == 'android' || buildapp == 'b2g'
|
||||
[test_browserElement_inproc_AppWindowNamespace.html]
|
||||
skip-if = toolkit == 'android' || buildapp == 'b2g' # android(TIMED_OUT, bug 783509) androidx86(TIMED_OUT, bug 783509)
|
||||
[test_browserElement_inproc_AudioChannelMutedByDefault.html]
|
||||
tags = audiochannel
|
||||
skip-if = toolkit == 'android'
|
||||
[test_browserElement_inproc_AudioPlayback.html]
|
||||
[test_browserElement_inproc_Auth.html]
|
||||
@ -261,9 +263,12 @@ skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 936226
|
||||
disabled = bug 774100
|
||||
[test_browserElement_inproc_GetContentDimensions.html]
|
||||
[test_browserElement_inproc_AudioChannel.html]
|
||||
tags = audiochannel
|
||||
[test_browserElement_inproc_AudioChannel_nested.html]
|
||||
tags = audiochannel
|
||||
[test_browserElement_inproc_SetNFCFocus.html]
|
||||
[test_browserElement_inproc_getStructuredData.html]
|
||||
[test_browserElement_inproc_OpenWindowEmpty.html]
|
||||
skip-if = (toolkit == 'gonk') # Test doesn't work on B2G emulator
|
||||
[test_browserElement_inproc_ActiveStateChangeOnChangingMutedOrVolume.html]
|
||||
[test_browserElement_inproc_ActiveStateChangeOnChangingMutedOrVolume.html]
|
||||
tags = audiochannel
|
1
dom/cache/AutoUtils.cpp
vendored
1
dom/cache/AutoUtils.cpp
vendored
@ -483,6 +483,7 @@ AutoParentOpResult::~AutoParentOpResult()
|
||||
break;
|
||||
}
|
||||
Unused << PCacheParent::Send__delete__(result.actorParent());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// other types do not need clean up
|
||||
|
@ -112,6 +112,7 @@ WebGL2Context::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
|
||||
return JS::NumberValue(0);
|
||||
|
||||
/*** fall through to fGetInteger64v ***/
|
||||
MOZ_FALLTHROUGH;
|
||||
|
||||
case LOCAL_GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS:
|
||||
case LOCAL_GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS:
|
||||
|
@ -52,12 +52,18 @@ struct WebGLVertexAttribData
|
||||
case LOCAL_GL_UNSIGNED_SHORT:
|
||||
return sizeof(GLushort);
|
||||
|
||||
case LOCAL_GL_INT:
|
||||
return sizeof(GLint);
|
||||
|
||||
case LOCAL_GL_UNSIGNED_INT:
|
||||
return sizeof(GLuint);
|
||||
|
||||
// case LOCAL_GL_FIXED:
|
||||
case LOCAL_GL_FLOAT:
|
||||
return sizeof(GLfloat);
|
||||
|
||||
default:
|
||||
NS_ERROR("Should never get here!");
|
||||
MOZ_ASSERT(false, "Should never get here!");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -58,7 +58,6 @@ UNIFIED_SOURCES += [
|
||||
|
||||
# WebGL Sources
|
||||
UNIFIED_SOURCES += [
|
||||
'MurmurHash3.cpp',
|
||||
'TexUnpackBlob.cpp',
|
||||
'WebGL1Context.cpp',
|
||||
'WebGL1ContextBuffers.cpp',
|
||||
@ -149,6 +148,14 @@ UNIFIED_SOURCES += [
|
||||
'WebGLVertexArrayObject.cpp',
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
'MurmurHash3.cpp',
|
||||
]
|
||||
|
||||
# Suppress warnings from third-party code.
|
||||
if CONFIG['CLANG_CXX']:
|
||||
SOURCES['MurmurHash3.cpp'].flags += ['-Wno-implicit-fallthrough']
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'/js/xpconnect/wrappers',
|
||||
]
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user