merge mozilla-inbound to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2016-01-21 11:49:16 +01:00
commit d6d7f5602f
360 changed files with 5106 additions and 9163 deletions

View File

@ -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

View 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

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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);

View File

@ -11,6 +11,7 @@ GARBAGE += $(MIDL_GENERATED_FILES)
MIDL_INTERFACES = \
Accessible2.idl \
Accessible2_2.idl \
Accessible2_3.idl \
AccessibleAction.idl \
AccessibleApplication.idl \
AccessibleComponent.idl \

View File

@ -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.
*/

View File

@ -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;

View File

@ -1,3 +1,4 @@
[DEFAULT]
[test_general.html]
[test_selection.html]

View 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>

View File

@ -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

View File

@ -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);

View File

@ -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,

View File

@ -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,

View File

@ -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);

View File

@ -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);

View File

@ -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]

View File

@ -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();
});

View File

@ -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");

View File

@ -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");

View File

@ -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");

View File

@ -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();
});

View File

@ -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");

View File

@ -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");

View File

@ -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 = [];

View File

@ -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");

View File

@ -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;

View File

@ -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");

View File

@ -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");

View File

@ -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) {

View File

@ -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();

View File

@ -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);

View File

@ -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;

View File

@ -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'`"])

View File

@ -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);
}

View File

@ -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

View File

@ -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)

View File

@ -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"

View File

@ -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);

View File

@ -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;
{

View File

@ -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;
{

View File

@ -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

View File

@ -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'

View 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>

View File

@ -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
}
}

View File

@ -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;

View File

@ -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

View File

@ -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)) {

View File

@ -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))) {

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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());

View File

@ -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

View File

@ -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;

View 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

View 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__ */

View File

@ -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"

View 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>

View File

@ -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

View File

@ -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',

View File

@ -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;
}

View File

@ -127,7 +127,7 @@ public:
private:
virtual ~nsContentPermissionRequester();
nsCOMPtr<nsPIDOMWindow> mWindow;
nsWeakPtr mWindow;
RefPtr<VisibilityChangeListener> mListener;
};

View File

@ -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,

View File

@ -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:

View File

@ -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!");

View File

@ -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()) {

View File

@ -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!");

View File

@ -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);

View File

@ -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;

View File

@ -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,

View File

@ -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");

View File

@ -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" %

View File

@ -139,8 +139,3 @@ if CONFIG['MOZ_SIMPLEPUSH']:
PYTHON_UNIT_TESTS += [
'mozwebidlcodegen/test/test_mozwebidlcodegen.py',
]
if CONFIG['GNU_CC']:
CXXFLAGS += [
'-Wno-uninitialized',
]

View File

@ -52,8 +52,3 @@ LOCAL_INCLUDES += [
'/js/xpconnect/src',
'/js/xpconnect/wrappers',
]
if CONFIG['GNU_CC']:
CXXFLAGS += [
'-Wno-uninitialized',
]

View File

@ -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));

View File

@ -483,6 +483,7 @@ AutoParentOpResult::~AutoParentOpResult()
break;
}
Unused << PCacheParent::Send__delete__(result.actorParent());
break;
}
default:
// other types do not need clean up

View File

@ -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:

View File

@ -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;
}
}

View File

@ -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',
]

View File

@ -113,7 +113,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=328885
ok(mutationCount == 19, "(20) Mutation listener should have been called! ["+ mutationCount + "]");
}
,false);
synthesizeMouseAtPoint(5, 5, {}, window);
synthesizeMouseAtCenter(inputelement, {}, window);
SimpleTest.finish();
}

View File

@ -1255,19 +1255,21 @@ Geolocation::Init(nsIDOMWindow* aContentDom)
nsresult rv = mPrincipal->GetURI(getter_AddRefs(uri));
NS_ENSURE_SUCCESS(rv, rv);
bool isHttp;
rv = uri->SchemeIs("http", &isHttp);
NS_ENSURE_SUCCESS(rv, rv);
if (uri) {
bool isHttp;
rv = uri->SchemeIs("http", &isHttp);
NS_ENSURE_SUCCESS(rv, rv);
bool isHttps;
rv = uri->SchemeIs("https", &isHttps);
NS_ENSURE_SUCCESS(rv, rv);
bool isHttps;
rv = uri->SchemeIs("https", &isHttps);
NS_ENSURE_SUCCESS(rv, rv);
// Store the protocol to send via telemetry later.
if (isHttp) {
mProtocolType = ProtocolType::HTTP;
} else if (isHttps) {
mProtocolType = ProtocolType::HTTPS;
// Store the protocol to send via telemetry later.
if (isHttp) {
mProtocolType = ProtocolType::HTTP;
} else if (isHttps) {
mProtocolType = ProtocolType::HTTPS;
}
}
}

View File

@ -3806,6 +3806,7 @@ HTMLInputElement::PostHandleEvent(EventChainPostVisitor& aVisitor)
break; // If we are submitting, do not send click event
}
// else fall through and treat Space like click...
MOZ_FALLTHROUGH;
}
case NS_FORM_INPUT_BUTTON:
case NS_FORM_INPUT_RESET:
@ -3834,7 +3835,7 @@ HTMLInputElement::PostHandleEvent(EventChainPostVisitor& aVisitor)
case NS_VK_UP:
case NS_VK_LEFT:
isMovingBack = true;
// FALLTHROUGH
MOZ_FALLTHROUGH;
case NS_VK_DOWN:
case NS_VK_RIGHT:
// Arrow key pressed, focus+select prev/next radio button
@ -5571,14 +5572,14 @@ HTMLInputElement::SubmitNamesValues(nsFormSubmission* aFormSubmission)
const nsTArray<RefPtr<File>>& files = GetFilesInternal();
for (uint32_t i = 0; i < files.Length(); ++i) {
aFormSubmission->AddNameFilePair(name, files[i]);
aFormSubmission->AddNameBlobPair(name, files[i]);
}
if (files.IsEmpty()) {
RefPtr<BlobImpl> blobImpl =
new BlobImplEmptyFile(NS_LITERAL_STRING("application/octet-stream"));
RefPtr<File> file = File::Create(OwnerDoc()->GetInnerWindow(), blobImpl);
aFormSubmission->AddNameFilePair(name, file);
new EmptyBlobImpl(NS_LITERAL_STRING("application/octet-stream"));
RefPtr<Blob> blob = Blob::Create(OwnerDoc()->GetInnerWindow(), blobImpl);
aFormSubmission->AddNameBlobPair(name, blob);
}
return NS_OK;

View File

@ -54,6 +54,17 @@ SendJSWarning(nsIDocument* aDocument,
aWarningArgs, aWarningArgsLen);
}
static void
RetrieveFileName(Blob* aBlob, nsAString& aFilename)
{
MOZ_ASSERT(aBlob);
RefPtr<File> file = aBlob->ToFile();
if (file) {
file->GetName(aFilename);
}
}
// --------------------------------------------------------------------------
class nsFSURLEncoded : public nsEncodingFormSubmission
@ -77,8 +88,8 @@ public:
virtual nsresult AddNameValuePair(const nsAString& aName,
const nsAString& aValue) override;
virtual nsresult AddNameFilePair(const nsAString& aName,
File* aFile) override;
virtual nsresult AddNameBlobPair(const nsAString& aName,
Blob* aBlob) override;
virtual nsresult GetEncodedSubmission(nsIURI* aURI,
nsIInputStream** aPostDataStream)
override;
@ -164,10 +175,10 @@ nsFSURLEncoded::AddIsindex(const nsAString& aValue)
}
nsresult
nsFSURLEncoded::AddNameFilePair(const nsAString& aName,
File* aFile)
nsFSURLEncoded::AddNameBlobPair(const nsAString& aName,
Blob* aBlob)
{
MOZ_ASSERT(aFile);
MOZ_ASSERT(aBlob);
if (!mWarnedFileControl) {
SendJSWarning(mDocument, "ForgotFileEnctypeWarning", nullptr, 0);
@ -175,8 +186,7 @@ nsFSURLEncoded::AddNameFilePair(const nsAString& aName,
}
nsAutoString filename;
aFile->GetName(filename);
RetrieveFileName(aBlob, filename);
return AddNameValuePair(aName, filename);
}
@ -438,10 +448,10 @@ nsFSMultipartFormData::AddNameValuePair(const nsAString& aName,
}
nsresult
nsFSMultipartFormData::AddNameFilePair(const nsAString& aName,
File* aFile)
nsFSMultipartFormData::AddNameBlobPair(const nsAString& aName,
Blob* aBlob)
{
MOZ_ASSERT(aFile);
MOZ_ASSERT(aBlob);
// Encode the control name
nsAutoCString nameStr;
@ -449,13 +459,16 @@ nsFSMultipartFormData::AddNameFilePair(const nsAString& aName,
NS_ENSURE_SUCCESS(rv, rv);
nsAutoString filename16;
aFile->GetName(filename16);
RetrieveFileName(aBlob, filename16);
ErrorResult error;
nsAutoString filepath16;
aFile->GetPath(filepath16, error);
if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult();
RefPtr<File> file = aBlob->ToFile();
if (file) {
file->GetPath(filepath16, error);
if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult();
}
}
if (!filepath16.IsEmpty()) {
@ -469,7 +482,7 @@ nsFSMultipartFormData::AddNameFilePair(const nsAString& aName,
// Get content type
nsAutoString contentType16;
aFile->GetType(contentType16);
aBlob->GetType(contentType16);
if (contentType16.IsEmpty()) {
contentType16.AssignLiteral("application/octet-stream");
}
@ -482,7 +495,7 @@ nsFSMultipartFormData::AddNameFilePair(const nsAString& aName,
// Get input stream
nsCOMPtr<nsIInputStream> fileStream;
aFile->GetInternalStream(getter_AddRefs(fileStream), error);
aBlob->GetInternalStream(getter_AddRefs(fileStream), error);
if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult();
}
@ -517,7 +530,7 @@ nsFSMultipartFormData::AddNameFilePair(const nsAString& aName,
// if we try to update a file that actually do not exist.
if (fileStream) {
ErrorResult error;
uint64_t size = aFile->GetSize(error);
uint64_t size = aBlob->GetSize(error);
if (error.Failed()) {
error.SuppressException();
} else {
@ -590,8 +603,8 @@ public:
virtual nsresult AddNameValuePair(const nsAString& aName,
const nsAString& aValue) override;
virtual nsresult AddNameFilePair(const nsAString& aName,
File* aFile) override;
virtual nsresult AddNameBlobPair(const nsAString& aName,
Blob* aBlob) override;
virtual nsresult GetEncodedSubmission(nsIURI* aURI,
nsIInputStream** aPostDataStream)
override;
@ -614,12 +627,13 @@ nsFSTextPlain::AddNameValuePair(const nsAString& aName,
}
nsresult
nsFSTextPlain::AddNameFilePair(const nsAString& aName,
File* aFile)
nsFSTextPlain::AddNameBlobPair(const nsAString& aName,
Blob* aBlob)
{
nsAutoString filename;
aFile->GetName(filename);
MOZ_ASSERT(aBlob);
nsAutoString filename;
RetrieveFileName(aBlob, filename);
AddNameValuePair(aName, filename);
return NS_OK;
}

View File

@ -19,7 +19,7 @@ class nsIMultiplexInputStream;
namespace mozilla {
namespace dom {
class File;
class Blob;
} // namespace dom
} // namespace mozilla
@ -45,13 +45,14 @@ public:
const nsAString& aValue) = 0;
/**
* Submit a name/file pair
* Submit a name/blob pair
*
* @param aName the name of the parameter
* @param aFile the file to submit. The file's name will be used
* @param aBlob the blob to submit. The file's name will be used if the Blob
* is actually a File, otherwise 'blob' string is used instead.
*/
virtual nsresult AddNameFilePair(const nsAString& aName,
mozilla::dom::File* aFile) = 0;
virtual nsresult AddNameBlobPair(const nsAString& aName,
mozilla::dom::Blob* aBlob) = 0;
/**
* Reports whether the instance supports AddIsindex().
@ -159,8 +160,8 @@ public:
virtual nsresult AddNameValuePair(const nsAString& aName,
const nsAString& aValue) override;
virtual nsresult AddNameFilePair(const nsAString& aName,
mozilla::dom::File* aFile) override;
virtual nsresult AddNameBlobPair(const nsAString& aName,
mozilla::dom::Blob* aBlob) override;
virtual nsresult GetEncodedSubmission(nsIURI* aURI,
nsIInputStream** aPostDataStream) override;

View File

@ -77,15 +77,11 @@ function testSet() {
is(f.getAll("other")[0], "value4", "set() should replace existing entries.");
}
function testIterate() {
todo(false, "Implement this in Bug 1085284.");
}
function testFilename() {
var f = new FormData();
// Spec says if a Blob (which is not a File) is added, the name parameter is set to "blob".
f.append("blob", new Blob(["hi"]));
is(f.get("blob").name, "blob", "Blob's filename should be blob.");
ok(f.get("blob") instanceof Blob, "We should have a blob back.");
// If a filename is passed, that should replace the original.
f.append("blob2", new Blob(["hi"]), "blob2.txt");
@ -209,7 +205,6 @@ function runTest(doneCb) {
testGetAll();
testDelete();
testSet();
testIterate();
testFilename();
testIterable();
// Finally, send an XHR and verify the response matches.

View File

@ -590,7 +590,7 @@ var expectedAugment = [
//{ name: "aNameUndef", value: "undefined" },
];
function checkMPSubmission(sub, expected, test) {
function checkMPSubmission(sub, expected, test, isFormData = false) {
function getPropCount(o) {
var x, l = 0;
for (x in o) ++l;
@ -625,7 +625,7 @@ function checkMPSubmission(sub, expected, test) {
else {
is(sub[i].headers["Content-Disposition"],
"form-data; name=\"" + mpquote(expected[i].name) + "\"; filename=\"" +
mpquote(expected[i].fileName) + "\"",
mpquote(expected[i].fileName != "" || !isFormData ? expected[i].fileName : "blob") + "\"",
"Correct name in " + test);
is(sub[i].headers["Content-Type"],
expected[i].contentType,
@ -782,14 +782,14 @@ function runTest() {
xhr.open("POST", "form_submit_server.sjs");
xhr.send(new FormData(form));
yield undefined; // Wait for XHR load
checkMPSubmission(JSON.parse(xhr.responseText), expectedSub, "send form using XHR and FormData");
checkMPSubmission(JSON.parse(xhr.responseText), expectedSub, "send form using XHR and FormData", true);
// Send disabled form using XHR and FormData
setDisabled(document.querySelectorAll("input, select, textarea"), true);
xhr.open("POST", "form_submit_server.sjs");
xhr.send(new FormData(form));
yield undefined;
checkMPSubmission(JSON.parse(xhr.responseText), [], "send disabled form using XHR and FormData");
checkMPSubmission(JSON.parse(xhr.responseText), [], "send disabled form using XHR and FormData", true);
setDisabled(document.querySelectorAll("input, select, textarea"), false);
// Send FormData
@ -804,7 +804,7 @@ function runTest() {
xhr.open("POST", "form_submit_server.sjs");
xhr.send(fd);
yield undefined;
checkMPSubmission(JSON.parse(xhr.responseText), expectedAugment, "send FormData");
checkMPSubmission(JSON.parse(xhr.responseText), expectedAugment, "send FormData", true);
// Augment <form> using FormData
fd = new FormData(form);
@ -813,7 +813,7 @@ function runTest() {
xhr.send(fd);
yield undefined;
checkMPSubmission(JSON.parse(xhr.responseText),
expectedSub.concat(expectedAugment), "send augmented FormData");
expectedSub.concat(expectedAugment), "send augmented FormData", true);
SimpleTest.finish();
yield undefined;

View File

@ -23228,8 +23228,9 @@ NormalJSRuntime::Init()
JSAutoRequest ar(mContext);
JS::CompartmentOptions options;
mGlobal = JS_NewGlobalObject(mContext, &kGlobalClass, nullptr,
JS::FireOnNewGlobalHook);
JS::FireOnNewGlobalHook, options);
if (NS_WARN_IF(!mGlobal)) {
return false;
}

View File

@ -49,7 +49,7 @@ interface nsIJSRAIIHelper;
interface nsIContentPermissionRequest;
interface nsIObserver;
[scriptable, uuid(7846c43d-e131-40a6-8417-3be2c7e11df1)]
[scriptable, uuid(ca6a458c-82e7-4979-886e-6d214eac6f0b)]
interface nsIDOMWindowUtils : nsISupports {
/**
@ -1458,6 +1458,11 @@ interface nsIDOMWindowUtils : nsISupports {
*/
bool flushApzRepaints();
/**
* Ask APZ to pan and zoom to the focused input element.
*/
void zoomToFocusedInput();
/**
* Method for testing StyleAnimationValue::ComputeDistance.
*

View File

@ -2813,8 +2813,7 @@ POfflineCacheUpdateChild*
ContentChild::AllocPOfflineCacheUpdateChild(const URIParams& manifestURI,
const URIParams& documentURI,
const PrincipalInfo& aLoadingPrincipalInfo,
const bool& stickDocument,
const TabId& aTabId)
const bool& stickDocument)
{
NS_RUNTIMEABORT("unused");
return nullptr;

View File

@ -574,8 +574,7 @@ public:
AllocPOfflineCacheUpdateChild(const URIParams& manifestURI,
const URIParams& documentURI,
const PrincipalInfo& aLoadingPrincipalInfo,
const bool& stickDocument,
const TabId& aTabId) override;
const bool& stickDocument) override;
virtual bool
DeallocPOfflineCacheUpdateChild(POfflineCacheUpdateChild* offlineCacheUpdate) override;

View File

@ -1237,6 +1237,8 @@ ContentParent::CreateBrowserOrApp(const TabContext& aContext,
Element* aFrameElement,
ContentParent* aOpenerContentParent)
{
PROFILER_LABEL_FUNC(js::ProfileEntry::Category::OTHER);
if (!sCanLaunchSubprocesses) {
return nullptr;
}
@ -2386,6 +2388,8 @@ ContentParent::InitializeMembers()
bool
ContentParent::LaunchSubprocess(ProcessPriority aInitialPriority /* = PROCESS_PRIORITY_FOREGROUND */)
{
PROFILER_LABEL_FUNC(js::ProfileEntry::Category::OTHER);
std::vector<std::string> extraArgs;
if (mIsNuwaProcess) {
extraArgs.push_back("-nuwa");
@ -3642,6 +3646,8 @@ ContentParent::ForceKillTimerCallback(nsITimer* aTimer, void* aClosure)
void
ContentParent::KillHard(const char* aReason)
{
PROFILER_LABEL_FUNC(js::ProfileEntry::Category::OTHER);
// On Windows, calling KillHard multiple times causes problems - the
// process handle becomes invalid on the first call, causing a second call
// to crash our process - more details in bug 890840.
@ -5240,17 +5246,10 @@ mozilla::docshell::POfflineCacheUpdateParent*
ContentParent::AllocPOfflineCacheUpdateParent(const URIParams& aManifestURI,
const URIParams& aDocumentURI,
const PrincipalInfo& aLoadingPrincipalInfo,
const bool& aStickDocument,
const TabId& aTabId)
const bool& aStickDocument)
{
TabContext tabContext;
if (!ContentProcessManager::GetSingleton()->
GetTabContextByProcessAndTabId(this->ChildID(), aTabId, &tabContext)) {
return nullptr;
}
RefPtr<mozilla::docshell::OfflineCacheUpdateParent> update =
new mozilla::docshell::OfflineCacheUpdateParent(
tabContext.OriginAttributesRef());
new mozilla::docshell::OfflineCacheUpdateParent();
// Use this reference as the IPDL reference.
return update.forget().take();
}
@ -5260,8 +5259,7 @@ ContentParent::RecvPOfflineCacheUpdateConstructor(POfflineCacheUpdateParent* aAc
const URIParams& aManifestURI,
const URIParams& aDocumentURI,
const PrincipalInfo& aLoadingPrincipal,
const bool& aStickDocument,
const TabId& aTabId)
const bool& aStickDocument)
{
MOZ_ASSERT(aActor);

View File

@ -457,16 +457,14 @@ public:
AllocPOfflineCacheUpdateParent(const URIParams& aManifestURI,
const URIParams& aDocumentURI,
const PrincipalInfo& aLoadingPrincipalInfo,
const bool& aStickDocument,
const TabId& aTabId) override;
const bool& aStickDocument) override;
virtual bool
RecvPOfflineCacheUpdateConstructor(POfflineCacheUpdateParent* aActor,
const URIParams& aManifestURI,
const URIParams& aDocumentURI,
const PrincipalInfo& aLoadingPrincipal,
const bool& stickDocument,
const TabId& aTabId) override;
const bool& stickDocument) override;
virtual bool
DeallocPOfflineCacheUpdateParent(POfflineCacheUpdateParent* aActor) override;

View File

@ -420,7 +420,7 @@ parent:
* Instructs the TabParent to forward a request to zoom to a rect given in
* CSS pixels. This rect is relative to the document.
*/
ZoomToRect(uint32_t aPresShellId, ViewID aViewId, CSSRect aRect);
ZoomToRect(uint32_t aPresShellId, ViewID aViewId, CSSRect aRect, uint32_t aFlags);
/**
* We know for sure that content has either preventDefaulted or not

View File

@ -1085,8 +1085,7 @@ parent:
* To identify which tab owns the app.
*/
POfflineCacheUpdate(URIParams manifestURI, URIParams documentURI,
PrincipalInfo loadingPrincipal, bool stickDocument,
TabId tabId);
PrincipalInfo loadingPrincipal, bool stickDocument);
/**
* Sets "offline-app" permission for the principal. Called when we hit

View File

@ -1691,7 +1691,7 @@ TabChild::RecvHandleDoubleTap(const CSSPoint& aPoint, const Modifiers& aModifier
ViewID viewId;
if (APZCCallbackHelper::GetOrCreateScrollIdentifiers(
document->GetDocumentElement(), &presShellId, &viewId)) {
SendZoomToRect(presShellId, viewId, zoomToRect);
SendZoomToRect(presShellId, viewId, zoomToRect, DEFAULT_BEHAVIOR);
}
return true;

View File

@ -2798,10 +2798,11 @@ TabParent::RecvBrowserFrameOpenWindow(PBrowserParent* aOpener,
bool
TabParent::RecvZoomToRect(const uint32_t& aPresShellId,
const ViewID& aViewId,
const CSSRect& aRect)
const CSSRect& aRect,
const uint32_t& aFlags)
{
if (RenderFrameParent* rfp = GetRenderFrame()) {
rfp->ZoomToRect(aPresShellId, aViewId, aRect);
rfp->ZoomToRect(aPresShellId, aViewId, aRect, aFlags);
}
return true;
}

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