Merge mozilla-central to fx-team

This commit is contained in:
Carsten "Tomcat" Book 2016-03-18 16:11:32 +01:00
commit 4bfd2c3573
393 changed files with 7371 additions and 2587 deletions

21
b2g/common.configure Normal file
View File

@ -0,0 +1,21 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# Truetype fonts for B2G
# ==============================================================
option(env='MOZTTDIR', nargs=1, help='Path to truetype fonts for B2G')
@depends('MOZTTDIR')
def mozttdir(value):
if value:
path = value[0]
if not os.path.isdir(path):
error('MOZTTDIR "%s" is not a valid directory' % path)
set_config('MOZTTDIR', path)
set_define('PACKAGE_MOZTT', '1')
include('../toolkit/moz.configure')

View File

@ -4,4 +4,4 @@
# 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('../../toolkit/moz.configure')
include('../common/moz.configure')

View File

@ -4,4 +4,4 @@
# 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('../../toolkit/moz.configure')
include('../common.configure')

View File

@ -11,4 +11,4 @@ def gonkdir(value):
return value[0] if value else ''
include('../toolkit/moz.configure')
include('common.configure')

View File

@ -193,6 +193,11 @@ extensions.registerSchemaAPI("windows", null, (extension, context) => {
WindowManager.setState(window, updateInfo.state);
}
if (updateInfo.drawAttention) {
// Bug 1257497 - Firefox can't cancel attention actions.
window.getAttention();
}
// TODO: All the other properties, focused=false...
return Promise.resolve(WindowManager.convert(extension, window));

View File

@ -409,7 +409,6 @@
"description": "If true, brings the window to the front. If false, brings the next window in the z-order to the front."
},
"drawAttention": {
"unsupported": true,
"type": "boolean",
"optional": true,
"description": "If true, causes the window to be displayed in a manner that draws the user's attention to the window, without changing the focused window. The effect lasts until the user changes focus to the window. This option has no effect if the window already has focus. Set to false to cancel a previous draw attention request."

View File

@ -125,3 +125,26 @@ add_task(function* testWindowUpdate() {
yield extension.awaitFinish("window-update");
yield extension.unload();
});
add_task(function* () {
let window2 = yield BrowserTestUtils.openNewBrowserWindow();
let extension = ExtensionTestUtils.loadExtension({
background: function() {
browser.windows.getAll(undefined, function(wins) {
browser.test.assertEq(wins.length, 2, "should have two windows");
let unfocused = wins.find(win => !win.focused);
browser.windows.update(unfocused.id, {drawAttention: true}, function() {
browser.test.sendMessage("check");
});
});
},
});
yield Promise.all([extension.startup(), extension.awaitMessage("check")]);
yield extension.unload();
yield BrowserTestUtils.closeWindow(window2);
});

View File

@ -255,11 +255,20 @@ def wanted_mozconfig_variables(help):
'DSYMUTIL',
'EXTERNAL_SOURCE_DIR',
'GENISOIMAGE',
'L10NBASEDIR',
'MOZILLABUILD',
'MOZ_ARTIFACT_BUILDS',
'MOZ_BUILD_APP',
'MOZ_CALLGRIND',
'MOZ_DMD',
'MOZ_FMP4',
'MOZ_INSTRUMENT_EVENT_LOOP',
'MOZ_INSTRUMENTS',
'MOZ_JPROF',
'MOZ_PROFILING',
'MOZ_USE_SYSTRACE',
'MOZ_VTUNE',
'MOZTTDIR',
'PERL',
'RPMBUILD',
'TAR',
@ -417,6 +426,15 @@ def split_triplet(triplet):
)
@template
@advanced
def config_sub(shell, triplet):
import subprocess
config_sub = os.path.join(os.path.dirname(__file__), '..',
'autoconf', 'config.sub')
return subprocess.check_output([shell, config_sub, triplet]).strip()
@depends('--host', shell)
@advanced
def host(value, shell):
@ -428,14 +446,14 @@ def host(value, shell):
else:
host = value[0]
return split_triplet(host)
return split_triplet(config_sub(shell, host))
@depends('--target', host)
def target(value, host):
@depends('--target', host, shell)
def target(value, host, shell):
if not value:
return host
return split_triplet(value[0])
return split_triplet(config_sub(shell, value[0]))
@depends(host, target)

View File

@ -178,7 +178,6 @@ def old_configure_options(*options):
'--enable-b2g-camera',
'--enable-b2g-ril',
'--enable-bundled-fonts',
'--enable-callgrind',
'--enable-chrome-format',
'--enable-clang-plugin',
'--enable-content-sandbox',
@ -192,7 +191,6 @@ def old_configure_options(*options):
'--enable-debug-js-modules',
'--enable-debug-symbols',
'--enable-directshow',
'--enable-dmd',
'--enable-dtrace',
'--enable-dump-painting',
'--enable-elf-hack',
@ -210,13 +208,11 @@ def old_configure_options(*options):
'--enable-hardware-aec-ns',
'--enable-icf',
'--enable-install-strip',
'--enable-instruments',
'--enable-ion',
'--enable-ios-target',
'--enable-ipdl-tests',
'--enable-jemalloc',
'--enable-jitspew',
'--enable-jprof',
'--enable-libjpeg-turbo',
'--enable-libproxy',
'--enable-llvm-hacks',
@ -246,7 +242,6 @@ def old_configure_options(*options):
'--enable-pref-extensions',
'--enable-printing',
'--enable-profilelocking',
'--enable-profiling',
'--enable-pulseaudio',
'--enable-raw',
'--enable-readline',
@ -274,7 +269,6 @@ def old_configure_options(*options):
'--enable-system-hunspell',
'--enable-system-pixman',
'--enable-system-sqlite',
'--enable-systrace',
'--enable-tasktracer',
'--enable-tests',
'--enable-thread-sanitizer',
@ -288,7 +282,6 @@ def old_configure_options(*options):
'--enable-url-classifier',
'--enable-valgrind',
'--enable-verify-mar',
'--enable-vtune',
'--enable-warnings-as-errors',
'--enable-webapp-runtime',
'--enable-webrtc',
@ -335,7 +328,6 @@ def old_configure_options(*options):
'--with-ios-sdk',
'--with-java-bin-path',
'--with-jitreport-granularity',
'--with-l10n-base',
'--with-linux-headers',
'--with-macbundlename-prefix',
'--with-macos-private-frameworks',

View File

@ -41,13 +41,13 @@ skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) || toolkit == 'and
[test_child.html]
[test_grandchild.html]
[test_not-opener.html]
skip-if = buildapp == 'b2g' || (toolkit == 'android' && processor == 'x86') #x86 only
skip-if = buildapp == 'b2g'
[test_opener.html]
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
[test_popup-navigates-children.html]
skip-if = buildapp == 'b2g' # b2g(Needs multiple window.open support, also uses docshelltreenode) b2g-debug(Needs multiple window.open support, also uses docshelltreenode) b2g-desktop(Needs multiple window.open support, also uses docshelltreenode)
[test_reserved.html]
skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) || android_version == '10' || android_version == '18' || (e10s && debug && os == 'win') #too slow on Android 2.3 and 4.3 aws only; bug 1030403
skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) || (toolkit == 'android') || (e10s && debug && os == 'win') #too slow on Android 4.3 aws only; bug 1030403
[test_sessionhistory.html]
skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) || toolkit == 'android' #RANDOM # b2g-debug(Perma-orange on debug emulator builds) b2g-desktop(Bug 931116, b2g desktop specific, initial triage)
[test_sibling-matching-parent.html]

View File

@ -573,15 +573,15 @@ KeyframeEffectReadOnly::ComposeStyle(RefPtr<AnimValuesStyleRule>& aStyleRule,
// FIXME: Maybe cache the current segment?
const AnimationPropertySegment *segment = prop.mSegments.Elements(),
*segmentEnd = segment + prop.mSegments.Length();
while (segment->mToKey < computedTiming.mProgress.Value()) {
MOZ_ASSERT(segment->mFromKey < segment->mToKey, "incorrect keys");
while (segment->mToKey <= computedTiming.mProgress.Value()) {
MOZ_ASSERT(segment->mFromKey <= segment->mToKey, "incorrect keys");
if ((segment+1) == segmentEnd) {
break;
}
++segment;
MOZ_ASSERT(segment->mFromKey == (segment-1)->mToKey, "incorrect keys");
}
MOZ_ASSERT(segment->mFromKey < segment->mToKey, "incorrect keys");
MOZ_ASSERT(segment->mFromKey <= segment->mToKey, "incorrect keys");
MOZ_ASSERT(segment >= prop.mSegments.Elements() &&
size_t(segment - prop.mSegments.Elements()) <
prop.mSegments.Length(),
@ -592,6 +592,18 @@ KeyframeEffectReadOnly::ComposeStyle(RefPtr<AnimValuesStyleRule>& aStyleRule,
aStyleRule = new AnimValuesStyleRule();
}
StyleAnimationValue* val = aStyleRule->AddEmptyValue(prop.mProperty);
// Special handling for zero-length segments
if (segment->mToKey == segment->mFromKey) {
if (computedTiming.mProgress.Value() < 0) {
*val = segment->mFromValue;
} else {
*val = segment->mToValue;
}
continue;
}
double positionInSegment =
(computedTiming.mProgress.Value() - segment->mFromKey) /
(segment->mToKey - segment->mFromKey);
@ -599,8 +611,6 @@ KeyframeEffectReadOnly::ComposeStyle(RefPtr<AnimValuesStyleRule>& aStyleRule,
ComputedTimingFunction::GetPortion(segment->mTimingFunction,
positionInSegment);
StyleAnimationValue *val = aStyleRule->AddEmptyValue(prop.mProperty);
#ifdef DEBUG
bool result =
#endif
@ -1789,6 +1799,93 @@ KeyframeEffectReadOnly::GetTarget(
}
}
static void
CreatePropertyValue(nsCSSProperty aProperty,
float aOffset,
const Maybe<ComputedTimingFunction>& aTimingFunction,
const StyleAnimationValue& aValue,
AnimationPropertyValueDetails& aResult)
{
aResult.mOffset = aOffset;
nsString stringValue;
StyleAnimationValue::UncomputeValue(aProperty, aValue, stringValue);
aResult.mValue = stringValue;
if (aTimingFunction) {
aResult.mEasing.Construct();
aTimingFunction->AppendToString(aResult.mEasing.Value());
} else {
aResult.mEasing.Construct(NS_LITERAL_STRING("linear"));
}
aResult.mComposite = CompositeOperation::Replace;
}
void
KeyframeEffectReadOnly::GetProperties(
nsTArray<AnimationPropertyDetails>& aProperties,
ErrorResult& aRv) const
{
for (const AnimationProperty& property : mProperties) {
AnimationPropertyDetails propertyDetails;
propertyDetails.mProperty =
NS_ConvertASCIItoUTF16(nsCSSProps::GetStringValue(property.mProperty));
propertyDetails.mRunningOnCompositor = property.mIsRunningOnCompositor;
nsXPIDLString localizedString;
if (property.mPerformanceWarning &&
property.mPerformanceWarning->ToLocalizedString(localizedString)) {
propertyDetails.mWarning.Construct(localizedString);
}
if (!propertyDetails.mValues.SetCapacity(property.mSegments.Length(),
mozilla::fallible)) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
return;
}
for (size_t segmentIdx = 0, segmentLen = property.mSegments.Length();
segmentIdx < segmentLen;
segmentIdx++)
{
const AnimationPropertySegment& segment = property.mSegments[segmentIdx];
binding_detail::FastAnimationPropertyValueDetails fromValue;
CreatePropertyValue(property.mProperty, segment.mFromKey,
segment.mTimingFunction, segment.mFromValue,
fromValue);
// We don't apply timing functions for zero-length segments, so
// don't return one here.
if (segment.mFromKey == segment.mToKey) {
fromValue.mEasing.Reset();
}
// The following won't fail since we have already allocated the capacity
// above.
propertyDetails.mValues.AppendElement(fromValue, mozilla::fallible);
// Normally we can ignore the to-value for this segment since it is
// identical to the from-value from the next segment. However, we need
// to add it if either:
// a) this is the last segment, or
// b) the next segment's from-value differs.
if (segmentIdx == segmentLen - 1 ||
property.mSegments[segmentIdx + 1].mFromValue != segment.mToValue) {
binding_detail::FastAnimationPropertyValueDetails toValue;
CreatePropertyValue(property.mProperty, segment.mToKey,
Nothing(), segment.mToValue, toValue);
// It doesn't really make sense to have a timing function on the
// last property value or before a sudden jump so we just drop the
// easing property altogether.
toValue.mEasing.Reset();
propertyDetails.mValues.AppendElement(toValue, mozilla::fallible);
}
}
aProperties.AppendElement(propertyDetails);
}
}
void
KeyframeEffectReadOnly::GetFrames(JSContext*& aCx,
nsTArray<JSObject*>& aResult,
@ -1887,32 +1984,6 @@ KeyframeEffectReadOnly::GetFrames(JSContext*& aCx,
}
}
void
KeyframeEffectReadOnly::GetPropertyState(
nsTArray<AnimationPropertyState>& aStates) const
{
for (const AnimationProperty& property : mProperties) {
// Bug 1252730: We should also expose this winsInCascade as well.
if (!property.mWinsInCascade) {
continue;
}
AnimationPropertyState state;
state.mProperty.Construct(
NS_ConvertASCIItoUTF16(nsCSSProps::GetStringValue(property.mProperty)));
state.mRunningOnCompositor.Construct(property.mIsRunningOnCompositor);
nsXPIDLString localizedString;
if (property.mPerformanceWarning &&
property.mPerformanceWarning->ToLocalizedString(localizedString)) {
state.mWarning.Construct(localizedString);
}
aStates.AppendElement(state);
}
}
/* static */ const TimeDuration
KeyframeEffectReadOnly::OverflowRegionRefreshInterval()
{

View File

@ -46,7 +46,7 @@ class UnrestrictedDoubleOrKeyframeAnimationOptions;
class UnrestrictedDoubleOrKeyframeEffectOptions;
enum class IterationCompositeOperation : uint32_t;
enum class CompositeOperation : uint32_t;
struct AnimationPropertyState;
struct AnimationPropertyDetails;
}
/**
@ -209,6 +209,8 @@ public:
void GetFrames(JSContext*& aCx,
nsTArray<JSObject*>& aResult,
ErrorResult& aRv);
void GetProperties(nsTArray<AnimationPropertyDetails>& aProperties,
ErrorResult& aRv) const;
// Temporary workaround to return both the target element and pseudo-type
// until we implement PseudoElement (bug 1174575).
@ -304,8 +306,6 @@ public:
bool IsRunningOnCompositor() const;
void SetIsRunningOnCompositor(nsCSSProperty aProperty, bool aIsRunning);
void GetPropertyState(nsTArray<AnimationPropertyState>& aStates) const;
// Returns true if this effect, applied to |aFrame|, contains properties
// that mean we shouldn't run transform compositor animations on this element.
//

View File

@ -7,6 +7,7 @@ support-files =
# file_animate_xrays.html needs to go in mochitest.ini since it is served
# over HTTP
[chrome/test_animation_observers.html]
[chrome/test_animation_properties.html]
[chrome/test_animation_property_state.html]
[chrome/test_generated_content_getAnimations.html]
[chrome/test_restyles.html]

View File

@ -0,0 +1,503 @@
<!doctype html>
<head>
<meta charset=utf-8>
<title>Bug 1254419 - Test the values returned by
KeyframeEffectReadOnly.getProperties()</title>
<script type="application/javascript" src="../testharness.js"></script>
<script type="application/javascript" src="../testharnessreport.js"></script>
<script type="application/javascript" src="../testcommon.js"></script>
</head>
<body>
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1254419"
target="_blank">Mozilla Bug 1254419</a>
<div id="log"></div>
<style>
div {
font-size: 10px; /* For calculating em-based units */
}
</style>
<script>
'use strict';
function assert_properties_equal(actual, expected) {
assert_equals(actual.length, expected.length);
var compareProperties = (a, b) =>
a.property == b.property ? 0 : (a.property < b.property ? -1 : 1);
var sortedActual = actual.sort(compareProperties);
var sortedExpected = expected.sort(compareProperties);
// We want to serialize the values in the following form:
//
// { offset: 0, easing: linear, composite: replace, value: 5px }, ...
//
// So that we can just compare strings and, in the failure case,
// easily see where the differences lie.
var serializeMember = value => {
return typeof value === 'undefined' ? '<not set>' : value;
}
var serializeValues = values =>
values.map(value =>
'{ ' +
[ 'offset', 'value', 'easing', 'composite' ].map(
member => `${member}: ${serializeMember(value[member])}`
).join(', ') +
' }')
.join(', ');
for (var i = 0; i < sortedActual.length; i++) {
assert_equals(sortedActual[i].property,
sortedExpected[i].property,
'CSS property name should match');
assert_equals(serializeValues(sortedActual[i].values),
serializeValues(sortedExpected[i].values),
`Values arrays do not match for `
+ `${sortedActual[i].property} property`);
}
}
// Shorthand for constructing a value object
function value(offset, value, composite, easing) {
return { offset: offset, value: value, easing: easing, composite: composite };
}
var gTests = [
// ---------------------------------------------------------------------
//
// Tests for property-indexed specifications
//
// ---------------------------------------------------------------------
{ desc: 'a one-property two-value property-indexed specification',
frames: { left: ['10px', '20px'] },
expected: [ { property: 'left',
values: [ value(0, '10px', 'replace', 'linear'),
value(1, '20px', 'replace') ] } ]
},
{ desc: 'a one-shorthand-property two-value property-indexed'
+ ' specification',
frames: { margin: ['10px', '10px 20px 30px 40px'] },
expected: [ { property: 'margin-top',
values: [ value(0, '10px', 'replace', 'linear'),
value(1, '10px', 'replace') ] },
{ property: 'margin-right',
values: [ value(0, '10px', 'replace', 'linear'),
value(1, '20px', 'replace') ] },
{ property: 'margin-bottom',
values: [ value(0, '10px', 'replace', 'linear'),
value(1, '30px', 'replace') ] },
{ property: 'margin-left',
values: [ value(0, '10px', 'replace', 'linear'),
value(1, '40px', 'replace') ] } ]
},
{ desc: 'a two-property (one shorthand and one of its longhand'
+ ' components) two-value property-indexed specification',
frames: { marginTop: ['50px', '60px'],
margin: ['10px', '10px 20px 30px 40px'] },
expected: [ { property: 'margin-top',
values: [ value(0, '50px', 'replace', 'linear'),
value(1, '60px', 'replace') ] },
{ property: 'margin-right',
values: [ value(0, '10px', 'replace', 'linear'),
value(1, '20px', 'replace') ] },
{ property: 'margin-bottom',
values: [ value(0, '10px', 'replace', 'linear'),
value(1, '30px', 'replace') ] },
{ property: 'margin-left',
values: [ value(0, '10px', 'replace', 'linear'),
value(1, '40px', 'replace') ] } ]
},
{ desc: 'a two-property property-indexed specification with different'
+ ' numbers of values',
frames: { left: ['10px', '20px', '30px'],
top: ['40px', '50px'] },
expected: [ { property: 'left',
values: [ value(0, '10px', 'replace', 'linear'),
value(0.5, '20px', 'replace', 'linear'),
value(1, '30px', 'replace') ] },
{ property: 'top',
values: [ value(0, '40px', 'replace', 'linear'),
value(1, '50px', 'replace') ] } ]
},
{ desc: 'a property-indexed specification with an invalid value',
frames: { left: ['10px', '20px', '30px', '40px', '50px'],
top: ['15px', '25px', 'invalid', '45px', '55px'] },
expected: [ { property: 'left',
values: [ value(0, '10px', 'replace', 'linear'),
value(0.25, '20px', 'replace', 'linear'),
value(0.5, '30px', 'replace', 'linear'),
value(0.75, '40px', 'replace', 'linear'),
value(1, '50px', 'replace') ] },
{ property: 'top',
values: [ value(0, '15px', 'replace', 'linear'),
value(0.25, '25px', 'replace', 'linear'),
value(0.75, '45px', 'replace', 'linear'),
value(1, '55px', 'replace') ] } ]
},
{ desc: 'a one-property two-value property-indexed specification that'
+ ' needs to stringify its values',
frames: { opacity: [0, 1] },
expected: [ { property: 'opacity',
values: [ value(0, '0', 'replace', 'linear'),
value(1, '1', 'replace') ] } ]
},
{ desc: 'a property-indexed keyframe where a lesser shorthand precedes'
+ ' a greater shorthand',
frames: { borderLeft: [ '1px solid rgb(1, 2, 3)',
'2px solid rgb(4, 5, 6)' ],
border: [ '3px dotted rgb(7, 8, 9)',
'4px dashed rgb(10, 11, 12)' ] },
expected: [ { property: 'border-bottom-color',
values: [ value(0, 'rgb(7, 8, 9)', 'replace', 'linear'),
value(1, 'rgb(10, 11, 12)', 'replace') ] },
{ property: 'border-left-color',
values: [ value(0, 'rgb(1, 2, 3)', 'replace', 'linear'),
value(1, 'rgb(4, 5, 6)', 'replace') ] },
{ property: 'border-right-color',
values: [ value(0, 'rgb(7, 8, 9)', 'replace', 'linear'),
value(1, 'rgb(10, 11, 12)', 'replace') ] },
{ property: 'border-top-color',
values: [ value(0, 'rgb(7, 8, 9)', 'replace', 'linear'),
value(1, 'rgb(10, 11, 12)', 'replace') ] },
{ property: 'border-bottom-width',
values: [ value(0, '3px', 'replace', 'linear'),
value(1, '4px', 'replace') ] },
{ property: 'border-left-width',
values: [ value(0, '1px', 'replace', 'linear'),
value(1, '2px', 'replace') ] },
{ property: 'border-right-width',
values: [ value(0, '3px', 'replace', 'linear'),
value(1, '4px', 'replace') ] },
{ property: 'border-top-width',
values: [ value(0, '3px', 'replace', 'linear'),
value(1, '4px', 'replace') ] } ]
},
{ desc: 'a property-indexed keyframe where a greater shorthand precedes'
+ ' a lesser shorthand',
frames: { border: [ '3px dotted rgb(7, 8, 9)',
'4px dashed rgb(10, 11, 12)' ],
borderLeft: [ '1px solid rgb(1, 2, 3)',
'2px solid rgb(4, 5, 6)' ] },
expected: [ { property: 'border-bottom-color',
values: [ value(0, 'rgb(7, 8, 9)', 'replace', 'linear'),
value(1, 'rgb(10, 11, 12)', 'replace') ] },
{ property: 'border-left-color',
values: [ value(0, 'rgb(1, 2, 3)', 'replace', 'linear'),
value(1, 'rgb(4, 5, 6)', 'replace') ] },
{ property: 'border-right-color',
values: [ value(0, 'rgb(7, 8, 9)', 'replace', 'linear'),
value(1, 'rgb(10, 11, 12)', 'replace') ] },
{ property: 'border-top-color',
values: [ value(0, 'rgb(7, 8, 9)', 'replace', 'linear'),
value(1, 'rgb(10, 11, 12)', 'replace') ] },
{ property: 'border-bottom-width',
values: [ value(0, '3px', 'replace', 'linear'),
value(1, '4px', 'replace') ] },
{ property: 'border-left-width',
values: [ value(0, '1px', 'replace', 'linear'),
value(1, '2px', 'replace') ] },
{ property: 'border-right-width',
values: [ value(0, '3px', 'replace', 'linear'),
value(1, '4px', 'replace') ] },
{ property: 'border-top-width',
values: [ value(0, '3px', 'replace', 'linear'),
value(1, '4px', 'replace') ] } ]
},
// ---------------------------------------------------------------------
//
// Tests for keyframe sequences
//
// ---------------------------------------------------------------------
{ desc: 'a keyframe sequence specification with repeated values at'
+ ' offset 0/1 with different easings',
frames: [ { offset: 0.0, left: '100px', easing: 'ease' },
{ offset: 0.0, left: '200px', easing: 'ease' },
{ offset: 0.5, left: '300px', easing: 'linear' },
{ offset: 1.0, left: '400px', easing: 'ease-out' },
{ offset: 1.0, left: '500px', easing: 'step-end' } ],
expected: [ { property: 'left',
values: [ value(0, '100px', 'replace'),
value(0, '200px', 'replace', 'ease'),
value(0.5, '300px', 'replace', 'linear'),
value(1, '400px', 'replace'),
value(1, '500px', 'replace') ] } ]
},
{ desc: 'a one-property two-keyframe sequence',
frames: [ { offset: 0, left: '10px' },
{ offset: 1, left: '20px' } ],
expected: [ { property: 'left',
values: [ value(0, '10px', 'replace', 'linear'),
value(1, '20px', 'replace') ] } ]
},
{ desc: 'a two-property two-keyframe sequence',
frames: [ { offset: 0, left: '10px', top: '30px' },
{ offset: 1, left: '20px', top: '40px' } ],
expected: [ { property: 'left',
values: [ value(0, '10px', 'replace', 'linear'),
value(1, '20px', 'replace') ] },
{ property: 'top',
values: [ value(0, '30px', 'replace', 'linear'),
value(1, '40px', 'replace') ] } ]
},
{ desc: 'a one shorthand property two-keyframe sequence',
frames: [ { offset: 0, margin: '10px' },
{ offset: 1, margin: '20px 30px 40px 50px' } ],
expected: [ { property: 'margin-top',
values: [ value(0, '10px', 'replace', 'linear'),
value(1, '20px', 'replace') ] },
{ property: 'margin-right',
values: [ value(0, '10px', 'replace', 'linear'),
value(1, '30px', 'replace') ] },
{ property: 'margin-bottom',
values: [ value(0, '10px', 'replace', 'linear'),
value(1, '40px', 'replace') ] },
{ property: 'margin-left',
values: [ value(0, '10px', 'replace', 'linear'),
value(1, '50px', 'replace') ] } ]
},
{ desc: 'a two-property (a shorthand and one of its component longhands)'
+ ' two-keyframe sequence',
frames: [ { offset: 0, margin: '10px', marginTop: '20px' },
{ offset: 1, marginTop: '70px',
margin: '30px 40px 50px 60px' } ],
expected: [ { property: 'margin-top',
values: [ value(0, '20px', 'replace', 'linear'),
value(1, '70px', 'replace') ] },
{ property: 'margin-right',
values: [ value(0, '10px', 'replace', 'linear'),
value(1, '40px', 'replace') ] },
{ property: 'margin-bottom',
values: [ value(0, '10px', 'replace', 'linear'),
value(1, '50px', 'replace') ] },
{ property: 'margin-left',
values: [ value(0, '10px', 'replace', 'linear'),
value(1, '60px', 'replace') ] } ]
},
{ desc: 'a keyframe sequence with duplicate values for a given interior'
+ ' offset',
frames: [ { offset: 0.0, left: '10px' },
{ offset: 0.5, left: '20px' },
{ offset: 0.5, left: '30px' },
{ offset: 0.5, left: '40px' },
{ offset: 1.0, left: '50px' } ],
expected: [ { property: 'left',
values: [ value(0, '10px', 'replace', 'linear'),
value(0.5, '20px', 'replace'),
value(0.5, '40px', 'replace', 'linear'),
value(1, '50px', 'replace') ] } ]
},
{ desc: 'a keyframe sequence with duplicate values for offsets 0 and 1',
frames: [ { offset: 0, left: '10px' },
{ offset: 0, left: '20px' },
{ offset: 0, left: '30px' },
{ offset: 1, left: '40px' },
{ offset: 1, left: '50px' },
{ offset: 1, left: '60px' } ],
expected: [ { property: 'left',
values: [ value(0, '10px', 'replace'),
value(0, '30px', 'replace', 'linear'),
value(1, '40px', 'replace'),
value(1, '60px', 'replace') ] } ]
},
{ desc: 'a two-property four-keyframe sequence',
frames: [ { offset: 0, left: '10px' },
{ offset: 0, top: '20px' },
{ offset: 1, top: '30px' },
{ offset: 1, left: '40px' } ],
expected: [ { property: 'left',
values: [ value(0, '10px', 'replace', 'linear'),
value(1, '40px', 'replace') ] },
{ property: 'top',
values: [ value(0, '20px', 'replace', 'linear'),
value(1, '30px', 'replace') ] } ]
},
{ desc: 'a one-property keyframe sequence with some omitted offsets',
frames: [ { offset: 0.00, left: '10px' },
{ offset: 0.25, left: '20px' },
{ left: '30px' },
{ left: '40px' },
{ offset: 1.00, left: '50px' } ],
expected: [ { property: 'left',
values: [ value(0, '10px', 'replace', 'linear'),
value(0.25, '20px', 'replace', 'linear'),
value(0.5, '30px', 'replace', 'linear'),
value(0.75, '40px', 'replace', 'linear'),
value(1, '50px', 'replace') ] } ]
},
{ desc: 'a two-property keyframe sequence with some omitted offsets',
frames: [ { offset: 0.00, left: '10px', top: '20px' },
{ offset: 0.25, left: '30px' },
{ left: '40px' },
{ left: '50px', top: '60px' },
{ offset: 1.00, left: '70px', top: '80px' } ],
expected: [ { property: 'left',
values: [ value(0, '10px', 'replace', 'linear'),
value(0.25, '30px', 'replace', 'linear'),
value(0.5, '40px', 'replace', 'linear'),
value(0.75, '50px', 'replace', 'linear'),
value(1, '70px', 'replace') ] },
{ property: 'top',
values: [ value(0, '20px', 'replace', 'linear'),
value(0.75, '60px', 'replace', 'linear'),
value(1, '80px', 'replace') ] } ]
},
{ desc: 'a one-property keyframe sequence with all omitted offsets',
frames: [ { left: '10px' },
{ left: '20px' },
{ left: '30px' },
{ left: '40px' },
{ left: '50px' } ],
expected: [ { property: 'left',
values: [ value(0, '10px', 'replace', 'linear'),
value(0.25, '20px', 'replace', 'linear'),
value(0.5, '30px', 'replace', 'linear'),
value(0.75, '40px', 'replace', 'linear'),
value(1, '50px', 'replace') ] } ]
},
{ desc: 'a keyframe sequence with different easing values, but the'
+ ' same easing value for a given offset',
frames: [ { offset: 0.0, easing: 'ease', left: '10px'},
{ offset: 0.0, easing: 'ease', top: '20px'},
{ offset: 0.5, easing: 'linear', left: '30px' },
{ offset: 0.5, easing: 'linear', top: '40px' },
{ offset: 1.0, easing: 'step-end', left: '50px' },
{ offset: 1.0, easing: 'step-end', top: '60px' } ],
expected: [ { property: 'left',
values: [ value(0, '10px', 'replace', 'ease'),
value(0.5, '30px', 'replace', 'linear'),
value(1, '50px', 'replace') ] },
{ property: 'top',
values: [ value(0, '20px', 'replace', 'ease'),
value(0.5, '40px', 'replace', 'linear'),
value(1, '60px', 'replace') ] } ]
},
{ desc: 'a one-property two-keyframe sequence that needs to'
+ ' stringify its values',
frames: [ { offset: 0, opacity: 0 },
{ offset: 1, opacity: 1 } ],
expected: [ { property: 'opacity',
values: [ value(0, '0', 'replace', 'linear'),
value(1, '1', 'replace') ] } ]
},
{ desc: 'a keyframe sequence where shorthand precedes longhand',
frames: [ { offset: 0, margin: '10px', marginRight: '20px' },
{ offset: 1, margin: '30px' } ],
expected: [ { property: 'margin-top',
values: [ value(0, '10px', 'replace', 'linear'),
value(1, '30px', 'replace') ] },
{ property: 'margin-right',
values: [ value(0, '20px', 'replace', 'linear'),
value(1, '30px', 'replace') ] },
{ property: 'margin-bottom',
values: [ value(0, '10px', 'replace', 'linear'),
value(1, '30px', 'replace') ] },
{ property: 'margin-left',
values: [ value(0, '10px', 'replace', 'linear'),
value(1, '30px', 'replace') ] } ]
},
{ desc: 'a keyframe sequence where longhand precedes shorthand',
frames: [ { offset: 0, marginRight: '20px', margin: '10px' },
{ offset: 1, margin: '30px' } ],
expected: [ { property: 'margin-top',
values: [ value(0, '10px', 'replace', 'linear'),
value(1, '30px', 'replace') ] },
{ property: 'margin-right',
values: [ value(0, '20px', 'replace', 'linear'),
value(1, '30px', 'replace') ] },
{ property: 'margin-bottom',
values: [ value(0, '10px', 'replace', 'linear'),
value(1, '30px', 'replace') ] },
{ property: 'margin-left',
values: [ value(0, '10px', 'replace', 'linear'),
value(1, '30px', 'replace') ] } ]
},
{ desc: 'a keyframe sequence where lesser shorthand precedes greater'
+ ' shorthand',
frames: [ { offset: 0, borderLeft: '1px solid rgb(1, 2, 3)',
border: '2px dotted rgb(4, 5, 6)' },
{ offset: 1, border: '3px dashed rgb(7, 8, 9)' } ],
expected: [ { property: 'border-bottom-color',
values: [ value(0, 'rgb(4, 5, 6)', 'replace', 'linear'),
value(1, 'rgb(7, 8, 9)', 'replace') ] },
{ property: 'border-left-color',
values: [ value(0, 'rgb(1, 2, 3)', 'replace', 'linear'),
value(1, 'rgb(7, 8, 9)', 'replace') ] },
{ property: 'border-right-color',
values: [ value(0, 'rgb(4, 5, 6)', 'replace', 'linear'),
value(1, 'rgb(7, 8, 9)', 'replace') ] },
{ property: 'border-top-color',
values: [ value(0, 'rgb(4, 5, 6)', 'replace', 'linear'),
value(1, 'rgb(7, 8, 9)', 'replace') ] },
{ property: 'border-bottom-width',
values: [ value(0, '2px', 'replace', 'linear'),
value(1, '3px', 'replace') ] },
{ property: 'border-left-width',
values: [ value(0, '1px', 'replace', 'linear'),
value(1, '3px', 'replace') ] },
{ property: 'border-right-width',
values: [ value(0, '2px', 'replace', 'linear'),
value(1, '3px', 'replace') ] },
{ property: 'border-top-width',
values: [ value(0, '2px', 'replace', 'linear'),
value(1, '3px', 'replace') ] } ]
},
{ desc: 'a keyframe sequence where greater shorthand precedes' +
+ ' lesser shorthand',
frames: [ { offset: 0, border: '2px dotted rgb(4, 5, 6)',
borderLeft: '1px solid rgb(1, 2, 3)' },
{ offset: 1, border: '3px dashed rgb(7, 8, 9)' } ],
expected: [ { property: 'border-bottom-color',
values: [ value(0, 'rgb(4, 5, 6)', 'replace', 'linear'),
value(1, 'rgb(7, 8, 9)', 'replace') ] },
{ property: 'border-left-color',
values: [ value(0, 'rgb(1, 2, 3)', 'replace', 'linear'),
value(1, 'rgb(7, 8, 9)', 'replace') ] },
{ property: 'border-right-color',
values: [ value(0, 'rgb(4, 5, 6)', 'replace', 'linear'),
value(1, 'rgb(7, 8, 9)', 'replace') ] },
{ property: 'border-top-color',
values: [ value(0, 'rgb(4, 5, 6)', 'replace', 'linear'),
value(1, 'rgb(7, 8, 9)', 'replace') ] },
{ property: 'border-bottom-width',
values: [ value(0, '2px', 'replace', 'linear'),
value(1, '3px', 'replace') ] },
{ property: 'border-left-width',
values: [ value(0, '1px', 'replace', 'linear'),
value(1, '3px', 'replace') ] },
{ property: 'border-right-width',
values: [ value(0, '2px', 'replace', 'linear'),
value(1, '3px', 'replace') ] },
{ property: 'border-top-width',
values: [ value(0, '2px', 'replace', 'linear'),
value(1, '3px', 'replace') ] } ]
},
// ---------------------------------------------------------------------
//
// Tests for unit conversion
//
// ---------------------------------------------------------------------
{ desc: 'em units are resolved to px values',
frames: { left: ['10em', '20em'] },
expected: [ { property: 'left',
values: [ value(0, '100px', 'replace', 'linear'),
value(1, '200px', 'replace') ] } ]
}
];
gTests.forEach(function(subtest) {
test(function(t) {
var div = addDiv(t);
var animation = div.animate(subtest.frames, 1000);
assert_properties_equal(animation.effect.getProperties(),
subtest.expected);
}, subtest.desc);
});
</script>
</body>

View File

@ -1,8 +1,8 @@
<!doctype html>
<head>
<meta charset=utf-8>
<title>Bug 1196114 - Animation property which indicates
running on the compositor or not</title>
<title>Bug 1196114 - Test metadata related to which animation properties
are running on the compositor</title>
<script type="application/javascript" src="../testharness.js"></script>
<script type="application/javascript" src="../testharnessreport.js"></script>
<script type="application/javascript" src="../testcommon.js"></script>
@ -13,6 +13,10 @@
height: 100px;
background-color: white;
}
@keyframes fade {
from { opacity: 1 }
to { opacity: 0 }
}
</style>
</head>
<body>
@ -41,7 +45,7 @@ function compare_property_state(a, b) {
}
function assert_animation_property_state_equals(actual, expected) {
assert_equals(actual.length, expected.length);
assert_equals(actual.length, expected.length, 'Number of properties');
var sortedActual = actual.sort(compare_property_state);
var sortedExpected = expected.sort(compare_property_state);
@ -215,7 +219,7 @@ gAnimationsTests.forEach(function(subtest) {
var animation = div.animate(subtest.frames, 100000);
return animation.ready.then(t.step_func(function() {
assert_animation_property_state_equals(
animation.effect.getPropertyState(),
animation.effect.getProperties(),
subtest.expected);
}));
}, subtest.desc);
@ -501,7 +505,7 @@ function start() {
var animation = div.animate(subtest.frames, 100000);
return animation.ready.then(t.step_func(function() {
assert_animation_property_state_equals(
animation.effect.getPropertyState(),
animation.effect.getProperties(),
subtest.expected);
}));
}, subtest.desc);
@ -518,19 +522,19 @@ function start() {
var animation = div.animate(subtest.frames, 100000);
return animation.ready.then(t.step_func(function() {
assert_property_state_on_compositor(
animation.effect.getPropertyState(),
animation.effect.getProperties(),
subtest.expected);
div.style = subtest.style;
return waitForFrame();
})).then(t.step_func(function() {
assert_animation_property_state_equals(
animation.effect.getPropertyState(),
animation.effect.getProperties(),
subtest.expected);
div.style = '';
return waitForFrame();
})).then(t.step_func(function() {
assert_property_state_on_compositor(
animation.effect.getPropertyState(),
animation.effect.getProperties(),
subtest.expected);
}));
}, subtest.desc);
@ -554,7 +558,7 @@ function start() {
return waitForAllAnimations(animations).then(t.step_func(function() {
animations.forEach(t.step_func(function(anim) {
assert_property_state_on_compositor(
anim.effect.getPropertyState(),
anim.effect.getProperties(),
anim.expected);
}));
div.style = subtest.style;
@ -562,7 +566,7 @@ function start() {
})).then(t.step_func(function() {
animations.forEach(t.step_func(function(anim) {
assert_animation_property_state_equals(
anim.effect.getPropertyState(),
anim.effect.getProperties(),
anim.expected);
}));
div.style = '';
@ -570,7 +574,7 @@ function start() {
})).then(t.step_func(function() {
animations.forEach(t.step_func(function(anim) {
assert_property_state_on_compositor(
anim.effect.getPropertyState(),
anim.effect.getProperties(),
anim.expected);
}));
}));
@ -590,7 +594,7 @@ function start() {
return waitForAllAnimations(animations).then(t.step_func(function() {
animations.forEach(t.step_func(function(anim) {
assert_animation_property_state_equals(
anim.effect.getPropertyState(),
anim.effect.getProperties(),
anim.expected);
}));
}));
@ -613,7 +617,7 @@ function start() {
return waitForAllAnimations(animations).then(t.step_func(function() {
animations.forEach(t.step_func(function(anim) {
assert_property_state_on_compositor(
anim.effect.getPropertyState(),
anim.effect.getProperties(),
anim.expected);
}));
})).then(t.step_func(function() {
@ -625,7 +629,7 @@ function start() {
// the 'width' animation.
animations.forEach(t.step_func(function(anim) {
assert_animation_property_state_equals(
anim.effect.getPropertyState(),
anim.effect.getProperties(),
anim.expected);
}));
// Remove the 'width' animation.
@ -635,7 +639,7 @@ function start() {
// Now all animations are running on compositor.
animations.forEach(t.step_func(function(anim) {
assert_property_state_on_compositor(
anim.effect.getPropertyState(),
anim.effect.getProperties(),
anim.expected);
}));
}));
@ -648,7 +652,7 @@ function start() {
{ transform: ['translate(0px)', 'translate(100px)'] }, 100000);
return animation.ready.then(t.step_func(function() {
assert_animation_property_state_equals(
animation.effect.getPropertyState(),
animation.effect.getProperties(),
[ { property: 'transform', runningOnCompositor: true } ]);
div.style = 'width: 10000px; height: 10000px';
return waitForFrame();
@ -659,7 +663,7 @@ function start() {
"bigger than the viewport \\(\\d+, \\d+\\) or the visual rectangle " +
"\\(10000, 10000\\) is larger than the max allowed value \\(\\d+\\)");
assert_animation_property_state_equals(
animation.effect.getPropertyState(),
animation.effect.getProperties(),
[ {
property: 'transform',
runningOnCompositor: false,
@ -670,7 +674,7 @@ function start() {
})).then(t.step_func(function() {
// FIXME: Bug 1253164: the animation should get back on compositor.
assert_animation_property_state_equals(
animation.effect.getPropertyState(),
animation.effect.getProperties(),
[ { property: 'transform', runningOnCompositor: false } ]);
}));
}, 'transform on too big element');
@ -693,13 +697,13 @@ function start() {
{ transform: ['translate(0px)', 'translate(100px)'] }, 100000);
return animation.ready.then(t.step_func(function() {
assert_animation_property_state_equals(
animation.effect.getPropertyState(),
animation.effect.getProperties(),
[ { property: 'transform', runningOnCompositor: true } ]);
svg.setAttribute('transform', 'translate(10, 20)');
return waitForFrame();
})).then(t.step_func(function() {
assert_animation_property_state_equals(
animation.effect.getPropertyState(),
animation.effect.getProperties(),
[ {
property: 'transform',
runningOnCompositor: false,
@ -709,10 +713,25 @@ function start() {
return waitForFrame();
})).then(t.step_func(function() {
assert_animation_property_state_equals(
animation.effect.getPropertyState(),
animation.effect.getProperties(),
[ { property: 'transform', runningOnCompositor: true } ]);
}));
}, 'transform of nsIFrame with SVG transform');
promise_test(function(t) {
var div = addDiv(t, { class: 'compositable',
style: 'animation: fade 100s' });
var cssAnimation = div.getAnimations()[0];
var scriptAnimation = div.animate({ opacity: [ 1, 0 ] }, 1000);
return scriptAnimation.ready.then(function() {
assert_animation_property_state_equals(
cssAnimation.effect.getProperties(),
[ { property: 'opacity', runningOnCompositor: false } ]);
assert_animation_property_state_equals(
scriptAnimation.effect.getProperties(),
[ { property: 'opacity', runningOnCompositor: true } ]);
});
}, 'overridden animation');
}
</script>

View File

@ -61,9 +61,7 @@ skip-if = os == "android" || toolkit == "gonk" || e10s # embed-apps doesn't work
[test_marketplace_pkg_install.html]
skip-if = buildapp == "b2g" || toolkit == "android" # see bug 989806
[test_packaged_app_install.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only
[test_packaged_app_update.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only
[test_receipt_operations.html]
[test_signed_pkg_install.html]
[test_uninstall_errors.html]

View File

@ -43,6 +43,66 @@ ParseInteger(const nsAString& aString, int32_t& aInt)
nsContentUtils::eParseHTMLInteger_NonStandard ));
}
static bool
ParseFloat(const nsAString& aString, double& aDouble)
{
// Check if it is a valid floating-point number first since the result of
// nsString.ToDouble() is more lenient than the spec,
// https://html.spec.whatwg.org/#valid-floating-point-number
nsAString::const_iterator iter, end;
aString.BeginReading(iter);
aString.EndReading(end);
if (iter == end) {
return false;
}
if (*iter == char16_t('-') && ++iter == end) {
return false;
}
if (nsCRT::IsAsciiDigit(*iter)) {
for (; iter != end && nsCRT::IsAsciiDigit(*iter) ; ++iter);
} else if (*iter == char16_t('.')) {
// Do nothing, jumps to fraction part
} else {
return false;
}
// Fraction
if (*iter == char16_t('.')) {
++iter;
if (iter == end || !nsCRT::IsAsciiDigit(*iter)) {
// U+002E FULL STOP character (.) must be followed by one or more ASCII digits
return false;
}
for (; iter != end && nsCRT::IsAsciiDigit(*iter) ; ++iter);
}
if (iter != end && (*iter == char16_t('e') || *iter == char16_t('E'))) {
++iter;
if (*iter == char16_t('-') || *iter == char16_t('+')) {
++iter;
}
if (iter == end || !nsCRT::IsAsciiDigit(*iter)) {
// Should have one or more ASCII digits
return false;
}
for (; iter != end && nsCRT::IsAsciiDigit(*iter) ; ++iter);
}
if (iter != end) {
return false;
}
nsresult rv;
aDouble = PromiseFlatString(aString).ToDouble(&rv);
return NS_SUCCEEDED(rv);
}
ResponsiveImageSelector::ResponsiveImageSelector(nsIContent *aContent)
: mOwnerNode(aContent),
mSelectedCandidateIndex(-1)
@ -533,9 +593,8 @@ ResponsiveImageDescriptors::AddDescriptor(const nsAString& aDescriptor)
} else if (*descType == char16_t('x')) {
// If the value is not a valid floating point number, it doesn't match this
// descriptor, fall through.
nsresult rv;
double possibleDensity = PromiseFlatString(valueStr).ToDouble(&rv);
if (NS_SUCCEEDED(rv)) {
double possibleDensity = 0.0;
if (ParseFloat(valueStr, possibleDensity)) {
if (possibleDensity >= 0.0 &&
mWidth.isNothing() &&
mDensity.isNothing() &&

View File

@ -831,18 +831,6 @@ danger::AutoCxPusher::IsStackTop() const
AutoJSContext::AutoJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_IN_IMPL)
: mCx(nullptr)
{
Init(false MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT);
}
AutoJSContext::AutoJSContext(bool aSafe MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
: mCx(nullptr)
{
Init(aSafe MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT);
}
void
AutoJSContext::Init(bool aSafe MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
{
JS::AutoSuppressGCAnalysis nogc;
MOZ_ASSERT(!mCx, "mCx should not be initialized!");
@ -850,9 +838,7 @@ AutoJSContext::Init(bool aSafe MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
nsXPConnect *xpc = nsXPConnect::XPConnect();
if (!aSafe) {
mCx = xpc->GetCurrentJSContext();
}
mCx = xpc->GetCurrentJSContext();
if (!mCx) {
mJSAPI.Init();
@ -888,9 +874,17 @@ ThreadsafeAutoJSContext::operator JSContext*() const
}
AutoSafeJSContext::AutoSafeJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_IN_IMPL)
: AutoJSContext(true MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT)
, mAc(mCx, xpc::UnprivilegedJunkScope())
: AutoJSAPI()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
DebugOnly<bool> ok = Init(xpc::UnprivilegedJunkScope());
MOZ_ASSERT(ok,
"This is quite odd. We should have crashed in the "
"xpc::NativeGlobal() call if xpc::UnprivilegedJunkScope() "
"returned null, and inited correctly otherwise!");
}
} // namespace mozilla

View File

@ -427,13 +427,6 @@ public:
operator JSContext*() const;
protected:
explicit AutoJSContext(bool aSafe MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
// We need this Init() method because we can't use delegating constructor for
// the moment. It is a C++11 feature and we do not require C++11 to be
// supported to be able to compile Gecko.
void Init(bool aSafe MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
JSContext* mCx;
dom::AutoJSAPI mJSAPI;
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
@ -461,11 +454,16 @@ private:
*
* Note - This is deprecated. Please use AutoJSAPI instead.
*/
class MOZ_RAII AutoSafeJSContext : public AutoJSContext {
class MOZ_RAII AutoSafeJSContext : public dom::AutoJSAPI {
public:
explicit AutoSafeJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM);
operator JSContext*() const
{
return cx();
}
private:
JSAutoCompartment mAc;
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
} // namespace mozilla

View File

@ -2724,6 +2724,10 @@ public:
}
void ReportHasScrollLinkedEffect();
bool HasScrollLinkedEffect() const
{
return mHasScrollLinkedEffect;
}
protected:
bool GetUseCounter(mozilla::UseCounter aUseCounter)

View File

@ -1413,20 +1413,29 @@ nsScriptLoader::OnStreamComplete(nsIIncrementalStreamLoader* aLoader,
NS_ASSERTION(request, "null request in stream complete handler");
NS_ENSURE_TRUE(request, NS_ERROR_FAILURE);
nsCOMPtr<nsIRequest> channelRequest;
aLoader->GetRequest(getter_AddRefs(channelRequest));
nsCOMPtr<nsIChannel> channel;
channel = do_QueryInterface(channelRequest);
nsresult rv = NS_OK;
if (!request->mIntegrity.IsEmpty() &&
NS_SUCCEEDED((rv = aSRIStatus))) {
MOZ_ASSERT(aSRIDataVerifier);
nsCOMPtr<nsIRequest> channelRequest;
aLoader->GetRequest(getter_AddRefs(channelRequest));
nsCOMPtr<nsIChannel> channel;
channel = do_QueryInterface(channelRequest);
if (NS_FAILED(aSRIDataVerifier->Verify(request->mIntegrity, channel,
request->mCORSMode, mDocument))) {
rv = NS_ERROR_SRI_CORRUPT;
}
} else {
nsCOMPtr<nsILoadInfo> loadInfo = channel->GetLoadInfo();
bool enforceSRI = false;
loadInfo->GetEnforceSRI(&enforceSRI);
if (enforceSRI) {
MOZ_LOG(GetSriLog(), mozilla::LogLevel::Debug,
("nsScriptLoader::OnStreamComplete, required SRI not found"));
rv = NS_ERROR_SRI_CORRUPT;
}
}
if (NS_SUCCEEDED(rv)) {

View File

@ -1489,7 +1489,9 @@ nsXMLHttpRequest::Open(const nsACString& inMethod, const nsACString& url,
bool async, const Optional<nsAString>& user,
const Optional<nsAString>& password)
{
NS_ENSURE_ARG(!inMethod.IsEmpty());
if (inMethod.IsEmpty()) {
return NS_ERROR_DOM_SYNTAX_ERR;
}
if (!async && !DontWarnAboutSyncXHR() && GetOwner() &&
GetOwner()->GetExtantDoc()) {

View File

@ -767,7 +767,6 @@ skip-if = buildapp == 'b2g' || toolkit == 'android' #bug 775227
[test_htmlcopyencoder.html]
[test_htmlcopyencoder.xhtml]
[test_ipc_messagemanager_blob.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 936226
[test_meta_viewport0.html]
skip-if = (os != 'b2g' && os != 'android') # meta-viewport tag support is mobile-only
[test_meta_viewport1.html]

View File

@ -32,6 +32,14 @@ public:
{
}
// See CallbackObject for an explanation of the arguments.
explicit CallbackFunction(JS::Handle<JSObject*> aCallable,
JS::Handle<JSObject*> aAsyncStack,
nsIGlobalObject* aIncumbentGlobal)
: CallbackObject(aCallable, aAsyncStack, aIncumbentGlobal)
{
}
JS::Handle<JSObject*> Callable() const
{
return Callback();

View File

@ -31,6 +31,14 @@ public:
{
}
// See CallbackObject for an explanation of the arguments.
explicit CallbackInterface(JS::Handle<JSObject*> aCallback,
JS::Handle<JSObject*> aAsyncStack,
nsIGlobalObject* aIncumbentGlobal)
: CallbackObject(aCallback, aAsyncStack, aIncumbentGlobal)
{
}
protected:
bool GetCallableProperty(JSContext* cx, JS::Handle<jsid> aPropId,
JS::MutableHandle<JS::Value> aCallable);

View File

@ -67,6 +67,16 @@ public:
}
}
// Instead of capturing the current stack to use as an async parent when the
// callback is invoked, the caller can use this overload to pass in a stack
// for that purpose.
explicit CallbackObject(JS::Handle<JSObject*> aCallback,
JS::Handle<JSObject*> aAsyncStack,
nsIGlobalObject *aIncumbentGlobal)
{
Init(aCallback, aAsyncStack, aIncumbentGlobal);
}
JS::Handle<JSObject*> Callback() const
{
JS::ExposeObjectToActiveJS(mCallback);

View File

@ -14687,17 +14687,29 @@ class CGCallback(CGClass):
# Not much we can assert about it, other than not being null, and
# CallbackObject does that already.
body = ""
return [ClassConstructor(
[Argument("JSContext*", "aCx"),
Argument("JS::Handle<JSObject*>", "aCallback"),
Argument("nsIGlobalObject*", "aIncumbentGlobal")],
bodyInHeader=True,
visibility="public",
explicit=True,
baseConstructors=[
"%s(aCx, aCallback, aIncumbentGlobal)" % self.baseName,
],
body=body)]
return [
ClassConstructor(
[Argument("JSContext*", "aCx"),
Argument("JS::Handle<JSObject*>", "aCallback"),
Argument("nsIGlobalObject*", "aIncumbentGlobal")],
bodyInHeader=True,
visibility="public",
explicit=True,
baseConstructors=[
"%s(aCx, aCallback, aIncumbentGlobal)" % self.baseName,
],
body=body),
ClassConstructor(
[Argument("JS::Handle<JSObject*>", "aCallback"),
Argument("JS::Handle<JSObject*>", "aAsyncStack"),
Argument("nsIGlobalObject*", "aIncumbentGlobal")],
bodyInHeader=True,
visibility="public",
explicit=True,
baseConstructors=[
"%s(aCallback, aAsyncStack, aIncumbentGlobal)" % self.baseName,
],
body=body)]
def getMethodImpls(self, method):
assert method.needThisHandling

View File

@ -204,7 +204,6 @@ disabled = bug 1022281
[test_browserElement_inproc_FrameWrongURI.html]
skip-if = (toolkit == 'gonk' && !debug)
[test_browserElement_inproc_GetScreenshot.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only
[test_browserElement_inproc_GetScreenshotDppx.html]
[test_browserElement_inproc_Iconchange.html]
[test_browserElement_inproc_LoadEvents.html]
@ -258,7 +257,6 @@ skip-if = (toolkit == 'gonk' && !debug)
[test_browserElement_inproc_XFrameOptionsDeny.html]
[test_browserElement_inproc_XFrameOptionsSameOrigin.html]
[test_browserElement_oop_NextPaint.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 936226
# Disabled due to https://bugzilla.mozilla.org/show_bug.cgi?id=774100
[test_browserElement_inproc_Reload.html]
disabled = bug 774100
@ -272,4 +270,4 @@ tags = audiochannel
[test_browserElement_inproc_OpenWindowEmpty.html]
skip-if = (toolkit == 'gonk') # Test doesn't work on B2G emulator
[test_browserElement_inproc_ActiveStateChangeOnChangingMutedOrVolume.html]
tags = audiochannel
tags = audiochannel

4
dom/cache/moz.build vendored
View File

@ -93,10 +93,6 @@ MOCHITEST_MANIFESTS += [
'test/mochitest/mochitest.ini',
]
MOCHITEST_CHROME_MANIFESTS += [
'test/mochitest/chrome.ini',
]
BROWSER_CHROME_MANIFESTS += [
'test/mochitest/browser.ini',
]

View File

@ -1 +0,0 @@
[test_chrome_constructor.html]

View File

@ -47,3 +47,4 @@ skip-if = e10s && debug && os == 'win'
[test_cache_orphaned_cache.html]
[test_cache_orphaned_body.html]
[test_cache_untrusted.html]
[test_chrome_constructor.html]

View File

@ -4,13 +4,11 @@
<html>
<head>
<title>Validate Interfaces Exposed to Workers</title>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<script class="testbody" type="text/javascript">
var Cu = Components.utils;
Cu.import('resource://gre/modules/Services.jsm');
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({
@ -19,9 +17,7 @@
}, function() {
// attach to a different origin's CacheStorage
var url = 'http://example.com/';
var uri = Services.io.newURI(url, null, null);
var principal = Services.scriptSecurityManager.createCodebasePrincipal(uri, {});
var storage = new CacheStorage('content', principal);
var storage = SpecialPowers.createChromeCache('content', url);
// verify we can use the other origin's CacheStorage as normal
var req = new Request('http://example.com/index.html');

View File

@ -51,6 +51,9 @@ public:
void Arc(double x, double y, double radius,
double startAngle, double endAngle, bool anticlockwise,
ErrorResult& error);
void Ellipse(double x, double y, double radiusX, double radiusY,
double rotation, double startAngle, double endAngle,
bool anticlockwise, ErrorResult& error);
void LineTo(const gfx::Point& aPoint);
void BezierTo(const gfx::Point& aCP1,

View File

@ -3045,6 +3045,22 @@ CanvasRenderingContext2D::Rect(double aX, double aY, double aW, double aH)
}
}
void
CanvasRenderingContext2D::Ellipse(double aX, double aY, double aRadiusX, double aRadiusY,
double aRotation, double aStartAngle, double aEndAngle,
bool aAnticlockwise, ErrorResult& aError)
{
if (aRadiusX < 0.0 || aRadiusY < 0.0) {
aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
return;
}
EnsureWritablePath();
ArcToBezier(this, Point(aX, aY), Size(aRadiusX, aRadiusY), aStartAngle, aEndAngle,
aAnticlockwise, aRotation);
}
void
CanvasRenderingContext2D::EnsureWritablePath()
{
@ -5941,6 +5957,22 @@ CanvasPath::Arc(double aX, double aY, double aRadius,
ArcToBezier(this, Point(aX, aY), Size(aRadius, aRadius), aStartAngle, aEndAngle, aAnticlockwise);
}
void
CanvasPath::Ellipse(double x, double y, double radiusX, double radiusY,
double rotation, double startAngle, double endAngle,
bool anticlockwise, ErrorResult& error)
{
if (radiusX < 0.0 || radiusY < 0.0) {
error.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
return;
}
EnsurePathBuilder();
ArcToBezier(this, Point(x, y), Size(radiusX, radiusY), startAngle, endAngle,
anticlockwise, rotation);
}
void
CanvasPath::LineTo(const gfx::Point& aPoint)
{

View File

@ -346,6 +346,9 @@ public:
void Rect(double aX, double aY, double aW, double aH);
void Arc(double aX, double aY, double aRadius, double aStartAngle,
double aEndAngle, bool aAnticlockwise, mozilla::ErrorResult& aError);
void Ellipse(double aX, double aY, double aRadiusX, double aRadiusY,
double aRotation, double aStartAngle, double aEndAngle,
bool aAnticlockwise, ErrorResult& aError);
void GetMozCurrentTransform(JSContext* aCx,
JS::MutableHandle<JSObject*> aResult,

View File

@ -47,6 +47,8 @@ ScopedResolveTexturesForDraw::ScopedResolveTexturesForDraw(WebGLContext* webgl,
bool* const out_error)
: mWebGL(webgl)
{
MOZ_ASSERT(webgl->gl->IsCurrent());
typedef decltype(WebGLContext::mBound2DTextures) TexturesT;
const auto fnResolveAll = [this, funcName](const TexturesT& textures)
@ -220,7 +222,7 @@ WebGLContext::DrawArrays_check(GLint first, GLsizei count, GLsizei primcount,
return false;
}
MakeContextCurrent();
MOZ_ASSERT(gl->IsCurrent());
if (mBoundDrawFramebuffer) {
if (!mBoundDrawFramebuffer->ValidateAndInitAttachments(info))
@ -246,6 +248,8 @@ WebGLContext::DrawArrays(GLenum mode, GLint first, GLsizei count)
if (!ValidateDrawModeEnum(mode, funcName))
return;
MakeContextCurrent();
bool error;
ScopedResolveTexturesForDraw scopedResolve(this, funcName, &error);
if (error)
@ -274,6 +278,8 @@ WebGLContext::DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsiz
if (!ValidateDrawModeEnum(mode, funcName))
return;
MakeContextCurrent();
bool error;
ScopedResolveTexturesForDraw scopedResolve(this, funcName, &error);
if (error)
@ -409,7 +415,7 @@ WebGLContext::DrawElements_check(GLsizei count, GLenum type,
WebGLContext::EnumName(type));
}
MakeContextCurrent();
MOZ_ASSERT(gl->IsCurrent());
if (mBoundDrawFramebuffer) {
if (!mBoundDrawFramebuffer->ValidateAndInitAttachments(info))
@ -436,6 +442,8 @@ WebGLContext::DrawElements(GLenum mode, GLsizei count, GLenum type,
if (!ValidateDrawModeEnum(mode, funcName))
return;
MakeContextCurrent();
bool error;
ScopedResolveTexturesForDraw scopedResolve(this, funcName, &error);
if (error)
@ -473,6 +481,8 @@ WebGLContext::DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type,
if (!ValidateDrawModeEnum(mode, funcName))
return;
MakeContextCurrent();
bool error;
ScopedResolveTexturesForDraw scopedResolve(this, funcName, &error);
if (error)

View File

@ -39,51 +39,28 @@ support-files =
[test_2d.clearRect.image.offscreen.html]
[test_2d.clip.winding.html]
[test_2d.composite.canvas.color-burn.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
[test_2d.composite.canvas.color-dodge.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
[test_2d.composite.canvas.color.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
[test_2d.composite.canvas.darken.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
[test_2d.composite.canvas.destination-atop.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
[test_2d.composite.canvas.destination-in.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
[test_2d.composite.canvas.difference.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
[test_2d.composite.canvas.exclusion.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
[test_2d.composite.canvas.hard-light.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
[test_2d.composite.canvas.hue.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
[test_2d.composite.canvas.lighten.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
[test_2d.composite.canvas.luminosity.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
[test_2d.composite.canvas.multiply.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
[test_2d.composite.canvas.overlay.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
[test_2d.composite.canvas.saturation.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
[test_2d.composite.canvas.screen.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
[test_2d.composite.canvas.soft-light.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
[test_2d.composite.canvas.source-in.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
[test_2d.composite.canvas.source-out.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
[test_2d.composite.image.destination-atop.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
[test_2d.composite.image.destination-in.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
[test_2d.composite.image.source-in.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
[test_2d.composite.image.source-out.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
# xor and lighter aren't well handled by cairo; they mostly work, but we don't want
# to test that
[test_2d.composite.solid.xor.html]
@ -123,7 +100,7 @@ disabled =
[test_2d.composite.solid.soft-light.html]
[test_2d.composite.uncovered.image.destination-atop.html]
# This test fails in Suite on Linux for some reason, disable it there
skip-if = (os == 'linux' && buildapp == 'suite') || (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
skip-if = (os == 'linux' && buildapp == 'suite')
[test_2d.composite.uncovered.fill.color-burn.html]
[test_2d.composite.uncovered.fill.color-dodge.html]
[test_2d.composite.uncovered.fill.color.html]
@ -149,11 +126,8 @@ skip-if = toolkit != 'cocoa'
[test_2d.composite.uncovered.fill.destination-atop.html]
skip-if = toolkit != 'cocoa'
[test_2d.composite.uncovered.image.destination-in.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
[test_2d.composite.uncovered.image.source-in.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
[test_2d.composite.uncovered.image.source-out.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
# Tests that fail on non-Mac (bug 407107)
[test_2d.composite.uncovered.pattern.source-in.html]
skip-if = toolkit != 'cocoa'
@ -233,7 +207,7 @@ skip-if = (toolkit == 'gonk' && debug) #bug 1045153
[test_bug902651.html]
[test_bug1215072.html]
[test_canvas.html]
skip-if = (toolkit == 'gonk' && debug) || (toolkit == 'android' && processor == 'x86') || (android_version == '18' && debug) #debug-only crash; bug 933541 #x86 only bug 913662 #android 4.3 debug bug 1143317
skip-if = (toolkit == 'gonk' && debug) || (android_version == '18' && debug) #debug-only crash; bug 933541 #android 4.3 debug bug 1143317
[test_canvas_focusring.html]
skip-if = (toolkit == 'gonk' && !debug) || os == 'win' #specialpowers.wrap
[test_canvas_font_setter.html]

View File

@ -153,8 +153,8 @@ skip-if(!winWidget) pref(webgl.disable-angle,true) == webgl-color-test.html?nat
== stroketext-shadow.html stroketext-shadow-ref.html
# focus rings
pref(canvas.focusring.enabled,true) skip-if(B2G) skip-if(Android&&AndroidVersion<15,8,500) skip-if(winWidget) needs-focus == drawFocusIfNeeded.html drawFocusIfNeeded-ref.html
pref(canvas.customfocusring.enabled,true) skip-if(B2G) skip-if(Android&&AndroidVersion<15,8,500) skip-if(winWidget) needs-focus == drawCustomFocusRing.html drawCustomFocusRing-ref.html
pref(canvas.focusring.enabled,true) skip-if(B2G) skip-if(cocoaWidget) skip-if(winWidget) needs-focus == drawFocusIfNeeded.html drawFocusIfNeeded-ref.html
pref(canvas.customfocusring.enabled,true) skip-if(B2G) skip-if(cocoaWidget) skip-if(Android) skip-if(winWidget) needs-focus == drawCustomFocusRing.html drawCustomFocusRing-ref.html
# Check that captureStream() displays in a local video element
skip-if(winWidget&&layersGPUAccelerated&&d2d) == capturestream.html wrapper.html?green.png

File diff suppressed because it is too large Load Diff

View File

@ -23,7 +23,7 @@ skip-if = (toolkit == 'gonk' && debug) || (os == 'win' && os_version == '5.1') #
skip-if = (toolkit == 'gonk' && debug) #debug-only failure
[test_contacts_events.html]
[test_contacts_getall.html]
skip-if = (toolkit == 'gonk' && debug) || (toolkit == 'android' && processor == 'x86') #debug-only failure #x86 only
skip-if = (toolkit == 'gonk' && debug) #debug-only failure
[test_contacts_getall2.html]
skip-if = (toolkit == 'gonk' && debug) #debug-only failure
[test_contacts_international.html]

View File

@ -410,9 +410,7 @@ public:
return;
}
AutoSafeJSContext cx;
mRequest = store->OpenCursor(cx, JS::UndefinedHandleValue,
IDBCursorDirection::Prev, error);
mRequest = store->OpenCursor(IDBCursorDirection::Prev, error);
if (NS_WARN_IF(error.Failed())) {
return;
}
@ -492,11 +490,9 @@ public:
MOZ_ASSERT(type.EqualsASCII("success"));
#endif
AutoSafeJSContext cx;
ErrorResult error;
JS::Rooted<JS::Value> result(cx);
request->GetResult(cx, &result, error);
JS::Rooted<JS::Value> result(nsContentUtils::RootingCx());
request->GetResult(&result, error);
if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult();
}

View File

@ -38,15 +38,12 @@ support-files =
[test_app_install.html]
skip-if = toolkit == 'gonk' # embed-apps doesn't work in the mochitest app
[test_readonly.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 936226
[test_basic.html]
[test_basic_worker.html]
[test_changes.html]
[test_arrays.html]
[test_oop.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 936226
[test_sync.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 936226
[test_sync_worker.html]
[test_bug924104.html]
[test_certifiedApp.html]

View File

@ -1,5 +1,4 @@
[DEFAULT]
skip-if = (toolkit == 'android' && processor == 'x86') # Android: bug 781789 & bug 782275
support-files = devicestorage_common.js
remove_testing_directory.js

View File

@ -15,10 +15,14 @@ FetchUtil::GetValidRequestMethod(const nsACString& aMethod, nsCString& outMethod
{
nsAutoCString upperCaseMethod(aMethod);
ToUpperCase(upperCaseMethod);
if (!NS_IsValidHTTPToken(aMethod)) {
outMethod.SetIsVoid(true);
return NS_ERROR_DOM_SYNTAX_ERR;
}
if (upperCaseMethod.EqualsLiteral("CONNECT") ||
upperCaseMethod.EqualsLiteral("TRACE") ||
upperCaseMethod.EqualsLiteral("TRACK") ||
!NS_IsValidHTTPToken(aMethod)) {
upperCaseMethod.EqualsLiteral("TRACK")) {
outMethod.SetIsVoid(true);
return NS_ERROR_DOM_SECURITY_ERR;
}

View File

@ -775,7 +775,7 @@ NS_IMPL_ISUPPORTS(nsGeolocationRequest::TimerCallbackHolder, nsISupports, nsITim
NS_IMETHODIMP
nsGeolocationRequest::TimerCallbackHolder::Notify(nsITimer*)
{
if (mRequest) {
if (mRequest.get()) {
mRequest->Notify();
}
return NS_OK;

View File

@ -59,7 +59,6 @@ skip-if = (toolkit == 'gonk' && debug) #debug-only failure; bug 926546
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
[test_input_sanitization.html]
[test_input_textarea_set_value_no_scroll.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only
[test_input_typing_sanitization.html]
skip-if = buildapp == 'mulet'
[test_input_untrusted_key_events.html]

View File

@ -404,7 +404,7 @@ skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop spec
[test_bug658746.html]
[test_bug659596.html]
[test_bug659743.xml]
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') || android_version == '10' #Bug 931116, b2g desktop specific, initial triage #Android 2.3 aws only; bug 1031103
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
[test_bug660663.html]
[test_bug660959-1.html]
[test_bug660959-2.html]

View File

@ -18005,18 +18005,12 @@ DatabaseMaintenance::CheckIntegrity(mozIStorageConnection* aConnection,
}
}
bool changedForeignKeys;
if (foreignKeysWereEnabled) {
changedForeignKeys = false;
} else {
if (!foreignKeysWereEnabled) {
rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"PRAGMA foreign_keys = ON;"
));
"PRAGMA foreign_keys = ON;"));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
changedForeignKeys = true;
}
bool foreignKeyError;
@ -18035,14 +18029,10 @@ DatabaseMaintenance::CheckIntegrity(mozIStorageConnection* aConnection,
}
}
if (changedForeignKeys) {
if (!foreignKeysWereEnabled) {
nsAutoCString stmtSQL;
stmtSQL.AssignLiteral("PRAGMA foreign_keys = ");
if (foreignKeysWereEnabled) {
stmtSQL.AppendLiteral("ON");
} else {
stmtSQL.AppendLiteral("OFF");
}
stmtSQL.AppendLiteral("OFF");
stmtSQL.Append(';');
rv = aConnection->ExecuteSimpleSQL(stmtSQL);

View File

@ -99,6 +99,8 @@ IDBKeyRange::FromJSVal(JSContext* aCx,
JS::Handle<JS::Value> aVal,
IDBKeyRange** aKeyRange)
{
MOZ_ASSERT_IF(!aCx, aVal.isUndefined());
RefPtr<IDBKeyRange> keyRange;
if (aVal.isNullOrUndefined()) {

View File

@ -57,6 +57,7 @@ public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(IDBKeyRange)
// aCx is allowed to be null, but only if aVal.isUndefined().
static nsresult
FromJSVal(JSContext* aCx,
JS::Handle<JS::Value> aVal,

View File

@ -2089,6 +2089,7 @@ IDBObjectStore::OpenCursorInternal(bool aKeysOnly,
ErrorResult& aRv)
{
AssertIsOnOwningThread();
MOZ_ASSERT_IF(!aCx, aRange.isUndefined());
if (mDeletedSpec) {
aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);

View File

@ -261,6 +261,16 @@ public:
aRv);
}
already_AddRefed<IDBRequest>
OpenCursor(IDBCursorDirection aDirection,
ErrorResult& aRv)
{
AssertIsOnOwningThread();
return OpenCursorInternal(/* aKeysOnly */ false, nullptr,
JS::UndefinedHandleValue, aDirection, aRv);
}
already_AddRefed<IDBRequest>
OpenKeyCursor(JSContext* aCx,
JS::Handle<JS::Value> aRange,
@ -337,6 +347,8 @@ private:
const IDBIndexParameters& aOptionalParameters,
ErrorResult& aRv);
// aCx is allowed to be null but only if aRange.isUndefined(). In that case,
// we don't actually use aCx for anything, so it's OK.
already_AddRefed<IDBRequest>
OpenCursorInternal(bool aKeysOnly,
JSContext* aCx,

View File

@ -20,13 +20,19 @@ FlushableTaskQueue::Flush()
nsresult
FlushableTaskQueue::FlushAndDispatch(already_AddRefed<nsIRunnable> aRunnable)
{
MonitorAutoLock mon(mQueueMonitor);
AutoSetFlushing autoFlush(this);
FlushLocked();
nsCOMPtr<nsIRunnable> r = dont_AddRef(aRunnable.take());
nsresult rv = DispatchLocked(r.forget(), IgnoreFlushing, AssertDispatchSuccess);
NS_ENSURE_SUCCESS(rv, rv);
AwaitIdleLocked();
nsCOMPtr<nsIRunnable> r = aRunnable;
{
MonitorAutoLock mon(mQueueMonitor);
AutoSetFlushing autoFlush(this);
FlushLocked();
nsresult rv = DispatchLocked(/* passed by ref */r, IgnoreFlushing, AssertDispatchSuccess);
NS_ENSURE_SUCCESS(rv, rv);
AwaitIdleLocked();
}
// If the ownership of |r| is not transferred in DispatchLocked() due to
// dispatch failure, it will be deleted here outside the lock. We do so
// since the destructor of the runnable might access TaskQueue and result
// in deadlocks.
return NS_OK;
}

View File

@ -662,6 +662,7 @@ void
AudioCallbackDriver::Destroy()
{
STREAM_LOG(LogLevel::Debug, ("AudioCallbackDriver destroyed."));
mAudioInput = nullptr;
mAudioStream.reset();
}

View File

@ -270,10 +270,10 @@ MP4Decoder::IsVideoAccelerated(layers::LayersBackend aBackend, nsIGlobalObject*
result.AssignLiteral("Yes");
} else {
result.AssignLiteral("No");
if (failureReason.Length()) {
result.AppendLiteral("; ");
AppendUTF8toUTF16(failureReason, result);
}
}
if (failureReason.Length()) {
result.AppendLiteral("; ");
AppendUTF8toUTF16(failureReason, result);
}
decoder->Shutdown();
taskQueue->BeginShutdown();

View File

@ -220,4 +220,38 @@ TEST(MozPromise, PromiseAllReject)
});
}
// Test we don't hit the assertions in MozPromise when exercising promise
// chaining upon task queue shutdown.
TEST(MozPromise, Chaining)
{
AutoTaskQueue atq;
RefPtr<TaskQueue> queue = atq.Queue();
MozPromiseRequestHolder<TestPromise> holder;
RunOnTaskQueue(queue, [queue, &holder] () {
auto p = TestPromise::CreateAndResolve(42, __func__);
const size_t kIterations = 100;
for (size_t i = 0; i < kIterations; ++i) {
p = p->Then(queue, __func__,
[] (int aVal) {
EXPECT_EQ(aVal, 42);
},
[] () {}
)->CompletionPromise();
if (i == kIterations / 2) {
p->Then(queue, __func__,
[queue, &holder] () {
holder.Disconnect();
queue->BeginShutdown();
},
DO_FAIL);
}
}
// We will hit the assertion if we don't disconnect the leaf Request
// in the promise chain.
holder.Begin(p->Then(queue, __func__, [] () {}, [] () {}));
});
}
#undef DO_FAIL

View File

@ -68,7 +68,6 @@ TEST_DIRS += [
MOCHITEST_MANIFESTS += [
'test/mochitest.ini',
'tests/mochitest/identity/mochitest.ini',
'tests/mochitest/ipc/mochitest.ini',
]
if CONFIG['MOZ_WEBRTC']:

View File

@ -156,13 +156,23 @@ public:
NS_IMETHOD Run() {
NS_ASSERTION(NS_IsMainThread(), "Must be on main thread.");
nsACString* failureReason = &mFailureReason;
nsCString secondFailureReason;
if (mBackend == LayersBackend::LAYERS_D3D11 &&
Preferences::GetBool("media.windows-media-foundation.allow-d3d11-dxva", true) &&
IsWin8OrLater()) {
mDXVA2Manager = DXVA2Manager::CreateD3D11DXVA(mFailureReason);
} else {
mDXVA2Manager = DXVA2Manager::CreateD3D9DXVA(mFailureReason);
mDXVA2Manager = DXVA2Manager::CreateD3D11DXVA(*failureReason);
if (mDXVA2Manager) {
return NS_OK;
}
// Try again with d3d9, but record the failure reason
// into a new var to avoid overwriting the d3d11 failure.
failureReason = &secondFailureReason;
mFailureReason.Append(NS_LITERAL_CSTRING("; "));
}
mDXVA2Manager = DXVA2Manager::CreateD3D9DXVA(*failureReason);
// Make sure we include the messages from both attempts (if applicable).
mFailureReason.Append(secondFailureReason);
return NS_OK;
}
nsAutoPtr<DXVA2Manager> mDXVA2Manager;
@ -206,14 +216,14 @@ WMFVideoMFTManager::Init()
{
bool success = InitInternal(/* aForceD3D9 = */ false);
// If initialization failed with d3d11 DXVA then try falling back
// to d3d9.
if (!success && mDXVA2Manager && mDXVA2Manager->IsD3D11()) {
mDXVA2Manager = nullptr;
nsCString d3d11Failure = mDXVAFailureReason;
success = InitInternal(true);
mDXVAFailureReason.Append(NS_LITERAL_CSTRING("; "));
mDXVAFailureReason.Append(d3d11Failure);
if (success && mDXVA2Manager) {
// If we had some failures but eventually made it work,
// make sure we preserve the messages.
if (mDXVA2Manager->IsD3D11()) {
mDXVAFailureReason.Append(NS_LITERAL_CSTRING("Using D3D11 API"));
} else {
mDXVAFailureReason.Append(NS_LITERAL_CSTRING("Using D3D9 API"));
}
}
return success;

View File

@ -577,25 +577,20 @@ skip-if = buildapp == 'b2g' && toolkit != 'gonk' # bug 1082984
[test_aspectratio_mp4.html]
[test_audio1.html]
[test_audio2.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_audioDocumentTitle.html]
skip-if = true # bug 475110 - disabled since we don't play Wave files standalone
[test_autoplay.html]
[test_autoplay_contentEditable.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only
[test_buffered.html]
[test_bug448534.html]
skip-if = buildapp == 'mulet' || os == 'win' || (toolkit == 'android' && processor == 'x86') # bug 894922 #x86 only bug 914439
skip-if = buildapp == 'mulet' || os == 'win' # bug 894922
[test_bug463162.xhtml]
[test_bug465498.html]
skip-if = (toolkit == 'android' && processor == 'x86')
[test_bug495145.html]
skip-if = (toolkit == 'android' && processor == 'x86') || (os == 'mac' && os_version == '10.6') #x86 only bug 914439, bug 1021174
skip-if = (os == 'mac' && os_version == '10.6') # bug 1021174
[test_bug495300.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_bug654550.html]
[test_bug686942.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_bug726904.html]
[test_bug874897.html]
[test_bug879717.html]
@ -614,12 +609,11 @@ tags=capturestream
tags=capturestream
[test_can_play_type.html]
[test_can_play_type_mpeg.html]
skip-if = buildapp == 'b2g' || (toolkit == 'android' && processor == 'x86') # bug 1021675 #x86 only bug 914439
skip-if = buildapp == 'b2g' # bug 1021675
[test_can_play_type_no_ogg.html]
[test_can_play_type_ogg.html]
[test_chaining.html]
[test_clone_media_element.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_closing_connections.html]
[test_constants.html]
[test_controls.html]
@ -668,7 +662,6 @@ skip-if = os == 'win' && debug #win debug : Bug 1202683
skip-if = toolkit == 'android' || (os == 'win' && !debug) || (os == 'mac' && !debug) # bug 608634
[test_error_on_404.html]
[test_fastSeek.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_fastSeek-forwards.html]
[test_gmp_playback.html]
skip-if = (os != 'win' || os_version == '5.1') # Only gmp-clearkey on Windows Vista and later decodes
@ -678,18 +671,12 @@ skip-if = (os != 'win' || os_version == '5.1') # Only gmp-clearkey on Windows Vi
[test_invalid_reject_play.html]
[test_invalid_seek.html]
[test_load.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_load_candidates.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_load_same_resource.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_load_source.html]
[test_loop.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_media_selection.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_media_sniffer.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_mediarecorder_avoid_recursion.html]
skip-if = os == 'win' && !debug # bug 1228605
tags=msg
@ -758,41 +745,30 @@ skip-if = true # bug 567954 and intermittent leaks
[test_multiple_mediastreamtracks.html]
[test_networkState.html]
[test_new_audio.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_no_load_event.html]
[test_paused.html]
[test_paused_after_ended.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_play_events.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_play_events_2.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_play_twice.html]
# Seamonkey: Bug 598252
skip-if = appname == "seamonkey"
[test_playback.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_playback_errors.html]
skip-if = toolkit == 'gonk' # bug 1128845
[test_playback_rate.html]
skip-if = (toolkit == 'android' && processor == 'x86') #bug 845162
[test_playback_rate_playpause.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_playback_reactivate.html]
#skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_played.html]
[test_preload_actions.html]
[test_preload_attribute.html]
[test_preload_suspend.html]
[test_progress.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_reactivate.html]
skip-if = toolkit == 'gonk' || (toolkit == 'android' && processor == 'x86') #x86 only bug 914439 and bug 1128845 on gonk
skip-if = toolkit == 'gonk' # bug 1128845 on gonk
[test_readyState.html]
[test_referer.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only
[test_replay_metadata.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_reset_events_async.html]
[test_reset_src.html]
[test_video_dimensions.html]
@ -802,9 +778,7 @@ skip-if = true # bug 1021673
[test_seek_negative.html]
[test_seek_nosrc.html]
[test_seek_out_of_range.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_seek-1.html]
skip-if = android_version == '10' # bug 1059116
[test_seek-2.html]
[test_seek-3.html]
[test_seek-4.html]
@ -818,24 +792,21 @@ skip-if = android_version == '10' # bug 1059116
[test_seek-12.html]
[test_seek-13.html]
[test_seekable1.html]
skip-if = (toolkit == 'android' && processor == 'x86') #timeout x86 only bug 914439
[test_seekLies.html]
[test_source.html]
[test_source_media.html]
[test_source_null.html]
[test_source_write.html]
[test_standalone.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_streams_autoplay.html]
tags=msg capturestream
[test_streams_capture_origin.html]
tags=msg capturestream
[test_streams_element_capture.html]
#x86 only bug 914439, b2g desktop bug 752796
skip-if = (toolkit == 'android' && processor == 'x86') || (buildapp == 'b2g' && toolkit != 'gonk')
skip-if = (buildapp == 'b2g' && toolkit != 'gonk')
tags=msg capturestream
[test_streams_element_capture_createObjectURL.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
tags=msg capturestream
[test_streams_element_capture_playback.html]
tags=msg capturestream
@ -859,13 +830,11 @@ tags=msg capturestream
[test_texttrackregion.html]
[test_texttrack_moz.html]
[test_timeupdate_small_files.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_trackelementevent.html]
[test_trackevent.html]
[test_unseekable.html]
skip-if = toolkit == 'gonk' || (toolkit == 'android' && processor == 'x86') #x86 only and bug 1128845 on gonk
skip-if = toolkit == 'gonk' # bug 1128845 on gonk
[test_video_to_canvas.html]
skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
[test_video_in_audio_element.html]
[test_videoDocumentTitle.html]
[test_VideoPlaybackQuality.html]

View File

@ -268,10 +268,7 @@ function setupEnvironment() {
return;
}
// Running as a Mochitest.
SimpleTest.requestFlakyTimeout("WebRTC inherently depends on timeouts");
window.finish = () => SimpleTest.finish();
SpecialPowers.pushPrefEnv({
var defaultMochitestPrefs = {
'set': [
['media.peerconnection.enabled', true],
['media.peerconnection.identity.enabled', true],
@ -285,7 +282,22 @@ function setupEnvironment() {
['media.getusermedia.audiocapture.enabled', true],
['media.recorder.audio_node.enabled', true]
]
}, setTestOptions);
};
const isAndroid = !!navigator.userAgent.includes("Android");
if (isAndroid) {
defaultMochitestPrefs.set.push(
["media.navigator.video.default_width", 320],
["media.navigator.video.default_height", 240],
["media.navigator.video.max_fr", 10]
);
}
// Running as a Mochitest.
SimpleTest.requestFlakyTimeout("WebRTC inherently depends on timeouts");
window.finish = () => SimpleTest.finish();
SpecialPowers.pushPrefEnv(defaultMochitestPrefs, setTestOptions);
// We don't care about waiting for this to complete, we just want to ensure
// that we don't build up a huge backlog of GC work.

View File

@ -1,9 +1,10 @@
[DEFAULT]
# Android 2.3 - bug 981881
# won't run on b2g desktop tests - bug 1119993
# broken HTTPS on b2g emulator - bug 1135339
# Android 4.3 - bug 981881
# Exit code -11 for linux/opt/non-e10s - bug 1256284
subsuite = media
skip-if = android_version == '10' || android_version == '18' || (buildapp == 'b2g' && toolkit != 'gonk') || (buildapp == 'b2g' && toolkit == 'gonk') || buildapp == 'mulet'
skip-if = android_version == '18' || (buildapp == 'b2g' && toolkit != 'gonk') || (buildapp == 'b2g' && toolkit == 'gonk') || buildapp == 'mulet' || (os == 'linux' && !debug && !e10s)
support-files =
/.well-known/idp-proxy/idp.js
identityPcTest.js

View File

@ -1,9 +0,0 @@
{
"runtests":{
"dom/media/tests/mochitest/test_getUserMedia_basicVideoAudio.html":"included",
"dom/media/tests/mochitest/test_peerConnection_basicAudioVideo.html":"included",
"dom/media/tests/mochitest/test_dataChannel_basicAudioVideo.html":"included"
},
"excludetests":{
}
}

View File

@ -1,10 +0,0 @@
[DEFAULT]
tags=msg
subsuite=media
support-files =
ipc.json
skip-if = e10s
[test_ipc.html]
skip-if = buildapp == 'b2g' || buildapp == 'mulet' || toolkit == 'android' #bug 910661 # b2g(nested ipc not working) b2g-debug(debug-only failure) b2g-desktop(nested ipc not working)

View File

@ -1,176 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for OOP PeerConncection</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<script type="application/javascript;version=1.7">
"use strict";
SimpleTest.waitForExplicitFinish();
// This isn't a single test. It runs the entirety of the PeerConnection
// tests. Each of those has a normal timeout handler, so there's no point in
// having a timeout here. I'm setting this really high just to avoid getting
// killed.
SimpleTest.requestLongerTimeout(100);
// The crash observer registration functions are stubbed out here to
// prevent the iframe test runner from breaking later crash-related tests.
function iframeScriptFirst() {
SpecialPowers.prototype.registerProcessCrashObservers = () => {};
SpecialPowers.prototype.unregisterProcessCrashObservers = () => {};
content.wrappedJSObject.RunSet.reloadAndRunAll({
preventDefault: function() { },
__exposedProps__: { preventDefault: 'r' }
});
}
function iframeScriptSecond() {
let TestRunner = content.wrappedJSObject.TestRunner;
let oldComplete = TestRunner.onComplete;
TestRunner.onComplete = function() {
TestRunner.onComplete = oldComplete;
sendAsyncMessage("test:PeerConnection:ipcTestComplete", {
result: JSON.stringify(TestRunner._failedTests)
});
if (oldComplete) {
oldComplete();
}
};
TestRunner.structuredLogger._dumpMessage = function(msg) {
sendAsyncMessage("test:PeerConnection:ipcTestMessage", { msg: msg });
}
}
let VALID_ACTIONS = ['suite_start', 'suite_end', 'test_start', 'test_end', 'test_status', 'process_output', 'log'];
function validStructuredMessage(message) {
return message.action !== undefined && VALID_ACTIONS.indexOf(message.action) >= 0;
}
function onTestMessage(data) {
let message = SpecialPowers.wrap(data).data.msg;
if (validStructuredMessage(message)) {
switch (message.action) {
case "test_status":
case "test_end":
let test_tokens = message.test.split("/");
let test_name = test_tokens[test_tokens.length - 1];
if (message.subtest) {
test_name += " | " + message.subtest;
}
ok(message.expected === undefined, test_name, message.message);
break;
case "log":
info(message.message);
break;
default:
// nothing
}
}
}
function onTestComplete() {
let comp = SpecialPowers.wrap(SpecialPowers.Components);
let mm = SpecialPowers.getBrowserFrameMessageManager(iframe);
let spObserver = comp.classes["@mozilla.org/special-powers-observer;1"]
.getService(comp.interfaces.nsIMessageListener);
mm.removeMessageListener("SPPrefService", spObserver);
mm.removeMessageListener("SPProcessCrashService", spObserver);
mm.removeMessageListener("SPPingService", spObserver);
mm.removeMessageListener("SpecialPowers.Quit", spObserver);
mm.removeMessageListener("SPPermissionManager", spObserver);
mm.removeMessageListener("test:PeerConnection:ipcTestMessage", onTestMessage);
mm.removeMessageListener("test:PeerConnection:ipcTestComplete", onTestComplete);
SimpleTest.executeSoon(function () { SimpleTest.finish(); });
}
function runTests() {
let iframe = document.createElement("iframe");
SpecialPowers.wrap(iframe).mozbrowser = true;
iframe.id = "iframe";
iframe.style.width = "100%";
iframe.style.height = "1000px";
function iframeLoadSecond() {
ok(true, "Got second iframe load event.");
iframe.removeEventListener("mozbrowserloadend", iframeLoadSecond);
let mm = SpecialPowers.getBrowserFrameMessageManager(iframe);
mm.loadFrameScript("data:,(" + iframeScriptSecond.toString() + ")();",
false);
}
function iframeLoadFirst() {
ok(true, "Got first iframe load event.");
iframe.removeEventListener("mozbrowserloadend", iframeLoadFirst);
iframe.addEventListener("mozbrowserloadend", iframeLoadSecond);
let mm = SpecialPowers.getBrowserFrameMessageManager(iframe);
let comp = SpecialPowers.wrap(SpecialPowers.Components);
let spObserver =
comp.classes["@mozilla.org/special-powers-observer;1"]
.getService(comp.interfaces.nsIMessageListener);
mm.addMessageListener("SPPrefService", spObserver);
mm.addMessageListener("SPProcessCrashService", spObserver);
mm.addMessageListener("SPPingService", spObserver);
mm.addMessageListener("SpecialPowers.Quit", spObserver);
mm.addMessageListener("SPPermissionManager", spObserver);
mm.addMessageListener("test:PeerConnection:ipcTestMessage", onTestMessage);
mm.addMessageListener("test:PeerConnection:ipcTestComplete", onTestComplete);
let specialPowersBase = "chrome://specialpowers/content/";
mm.loadFrameScript(specialPowersBase + "MozillaLogger.js", false);
mm.loadFrameScript(specialPowersBase + "specialpowersAPI.js", false);
mm.loadFrameScript(specialPowersBase + "specialpowers.js", false);
mm.loadFrameScript("data:,(" + iframeScriptFirst.toString() + ")();", false);
}
iframe.addEventListener("mozbrowserloadend", iframeLoadFirst);
// Strip the filename and a directory level.
let href = window.location.href;
href = href.substring(0, href.lastIndexOf('/'));
href = href.substring(0, href.lastIndexOf('/'));
href += "?consoleLevel=INFO" +
"&testManifest=tests/dom/media/tests/mochitest/ipc/ipc.json";
iframe.src = href;
document.body.appendChild(iframe);
}
addEventListener("load", function() {
SpecialPowers.addPermission("browser", true, document);
SpecialPowers.pushPrefEnv({
"set": [
["media.peerconnection.ipc.enabled", true],
// TODO: remove this as part of bug 820712
["network.disable.ipc.security", true],
["dom.ipc.browser_frames.oop_by_default", true],
["dom.mozBrowserFramesEnabled", true],
["browser.pagethumbnails.capturing_disabled", true]
]
}, runTests);
});
</script>
</body>
</html>

View File

@ -1,8 +1,7 @@
[DEFAULT]
# Android 2.3 - bug 981881
tags = msg webrtc
subsuite = media
skip-if = android_version == '10' || (buildapp == 'mulet') || (toolkit == 'gonk' && debug) # b2g(Either bug 1171118 or bug 1169838, take your pick)
skip-if = (buildapp == 'mulet') || (toolkit == 'gonk' && debug) # b2g(Either bug 1171118 or bug 1169838, take your pick)
support-files =
head.js
dataChannel.js

View File

@ -41,7 +41,7 @@ support-files =
[test_audioBufferSourceNodeLoopStartEnd.html]
[test_audioBufferSourceNodeLoopStartEndSame.html]
[test_audioBufferSourceNodeDetached.html]
skip-if = (toolkit == 'android' && (processor == 'x86' || debug)) || os == 'win' # bug 1127845, bug 1138468
skip-if = (toolkit == 'android' && debug) || os == 'win' # bug 1127845, bug 1138468
[test_audioBufferSourceNodeNoStart.html]
[test_audioBufferSourceNodeNullBuffer.html]
[test_audioBufferSourceNodeOffset.html]
@ -146,10 +146,10 @@ tags=capturestream
[test_mediaStreamAudioSourceNodeResampling.html]
tags=capturestream
[test_mixingRules.html]
skip-if = android_version == '10' || android_version == '18' # bug 1091965
skip-if = toolkit == 'android' # bug 1091965
[test_mozaudiochannel.html]
# Android: bug 1061675; OSX 10.6: bug 1097721
skip-if = (toolkit == 'gonk' && !debug) || android_version == '10' || android_version == '18' || (os == 'mac' && os_version == '10.6')
skip-if = (toolkit == 'gonk' && !debug) || (toolkit == 'android') || (os == 'mac' && os_version == '10.6')
[test_nodeToParamConnection.html]
[test_OfflineAudioContext.html]
[test_offlineDestinationChannelCountLess.html]

View File

@ -42,6 +42,7 @@ MediaEngineTabVideoSource::MediaEngineTabVideoSource()
, mViewportHeight(0)
, mTimePerFrame(0)
, mDataSize(0)
, mBlackedoutWindow(false)
, mMonitor("MediaEngineTabVideoSource") {}
nsresult
@ -80,19 +81,26 @@ MediaEngineTabVideoSource::Notify(nsITimer*) {
Draw();
return NS_OK;
}
#define LOGTAG "TabVideo"
nsresult
MediaEngineTabVideoSource::InitRunnable::Run()
{
if (mVideoSource->mWindowId != -1) {
nsCOMPtr<nsPIDOMWindowOuter> window =
nsGlobalWindow::GetOuterWindowWithId(mVideoSource->mWindowId)->AsOuter();
if (window) {
mVideoSource->mWindow = window;
nsGlobalWindow* globalWindow =
nsGlobalWindow::GetOuterWindowWithId(mVideoSource->mWindowId);
if (!globalWindow) {
// We can't access the window, just send a blacked out screen.
mVideoSource->mWindow = nullptr;
mVideoSource->mBlackedoutWindow = true;
} else {
nsCOMPtr<nsPIDOMWindowOuter> window = globalWindow->AsOuter();
if (window) {
mVideoSource->mWindow = window;
mVideoSource->mBlackedoutWindow = false;
}
}
}
if (!mVideoSource->mWindow) {
if (!mVideoSource->mWindow && !mVideoSource->mBlackedoutWindow) {
nsresult rv;
mVideoSource->mTabSource = do_GetService(NS_TABSOURCESERVICE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
@ -104,6 +112,7 @@ MediaEngineTabVideoSource::InitRunnable::Run()
return NS_OK;
mVideoSource->mWindow = nsPIDOMWindowOuter::From(win);
MOZ_ASSERT(mVideoSource->mWindow);
}
nsCOMPtr<nsIRunnable> start(new StartRunnable(mVideoSource));
start->Run();
@ -211,24 +220,33 @@ MediaEngineTabVideoSource::NotifyPull(MediaStreamGraph*,
void
MediaEngineTabVideoSource::Draw() {
if (!mWindow) {
if (!mWindow && !mBlackedoutWindow) {
return;
}
if (mScrollWithPage || mViewportWidth == INT32_MAX) {
mWindow->GetInnerWidth(&mViewportWidth);
}
if (mScrollWithPage || mViewportHeight == INT32_MAX) {
mWindow->GetInnerHeight(&mViewportHeight);
}
if (!mViewportWidth || !mViewportHeight) {
return;
if (mWindow) {
if (mScrollWithPage || mViewportWidth == INT32_MAX) {
mWindow->GetInnerWidth(&mViewportWidth);
}
if (mScrollWithPage || mViewportHeight == INT32_MAX) {
mWindow->GetInnerHeight(&mViewportHeight);
}
if (!mViewportWidth || !mViewportHeight) {
return;
}
} else {
mViewportWidth = 640;
mViewportHeight = 480;
}
IntSize size;
{
float pixelRatio;
mWindow->GetDevicePixelRatio(&pixelRatio);
if (mWindow) {
mWindow->GetDevicePixelRatio(&pixelRatio);
} else {
pixelRatio = 1.0f;
}
const int32_t deviceWidth = (int32_t)(pixelRatio * mViewportWidth);
const int32_t deviceHeight = (int32_t)(pixelRatio * mViewportHeight);
@ -255,7 +273,7 @@ MediaEngineTabVideoSource::Draw() {
}
nsCOMPtr<nsIPresShell> presShell;
{
if (mWindow) {
RefPtr<nsPresContext> presContext;
nsIDocShell* docshell = mWindow->GetDocShell();
if (docshell) {
@ -267,15 +285,6 @@ MediaEngineTabVideoSource::Draw() {
presShell = presContext->PresShell();
}
nscolor bgColor = NS_RGB(255, 255, 255);
uint32_t renderDocFlags = mScrollWithPage? 0 :
(nsIPresShell::RENDER_IGNORE_VIEWPORT_SCROLLING |
nsIPresShell::RENDER_DOCUMENT_RELATIVE);
nsRect r(nsPresContext::CSSPixelsToAppUnits((float)mViewportOffsetX),
nsPresContext::CSSPixelsToAppUnits((float)mViewportOffsetY),
nsPresContext::CSSPixelsToAppUnits((float)mViewportWidth),
nsPresContext::CSSPixelsToAppUnits((float)mViewportHeight));
RefPtr<layers::ImageContainer> container = layers::LayerManager::CreateImageContainer();
RefPtr<DrawTarget> dt =
Factory::CreateDrawTargetForData(BackendType::CAIRO,
@ -290,7 +299,17 @@ MediaEngineTabVideoSource::Draw() {
context->SetMatrix(context->CurrentMatrix().Scale((((float) size.width)/mViewportWidth),
(((float) size.height)/mViewportHeight)));
NS_ENSURE_SUCCESS_VOID(presShell->RenderDocument(r, renderDocFlags, bgColor, context));
if (mWindow) {
nscolor bgColor = NS_RGB(255, 255, 255);
uint32_t renderDocFlags = mScrollWithPage? 0 :
(nsIPresShell::RENDER_IGNORE_VIEWPORT_SCROLLING |
nsIPresShell::RENDER_DOCUMENT_RELATIVE);
nsRect r(nsPresContext::CSSPixelsToAppUnits((float)mViewportOffsetX),
nsPresContext::CSSPixelsToAppUnits((float)mViewportOffsetY),
nsPresContext::CSSPixelsToAppUnits((float)mViewportWidth),
nsPresContext::CSSPixelsToAppUnits((float)mViewportHeight));
NS_ENSURE_SUCCESS_VOID(presShell->RenderDocument(r, renderDocFlags, bgColor, context));
}
RefPtr<SourceSurface> surface = dt->Snapshot();
if (!surface) {
@ -306,8 +325,11 @@ MediaEngineTabVideoSource::Draw() {
nsresult
MediaEngineTabVideoSource::Stop(mozilla::SourceMediaStream*, mozilla::TrackID)
{
if (!mWindow)
// If mBlackedoutWindow is true, we may be running
// despite mWindow == nullptr.
if (!mWindow && !mBlackedoutWindow) {
return NS_OK;
}
NS_DispatchToMainThread(new StopRunnable(this));
return NS_OK;

View File

@ -89,6 +89,8 @@ private:
UniquePtr<unsigned char[]> mData;
size_t mDataSize;
nsCOMPtr<nsPIDOMWindowOuter> mWindow;
// If this is set, we will run despite mWindow == nullptr.
bool mBlackedoutWindow;
RefPtr<layers::SourceSurfaceImage> mImage;
nsCOMPtr<nsITimer> mTimer;
Monitor mMonitor;

View File

@ -220,9 +220,6 @@ MediaEngineWebRTC::EnumerateVideoDevices(dom::MediaSourceEnum aMediaSource,
num = mozilla::camera::GetChildAndCall(
&mozilla::camera::CamerasChild::NumberOfCaptureDevices,
capEngine);
if (num <= 0) {
return;
}
for (int i = 0; i < num; i++) {
char deviceName[MediaEngineSource::kMaxDeviceNameLength];

View File

@ -13,6 +13,8 @@
#include "SpeechSynthesisUtterance.h"
#include "SpeechSynthesisVoice.h"
#include <stdlib.h>
namespace mozilla {
namespace dom {
@ -120,7 +122,7 @@ SpeechSynthesisUtterance::Volume() const
void
SpeechSynthesisUtterance::SetVolume(float aVolume)
{
mVolume = aVolume;
mVolume = std::max<float>(std::min<float>(aVolume, 1), 0);
}
float
@ -132,7 +134,7 @@ SpeechSynthesisUtterance::Rate() const
void
SpeechSynthesisUtterance::SetRate(float aRate)
{
mRate = aRate;
mRate = std::max<float>(std::min<float>(aRate, 10), 0.1f);
}
float
@ -144,7 +146,7 @@ SpeechSynthesisUtterance::Pitch() const
void
SpeechSynthesisUtterance::SetPitch(float aPitch)
{
mPitch = aPitch;
mPitch = std::max<float>(std::min<float>(aPitch, 2), 0);
}
void

View File

@ -48,6 +48,24 @@ is(ssu.volume, 0.5, "SpeechSynthesisUtterance.volume is correct");
is(ssu.rate, 2.0, "SpeechSynthesisUtterance.rate is correct");
is(ssu.pitch, 1.5, "SpeechSynthesisUtterance.pitch is correct");
// Assign a rate that is out of bounds
ssu.rate = 20;
is(ssu.rate, 10, "SpeechSynthesisUtterance.rate enforces max of 10");
ssu.rate = 0;
is(ssu.rate.toPrecision(1), "0.1", "SpeechSynthesisUtterance.rate enforces min of 0.1");
// Assign a volume which is out of bounds
ssu.volume = 2;
is(ssu.volume, 1, "SpeechSynthesisUtterance.volume enforces max of 1");
ssu.volume = -1;
is(ssu.volume, 0, "SpeechSynthesisUtterance.volume enforces min of 0");
// Assign a pitch which is out of bounds
ssu.pitch = 2.1;
is(ssu.pitch, 2, "SpeechSynthesisUtterance.pitch enforces max of 2");
ssu.pitch = -1;
is(ssu.pitch, 0, "SpeechSynthesisUtterance.pitch enforces min of 0");
// Test for singleton instance hanging off of window.
ok(speechSynthesis, "speechSynthesis exists in global scope");
is(typeof speechSynthesis, "object", "speechSynthesis instance is an object");

View File

@ -255,6 +255,17 @@ Object.assign(PushServiceParent.prototype, {
let name = requestName.slice("Push:".length);
return "PushService:" + name + ":" + suffix;
},
// Methods used for mocking in tests.
replaceServiceBackend(options) {
this._service.changeTestServer(options.serverURI, options);
},
restoreServiceBackend() {
var defaultServerURL = Services.prefs.getCharPref("dom.push.serverURL");
this._service.changeTestServer(defaultServerURL);
},
});
/**

View File

@ -235,6 +235,20 @@ this.PushService = {
}
},
// Used for testing.
changeTestServer(url, options = {}) {
console.debug("changeTestServer()");
this._stateChangeProcessEnqueue(_ => {
if (this._state < PUSH_SERVICE_ACTIVATING) {
console.debug("changeTestServer: PushService not activated?");
return Promise.resolve();
}
return this._changeServerURL(url, CHANGING_SERVICE_EVENT, options);
});
},
observe: function observe(aSubject, aTopic, aData) {
switch (aTopic) {
/*
@ -367,7 +381,7 @@ this.PushService = {
return [service, uri];
},
_changeServerURL: function(serverURI, event) {
_changeServerURL: function(serverURI, event, options = {}) {
console.debug("changeServerURL()");
switch(event) {
@ -392,7 +406,7 @@ this.PushService = {
if (this._state == PUSH_SERVICE_INIT) {
this._setState(PUSH_SERVICE_ACTIVATING);
// The service has not been running - start it.
return this._startService(service, uri)
return this._startService(service, uri, options)
.then(_ => this._stateChangeProcessEnqueue(_ =>
this._changeStateConnectionEnabledEvent(prefs.get("connection.enabled")))
);
@ -404,7 +418,7 @@ this.PushService = {
// check is called in changeStateConnectionEnabledEvent function)
return this._stopService(CHANGING_SERVICE_EVENT)
.then(_ =>
this._startService(service, uri)
this._startService(service, uri, options)
)
.then(_ => this._stateChangeProcessEnqueue(_ =>
this._changeStateConnectionEnabledEvent(prefs.get("connection.enabled")))
@ -610,9 +624,10 @@ this.PushService = {
this._stateChangeProcessEnqueue(_ =>
{
this._changeServerURL("", UNINIT_EVENT);
var p = this._changeServerURL("", UNINIT_EVENT);
this._setState(PUSH_SERVICE_UNINIT);
console.debug("uninit: shutdown complete!");
return p;
});
},

View File

@ -2,11 +2,11 @@
subsuite = push
support-files =
worker.js
push-server.sjs
frame.html
webpush.js
lifetime_worker.js
test_utils.js
mockpushserviceparent.js
skip-if = os == "android" || toolkit == "gonk"
[test_has_permissions.html]

View File

@ -0,0 +1,111 @@
"use strict";
const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
/**
* Defers one or more callbacks until the next turn of the event loop. Multiple
* callbacks are executed in order.
*
* @param {Function[]} callbacks The callbacks to execute. One callback will be
* executed per tick.
*/
function waterfall(...callbacks) {
callbacks.reduce((promise, callback) => promise.then(() => {
callback();
}), Promise.resolve()).catch(Cu.reportError);
}
/**
* Minimal implementation of a mock WebSocket connect to be used with
* PushService. Forwards and receive messages from the implementation
* that lives in the content process.
*/
function MockWebSocketParent(originalURI) {
this._originalURI = originalURI;
}
MockWebSocketParent.prototype = {
_originalURI: null,
_listener: null,
_context: null,
QueryInterface: XPCOMUtils.generateQI([
Ci.nsISupports,
Ci.nsIWebSocketChannel
]),
get originalURI() {
return this._originalURI;
},
asyncOpen(uri, origin, windowId, listener, context) {
this._listener = listener;
this._context = context;
waterfall(() => this._listener.onStart(this._context));
},
sendMsg(msg) {
sendAsyncMessage("client-msg", msg);
},
close() {
waterfall(() => this._listener.onStop(this._context, Cr.NS_OK));
},
serverSendMsg(msg) {
waterfall(() => this._listener.onMessageAvailable(this._context, msg),
() => this._listener.onAcknowledge(this._context, 0));
},
};
function MockNetworkInfo() {}
MockNetworkInfo.prototype = {
getNetworkInformation() {
return {mcc: '', mnc: '', ip: ''};
},
getNetworkState(callback) {
callback({mcc: '', mnc: '', ip: '', netid: ''});
},
getNetworkStateChangeEventName() {
return 'network:offline-status-changed';
}
};
var pushService = Cc["@mozilla.org/push/Service;1"].
getService(Ci.nsIPushService).
wrappedJSObject;
var mockWebSocket;
addMessageListener("setup", function () {
mockWebSocket = new Promise((resolve, reject) => {
pushService.replaceServiceBackend({
serverURI: "wss://push.example.org/",
networkInfo: new MockNetworkInfo(),
makeWebSocket(uri) {
var socket = new MockWebSocketParent(uri);
resolve(socket);
return socket;
}
});
});
});
addMessageListener("teardown", function () {
mockWebSocket.then(socket => {
socket.close();
pushService.restoreServiceBackend();
});
});
addMessageListener("server-msg", function (msg) {
mockWebSocket.then(socket => {
socket.serverSendMsg(msg);
});
});

View File

@ -1,59 +0,0 @@
function debug(str) {
// dump("@@@ push-server " + str + "\n");
}
function concatUint8Arrays(arrays, size) {
let index = 0;
return arrays.reduce((result, a) => {
result.set(new Uint8Array(a), index);
index += a.byteLength;
return result;
}, new Uint8Array(size));
}
function handleRequest(request, response)
{
debug("handling request!");
const Cc = Components.classes;
const Ci = Components.interfaces;
let params = request.getHeader("X-Push-Server");
debug("params = " + params);
let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest);
xhr.open(request.getHeader("X-Push-Method"), params);
for (let headers = request.headers; headers.hasMoreElements();) {
let header = headers.getNext().QueryInterface(Ci.nsISupportsString).data;
if (header.toLowerCase() != "x-push-server") {
xhr.setRequestHeader(header, request.getHeader(header));
}
}
let bodyStream = Cc["@mozilla.org/binaryinputstream;1"].createInstance(Ci.nsIBinaryInputStream);
bodyStream.setInputStream(request.bodyInputStream);
let size = 0;
let data = [];
for (let available; available = bodyStream.available();) {
data.push(bodyStream.readByteArray(available));
size += available;
}
function reply(statusCode, statusText) {
response.setStatusLine(request.httpVersion, statusCode, statusText);
response.finish();
}
xhr.onload = function(e) {
debug("xhr : " + this.status);
reply(this.status, this.statusText);
};
xhr.onerror = function(e) {
debug("xhr error: " + e);
reply(500, "Internal Server Error");
};
response.processAsync();
xhr.send(concatUint8Arrays(data, size));
}

View File

@ -25,10 +25,24 @@ http://creativecommons.org/licenses/publicdomain/
</pre>
<script class="testbody" type="text/javascript">
var userAgentID = "ac44402c-85fc-41e4-a0d0-483316d15351";
var channelID = null;
var mockSocket = new MockWebSocket();
mockSocket.onRegister = function(request) {
channelID = request.channelID;
this.serverSendMsg(JSON.stringify({
messageType: "register",
uaid: userAgentID,
channelID,
status: 200,
pushEndpoint: "https://example.com/endpoint/1"
}));
};
var registration;
add_task(function* start() {
yield setupPrefs();
yield setupPrefsAndMock(mockSocket);
yield setPushPermission(true);
var url = "worker.js" + "?" + (Math.random());
@ -104,10 +118,28 @@ http://creativecommons.org/licenses/publicdomain/
);
});
var version = 0;
function sendEncryptedMsg(pushSubscription, message) {
return webPushEncrypt(pushSubscription, message)
.then((encryptedData) => {
mockSocket.serverSendMsg(JSON.stringify({
messageType: 'notification',
version: version++,
channelID: channelID,
data: encryptedData.data,
headers: {
encryption: encryptedData.encryption,
encryption_key: encryptedData.encryption_key,
encoding: encryptedData.encoding
}
}));
});
}
function waitForMessage(pushSubscription, message) {
return Promise.all([
controlledFrame.waitOnWorkerMessage("finished"),
webpush(pushSubscription, message, 120),
sendEncryptedMsg(pushSubscription, message),
]).then(([message]) => message);
}
@ -159,18 +191,15 @@ http://creativecommons.org/licenses/publicdomain/
});
is(text, "Hi! \ud83d\udc40", "Wrong blob data for message with emoji");
var finishedPromise = controlledFrame.waitOnWorkerMessage("finished");
// Send a blank message.
var [message] = yield Promise.all([
controlledFrame.waitOnWorkerMessage("finished"),
fetch("http://mochi.test:8888/tests/dom/push/test/push-server.sjs", {
method: "PUT",
headers: {
"X-Push-Method": "POST",
"X-Push-Server": pushSubscription.endpoint,
"TTL": "120",
},
}),
]);
mockSocket.serverSendMsg(JSON.stringify({
messageType: "notification",
version: "vDummy",
channelID: channelID
}));
var message = yield finishedPromise;
ok(!message.data, "Should exclude data for blank messages");
});

View File

@ -10,6 +10,7 @@ http://creativecommons.org/licenses/publicdomain/
<head>
<title>Test for Bug 1038811</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/dom/push/test/test_utils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
</head>
@ -118,13 +119,7 @@ http://creativecommons.org/licenses/publicdomain/
}).then(SimpleTest.finish);
}
SpecialPowers.pushPrefEnv({"set": [
["dom.push.enabled", true],
["dom.push.connection.enabled", true],
["dom.serviceWorkers.exemptFromPerDomainMax", true],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true]
]}, runTest);
setupPrefsAndMock(new MockWebSocket()).then(_ => runTest());
SpecialPowers.addPermission("desktop-notification", true, document);
SimpleTest.waitForExplicitFinish();
</script>

View File

@ -10,6 +10,7 @@ http://creativecommons.org/licenses/publicdomain/
<head>
<title>Test for Bug 1150812</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/dom/push/test/test_utils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
</head>
@ -113,13 +114,7 @@ http://creativecommons.org/licenses/publicdomain/
}).then(SimpleTest.finish);
}
SpecialPowers.pushPrefEnv({"set": [
["dom.push.enabled", true],
["dom.push.connection.enabled", true],
["dom.serviceWorkers.exemptFromPerDomainMax", true],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true]
]}, runTest);
setupPrefsAndMock(new MockWebSocket()).then(_ => runTest());
SpecialPowers.addPermission("desktop-notification", true, document);
SimpleTest.waitForExplicitFinish();
</script>

View File

@ -12,6 +12,7 @@ http://creativecommons.org/licenses/publicdomain/
<head>
<title>Test for Bug 1150812</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/dom/push/test/test_utils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
</head>
@ -54,13 +55,11 @@ http://creativecommons.org/licenses/publicdomain/
});
}
var defaultServerURL = SpecialPowers.getCharPref("dom.push.serverURL");
function setupMultipleSubscriptions(swr) {
// We need to do this to restart service so that a queue will be formed.
SpecialPowers.pushPrefEnv({"set": [["dom.push.serverURL", defaultServerURL]]},
null);
teardownMockPushService();
setupMockPushService(new MockWebSocket());
return Promise.all([
subscribe(swr),
subscribe(swr)
@ -100,14 +99,7 @@ var defaultServerURL = SpecialPowers.getCharPref("dom.push.serverURL");
}).then(SimpleTest.finish);
}
SpecialPowers.pushPrefEnv({"set": [
["dom.push.enabled", true],
["dom.push.connection.enabled", true],
["dom.serviceWorkers.exemptFromPerDomainMax", true],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true],
["dom.push.serverURL", "wss://something.org"]
]}, runTest);
setupPrefsAndMock(new MockWebSocket()).then(_ => runTest());
SpecialPowers.addPermission("desktop-notification", true, document);
SimpleTest.waitForExplicitFinish();
</script>

View File

@ -31,7 +31,7 @@ http://creativecommons.org/licenses/publicdomain/
var registration;
add_task(function* start() {
yield setupPrefs();
yield setupPrefsAndMock(new MockWebSocket());
yield setPushPermission(false);
var url = "worker.js" + "?" + Math.random();

View File

@ -29,9 +29,24 @@ http://creativecommons.org/licenses/publicdomain/
// console.log(str + "\n");
}
var mockSocket = new MockWebSocket();
var channelID = null;
mockSocket.onRegister = function(request) {
channelID = request.channelID;
this.serverSendMsg(JSON.stringify({
messageType: "register",
uaid: "c69e2014-9e15-438d-b253-d79cc2df60a8",
channelID,
status: 200,
pushEndpoint: "https://example.com/endpoint/1"
}));
};
var registration;
add_task(function* start() {
yield setupPrefs();
yield setupPrefsAndMock(mockSocket);
yield setPushPermission(true);
var url = "worker.js" + "?" + (Math.random());
@ -64,17 +79,16 @@ http://creativecommons.org/licenses/publicdomain/
});
add_task(function* waitForPushNotification() {
yield Promise.all([
controlledFrame.waitOnWorkerMessage("finished"),
fetch("http://mochi.test:8888/tests/dom/push/test/push-server.sjs", {
method: "PUT",
headers: {
"X-Push-Method": "POST",
"X-Push-Server": pushSubscription.endpoint,
"TTL": "120",
},
}),
]);
var finishedPromise = controlledFrame.waitOnWorkerMessage("finished");
// Send a blank message.
mockSocket.serverSendMsg(JSON.stringify({
messageType: "notification",
version: "vDummy",
channelID: channelID
}));
yield finishedPromise;
});
add_task(function* unsubscribe() {

View File

@ -23,6 +23,7 @@
<head>
<title>Test for Bug 1188545</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/dom/push/test/test_utils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
</head>
@ -71,14 +72,27 @@
return p;
}
var mockSocket = new MockWebSocket();
var endpoint = "https://example.com/endpoint/1";
var channelID = null;
mockSocket.onRegister = function(request) {
channelID = request.channelID;
this.serverSendMsg(JSON.stringify({
messageType: "register",
uaid: "fa8f2e4b-5ddc-4408-b1e3-5f25a02abff0",
channelID,
status: 200,
pushEndpoint: endpoint
}));
};
function sendPushToPushServer(pushEndpoint) {
// Work around CORS for now.
var xhr = new XMLHttpRequest();
xhr.open('GET', "http://mochi.test:8888/tests/dom/push/test/push-server.sjs", true);
xhr.setRequestHeader("X-Push-Method", "POST");
xhr.setRequestHeader("X-Push-Server", pushEndpoint);
xhr.setRequestHeader("TTL", "120");
xhr.send(null);
is(pushEndpoint, endpoint, "Got unexpected endpoint");
mockSocket.serverSendMsg(JSON.stringify({
messageType: "notification",
version: "vDummy",
channelID
}));
}
function unregisterPushNotification(ctx) {
@ -321,13 +335,7 @@
}).then(SimpleTest.finish);
}
SpecialPowers.pushPrefEnv({"set": [
["dom.push.enabled", true],
["dom.push.connection.enabled", true],
["dom.serviceWorkers.exemptFromPerDomainMax", true],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true],
]}, runTest);
setupPrefsAndMock(mockSocket).then(_ => runTest());
SpecialPowers.addPermission('desktop-notification', true, document);
SimpleTest.waitForExplicitFinish();
</script>

View File

@ -27,7 +27,7 @@ http://creativecommons.org/licenses/publicdomain/
var registration;
add_task(function* start() {
yield setupPrefs();
yield setupPrefsAndMock(new MockWebSocket());
yield setPushPermission(true);
var url = "worker.js" + "?" + (Math.random());

View File

@ -10,6 +10,7 @@ http://creativecommons.org/licenses/publicdomain/
<head>
<title>Test for Bug 1170817</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/dom/push/test/test_utils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
</head>
@ -79,13 +80,7 @@ http://creativecommons.org/licenses/publicdomain/
}).then(SimpleTest.finish);
}
SpecialPowers.pushPrefEnv({"set": [
["dom.push.enabled", true],
["dom.push.connection.enabled", true],
["dom.serviceWorkers.exemptFromPerDomainMax", true],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true]
]}, runTest);
setupPrefsAndMock(new MockWebSocket()).then(_ => runTest());
SpecialPowers.addPermission("desktop-notification", true, document);
SimpleTest.waitForExplicitFinish();
</script>

View File

@ -1,11 +1,115 @@
(function (g) {
"use strict";
let url = SimpleTest.getTestFileURL("mockpushserviceparent.js");
let chromeScript = SpecialPowers.loadChromeScript(url);
let userAgentID = "8e1c93a9-139b-419c-b200-e715bb1e8ce8";
let currentMockSocket = null;
function setupMockPushService(mockWebSocket) {
currentMockSocket = mockWebSocket;
currentMockSocket._isActive = true;
chromeScript.sendSyncMessage("setup");
chromeScript.addMessageListener("client-msg", function(msg) {
mockWebSocket.handleMessage(msg);
});
}
function teardownMockPushService() {
if (currentMockSocket) {
currentMockSocket._isActive = false;
chromeScript.sendSyncMessage("teardown");
}
}
/**
* Minimal implementation of web sockets for use in testing. Forwards
* messages to a mock web socket in the parent process that is used
* by the push service.
*/
function MockWebSocket() {}
let registerCount = 0;
// Default implementation to make the push server work minimally.
// Override methods to implement custom functionality.
MockWebSocket.prototype = {
// We only allow one active mock web socket to talk to the parent.
// This flag is used to keep track of which mock web socket is active.
_isActive: false,
onHello(request) {
this.serverSendMsg(JSON.stringify({
messageType: "hello",
uaid: userAgentID,
status: 200,
use_webpush: true,
}));
},
onRegister(request) {
this.serverSendMsg(JSON.stringify({
messageType: "register",
uaid: userAgentID,
channelID: request.channelID,
status: 200,
pushEndpoint: "https://example.com/endpoint/" + registerCount++
}));
},
onUnregister(request) {
// Do nothing.
},
onAck(request) {
// Do nothing.
},
handleMessage(msg) {
let request = JSON.parse(msg);
let messageType = request.messageType;
switch (messageType) {
case "hello":
this.onHello(request);
break;
case "register":
this.onRegister(request);
break;
case "unregister":
this.onUnregister(request);
break;
case "ack":
this.onAck(request);
break;
default:
throw new Error("Unexpected message: " + messageType);
}
},
serverSendMsg(msg) {
if (this._isActive) {
chromeScript.sendAsyncMessage("server-msg", msg);
}
},
};
g.MockWebSocket = MockWebSocket;
g.setupMockPushService = setupMockPushService;
g.teardownMockPushService = teardownMockPushService;
}(this));
// Remove permissions and prefs when the test finishes.
SimpleTest.registerCleanupFunction(() =>
SimpleTest.registerCleanupFunction(() => {
new Promise(resolve => {
SpecialPowers.flushPermissions(_ => {
SpecialPowers.flushPrefEnv(resolve);
});
})
);
}).then(_ => {
teardownMockPushService();
});
});
function setPushPermission(allow) {
return new Promise(resolve => {
@ -15,8 +119,9 @@ function setPushPermission(allow) {
});
}
function setupPrefs() {
function setupPrefsAndMock(mockSocket) {
return new Promise(resolve => {
setupMockPushService(mockSocket);
SpecialPowers.pushPrefEnv({"set": [
["dom.push.enabled", true],
["dom.push.connection.enabled", true],

View File

@ -161,15 +161,7 @@
}).then(bsConcat);
}
/*
* Request push for a message. This returns a promise that resolves when the
* push has been delivered to the push service.
*
* @param subscription A PushSubscription that contains endpoint and p256dh
* parameters.
* @param data The message to send.
*/
function webpush(subscription, data, ttl) {
function webPushEncrypt(subscription, data) {
data = ensureView(data);
var salt = g.crypto.getRandomValues(new Uint8Array(16));
@ -181,27 +173,14 @@
webCrypto.exportKey('raw', localKey.publicKey),
]);
}).then(([payload, pubkey]) => {
var options = {
method: 'PUT',
headers: {
'X-Push-Server': subscription.endpoint,
// Web Push requires POST requests.
'X-Push-Method': 'POST',
'Encryption-Key': 'keyid=p256dh;dh=' + base64url.encode(pubkey),
Encryption: 'keyid=p256dh;salt=' + base64url.encode(salt),
'Content-Encoding': 'aesgcm128',
'TTL': ttl,
},
body: payload,
return {
data: base64url.encode(payload),
encryption: 'keyid=p256dh;salt=' + base64url.encode(salt),
encryption_key: 'keyid=p256dh;dh=' + base64url.encode(pubkey),
encoding: 'aesgcm128'
};
return fetch('http://mochi.test:8888/tests/dom/push/test/push-server.sjs', options);
}).then(response => {
if (Math.floor(response.status / 100) !== 2) {
throw new Error('Unable to deliver message');
}
return response;
});
}
g.webpush = webpush;
g.webPushEncrypt = webPushEncrypt;
}(this));

View File

@ -6,5 +6,9 @@ support-files =
file_about_newtab_good_signature
file_about_newtab_bad_signature
file_about_newtab_broken_signature
file_about_newtab_sri.html
file_about_newtab_sri_signature
script.js
style.css
[browser_verify_content_about_newtab.js]

View File

@ -43,22 +43,40 @@ const GOOD_ABOUT_STRING = "Just a fully good testpage for Bug 1226928";
const BAD_ABOUT_STRING = "Just a bad testpage for Bug 1226928";
const ABOUT_BLANK = "<head></head><body></body>";
const URI_CLEANUP = BASE + "cleanup=true";
const CLEANUP_DONE = "Done";
const URI_SRI = BASE + "sig=sri&key=good&file=sri&header=good";
const STYLESHEET_WITHOUT_SRI_BLOCKED = "Stylesheet without SRI blocked";
const STYLESHEET_WITH_SRI_BLOCKED = "Stylesheet with SRI blocked";
const STYLESHEET_WITH_SRI_LOADED = "Stylesheet with SRI loaded";
const SCRIPT_WITHOUT_SRI_BLOCKED = "Script without SRI blocked";
const SCRIPT_WITH_SRI_BLOCKED = "Script with SRI blocked";
const SCRIPT_WITH_SRI_LOADED = "Script with SRI loaded";
const TESTS = [
// { newtab (aboutURI) or regular load (url) : url,
// testString : expected string in the loaded page }
{ "aboutURI" : URI_GOOD, "testString" : GOOD_ABOUT_STRING },
{ "aboutURI" : URI_ERROR_HEADER, "testString" : ABOUT_BLANK },
{ "aboutURI" : URI_KEYERROR_HEADER, "testString" : ABOUT_BLANK },
{ "aboutURI" : URI_SIGERROR_HEADER, "testString" : ABOUT_BLANK },
{ "aboutURI" : URI_NO_HEADER, "testString" : ABOUT_BLANK },
{ "aboutURI" : URI_BAD_SIG, "testString" : ABOUT_BLANK },
{ "aboutURI" : URI_BROKEN_SIG, "testString" : ABOUT_BLANK },
{ "aboutURI" : URI_BAD_KEY, "testString" : ABOUT_BLANK },
{ "aboutURI" : URI_BAD_FILE, "testString" : ABOUT_BLANK },
{ "aboutURI" : URI_BAD_ALL, "testString" : ABOUT_BLANK },
{ "url" : URI_BAD_FILE_CACHED, "testString" : BAD_ABOUT_STRING },
{ "aboutURI" : URI_BAD_FILE_CACHED, "testString" : ABOUT_BLANK },
{ "aboutURI" : URI_GOOD, "testString" : GOOD_ABOUT_STRING }
// testStrings : expected strings in the loaded page }
{ "aboutURI" : URI_GOOD, "testStrings" : [GOOD_ABOUT_STRING] },
{ "aboutURI" : URI_ERROR_HEADER, "testStrings" : [ABOUT_BLANK] },
{ "aboutURI" : URI_KEYERROR_HEADER, "testStrings" : [ABOUT_BLANK] },
{ "aboutURI" : URI_SIGERROR_HEADER, "testStrings" : [ABOUT_BLANK] },
{ "aboutURI" : URI_NO_HEADER, "testStrings" : [ABOUT_BLANK] },
{ "aboutURI" : URI_BAD_SIG, "testStrings" : [ABOUT_BLANK] },
{ "aboutURI" : URI_BROKEN_SIG, "testStrings" : [ABOUT_BLANK] },
{ "aboutURI" : URI_BAD_KEY, "testStrings" : [ABOUT_BLANK] },
{ "aboutURI" : URI_BAD_FILE, "testStrings" : [ABOUT_BLANK] },
{ "aboutURI" : URI_BAD_ALL, "testStrings" : [ABOUT_BLANK] },
{ "url" : URI_BAD_FILE_CACHED, "testStrings" : [BAD_ABOUT_STRING] },
{ "aboutURI" : URI_BAD_FILE_CACHED, "testStrings" : [ABOUT_BLANK] },
{ "aboutURI" : URI_GOOD, "testStrings" : [GOOD_ABOUT_STRING] },
{ "aboutURI" : URI_SRI, "testStrings" : [
STYLESHEET_WITHOUT_SRI_BLOCKED,
STYLESHEET_WITH_SRI_LOADED,
SCRIPT_WITHOUT_SRI_BLOCKED,
SCRIPT_WITH_SRI_LOADED,
]},
{ "url" : URI_CLEANUP, "testStrings" : [CLEANUP_DONE] },
];
var browser = null;
@ -74,7 +92,7 @@ function pushPrefs(...aPrefs) {
/*
* run tests with input from TESTS
*/
function doTest(aExpectedString, reload, aUrl, aNewTabPref) {
function doTest(aExpectedStrings, reload, aUrl, aNewTabPref) {
// set about:newtab location for this test if it's a newtab test
if (aNewTabPref) {
aboutNewTabService.newTabURL = aNewTabPref;
@ -115,10 +133,12 @@ function doTest(aExpectedString, reload, aUrl, aNewTabPref) {
"sanity check: default URL for about:newtab should return the new URL");
}
yield ContentTask.spawn(
browser, aExpectedString, function * (aExpectedString) {
ok(content.document.documentElement.innerHTML.includes(aExpectedString),
"Expect the following value in the result\n" + aExpectedString +
"\nand got " + content.document.documentElement.innerHTML);
browser, aExpectedStrings, function * (aExpectedStrings) {
for (let expectedString of aExpectedStrings) {
ok(content.document.documentElement.innerHTML.includes(expectedString),
"Expect the following value in the result\n" + expectedString +
"\nand got " + content.document.documentElement.innerHTML);
}
});
// for good test cases we check if a reload fails if the remote page
@ -140,12 +160,22 @@ function doTest(aExpectedString, reload, aUrl, aNewTabPref) {
browser.reload();
yield BrowserTestUtils.browserLoaded(browser);
aExpectedString = ABOUT_BLANK;
yield ContentTask.spawn(browser, aExpectedString,
function * (aExpectedString) {
ok(content.document.documentElement.innerHTML.includes(aExpectedString),
"Expect the following value in the result\n" + aExpectedString +
"\nand got " + content.document.documentElement.innerHTML);
let expectedStrings = [ABOUT_BLANK];
if (aNewTabPref == URI_SRI) {
expectedStrings = [
STYLESHEET_WITHOUT_SRI_BLOCKED,
STYLESHEET_WITH_SRI_BLOCKED,
SCRIPT_WITHOUT_SRI_BLOCKED,
SCRIPT_WITH_SRI_BLOCKED
];
}
yield ContentTask.spawn(browser, expectedStrings,
function * (expectedStrings) {
for (let expectedString of expectedStrings) {
ok(content.document.documentElement.innerHTML.includes(expectedString),
"Expect the following value in the result\n" + expectedString +
"\nand got " + content.document.documentElement.innerHTML);
}
}
);
@ -172,17 +202,17 @@ add_task(function * test() {
let testCase = TESTS[i];
let url = "", aNewTabPref = "";
let reload = false;
let aExpectedString = testCase.testString;
var aExpectedStrings = testCase.testStrings;
if (testCase.aboutURI) {
url = ABOUT_NEWTAB_URI;
aNewTabPref = testCase.aboutURI;
if (aExpectedString == GOOD_ABOUT_STRING) {
if (aNewTabPref == URI_GOOD || aNewTabPref == URI_SRI) {
reload = true;
}
} else {
url = testCase.url;
}
yield doTest(aExpectedString, reload, url, aNewTabPref);
yield doTest(aExpectedStrings, reload, url, aNewTabPref);
}
});

View File

@ -0,0 +1,36 @@
<!DOCTYPE HTML>
<html>
<!-- https://bugzilla.mozilla.org/show_bug.cgi?id=1235572 -->
<head>
<meta charset="utf-8">
<title>Testpage for bug 1235572</title>
<script>
function loaded(resource) {
document.getElementById("result").innerHTML += resource + " loaded\n";
}
function blocked(resource) {
document.getElementById("result").innerHTML += resource + " blocked\n";
}
</script>
</head>
<body>
Testing script loading without SRI for Bug 1235572<br/>
<div id="result"></div>
<!-- use css1 and css2 to make urls different to avoid the resource being cached-->
<link rel="stylesheet" href="https://example.com/browser/dom/security/test/contentverifier/file_contentserver.sjs?resource=css1"
onload="loaded('Stylesheet without SRI')"
onerror="blocked('Stylesheet without SRI')">
<link rel="stylesheet" href="https://example.com/browser/dom/security/test/contentverifier/file_contentserver.sjs?resource=css2"
integrity="sha384-/6Tvxh7SX39y62qePcvYoi5Vrf0lK8Ix3wJFLCYKI5KNJ5wIlCR8UsFC1OXwmwgd"
onload="loaded('Stylesheet with SRI')"
onerror="blocked('Stylesheet with SRI')">
<script src="https://example.com/browser/dom/security/test/contentverifier/file_contentserver.sjs?resource=script"
onload="loaded('Script without SRI')"
onerror="blocked('Script without SRI')"></script>
<script src="https://example.com/browser/dom/security/test/contentverifier/file_contentserver.sjs?resource=script"
integrity="sha384-zDCkvKOHXk8mM6Nk07oOGXGME17PA4+ydFw+hq0r9kgF6ZDYFWK3fLGPEy7FoOAo"
onload="loaded('Script with SRI')"
onerror="blocked('Script with SRI')"></script>
</body>
</html>

View File

@ -0,0 +1 @@
i5jOnrZWwyNwrTcIjfJ6fUR-8MhhvhtMvQbdrUD7j8aHTybNolv25v9NwJAT6rVU6kgkxmD_st9Kla086CQmzYQdLhKfzgLbTDXz0-1j23fQnyjsP1_4MNIu2xTea11p

View File

@ -14,21 +14,30 @@ goodFile.append(goodFileName);
const goodSignature = path + "file_about_newtab_good_signature";
const goodKeyId = "RemoteNewTab";
const scriptFileName = "script.js";
const cssFileName = "style.css";
const badFile = path + "file_about_newtab_bad.html";
const brokenSignature = path + "file_about_newtab_broken_signature";
const badSignature = path + "file_about_newtab_bad_signature";
const badKeyId = "OldRemoteNewTabKey";
const sriFile = path + "file_about_newtab_sri.html";
const sriSignature = path + "file_about_newtab_sri_signature";
const tempFileNames = [goodFileName, scriptFileName, cssFileName];
// we copy the file to serve as newtab to a temp directory because
// we modify it during tests.
setupTestFile();
setupTestFiles();
function setupTestFile() {
let tempFile = FileUtils.getDir("TmpD", [], true);
tempFile.append(goodFileName);
if (!tempFile.exists()) {
let fileIn = getFileName(goodFileBase, "CurWorkD");
fileIn.copyTo(FileUtils.getDir("TmpD", [], true), "");
function setupTestFiles() {
for (let fileName of tempFileNames) {
let tempFile = FileUtils.getDir("TmpD", [], true);
tempFile.append(fileName);
if (!tempFile.exists()) {
let fileIn = getFileName(path + fileName, "CurWorkD");
fileIn.copyTo(FileUtils.getDir("TmpD", [], true), "");
}
}
}
@ -85,6 +94,14 @@ function truncateFile(aFile, length) {
return "Done";
}
function cleanupTestFiles() {
for (let fileName of tempFileNames) {
let tempFile = FileUtils.getDir("TmpD", [], true);
tempFile.append(fileName);
tempFile.remove(true);
}
}
/*
* handle requests of the following form:
* sig=good&key=good&file=good&header=good&cached=no to serve pages with
@ -102,13 +119,37 @@ function handleRequest(request, response) {
let cached = params.get("cached");
let invalidateFile = params.get("invalidateFile");
let validateFile = params.get("validateFile");
let resource = params.get("resource");
if (params.get("cleanup")) {
cleanupTestFiles();
response.setHeader("Content-Type", "text/html", false);
response.write("Done");
return;
}
if (resource) {
if (resource == "script") {
response.setHeader("Content-Type", "application/javascript", false);
response.write(loadFile(getFileName(scriptFileName, "TmpD")));
} else { // resource == "css1" || resource == "css2"
response.setHeader("Content-Type", "text/css", false);
response.write(loadFile(getFileName(cssFileName, "TmpD")));
}
return;
}
// if invalidateFile is set, this doesn't actually return a newtab page
// but changes the served file to invalidate the signature
// NOTE: make sure to make the file valid again afterwards!
if (invalidateFile) {
let r = "Done";
for (let fileName of tempFileNames) {
if (appendToFile(getFileName(fileName, "TmpD"), "!") != "Done") {
r = "Error";
}
}
response.setHeader("Content-Type", "text/html", false);
let r = appendToFile(goodFile, "!");
response.write(r);
return;
}
@ -116,8 +157,13 @@ function handleRequest(request, response) {
// if validateFile is set, this doesn't actually return a newtab page
// but changes the served file to make the signature valid again
if (validateFile) {
let r = "Done";
for (let fileName of tempFileNames) {
if (truncateFile(getFileName(fileName, "TmpD"), 1) != "Done") {
r = "Error";
}
}
response.setHeader("Content-Type", "text/html", false);
let r = truncateFile(goodFile, 1);
response.write(r);
return;
}
@ -147,9 +193,13 @@ function handleRequest(request, response) {
signature = badSignature;
} else if (signatureType == "broken") {
signature = brokenSignature;
} else if (signatureType == "sri") {
signature = sriSignature;
}
if (fileType == "bad") {
file = getFileName(badFile, "CurWorkD");
} else if (fileType == "sri") {
file = getFileName(sriFile, "CurWorkD");
}
if (headerType == "good") {

View File

@ -0,0 +1 @@
var load=true;

View File

@ -0,0 +1,3 @@
#red-text {
color: red;
}

View File

@ -5,7 +5,7 @@
* In particular, the tests check that default-src and manifest-src directives are
* are respected by the ManifestObtainer.
*/
/*globals Components*/
/*globals Cu, is, ok*/
'use strict';
requestLongerTimeout(10); // e10s tests take time.
const {
@ -15,11 +15,9 @@ const path = '/tests/dom/security/test/csp/';
const testFile = `file=${path}file_web_manifest.html`;
const remoteFile = `file=${path}file_web_manifest_remote.html`;
const httpsManifest = `file=${path}file_web_manifest_https.html`;
const mixedContent = `file=${path}file_web_manifest_mixed_content.html`;
const server = 'file_testserver.sjs';
const defaultURL = `http://example.org${path}${server}`;
const remoteURL = `http://mochi.test:8888`;
const secureURL = `https://example.com${path}${server}`;
const secureURL = `https://example.com:443${path}${server}`;
const tests = [
// CSP block everything, so trying to load a manifest
// will result in a policy violation.
@ -103,7 +101,7 @@ const tests = [
expected: `CSP manifest-src allows self`,
get tabURL() {
let queryParts = [
`manifest-src 'self'`,
`csp=manifest-src 'self'`,
testFile
];
return `${defaultURL}?${queryParts.join('&')}`;
@ -117,7 +115,7 @@ const tests = [
expected: `CSP manifest-src allows http://example.org`,
get tabURL() {
let queryParts = [
`manifest-src http://example.org`,
`csp=manifest-src http://example.org`,
testFile
];
return `${defaultURL}?${queryParts.join('&')}`;
@ -126,42 +124,11 @@ const tests = [
is(manifest.name, 'loaded', this.expected);
}
},
// Check interaction with default-src and another origin,
// CSP allows fetching from example.org, so manifest should load.
{
expected: `CSP manifest-src overrides default-src of elsewhere.com`,
get tabURL() {
let queryParts = [
`default-src: http://elsewhere.com; manifest-src http://example.org`,
testFile
];
return `${defaultURL}?${queryParts.join('&')}`;
},
run(manifest) {
is(manifest.name, 'loaded', this.expected);
}
},
// Check interaction with default-src none,
// CSP allows fetching manifest from example.org, so manifest should load.
{
expected: `CSP manifest-src overrides default-src`,
get tabURL() {
let queryParts = [
`default-src: 'none'; manifest-src 'self'`,
testFile
];
return `${defaultURL}?${queryParts.join('&')}`;
},
run(manifest) {
is(manifest.name, 'loaded', this.expected);
}
},
// CSP allows fetching from mochi.test:8888, which has a
// CORS header set to '*'. So the manifest should load.
{
expected: `CSP manifest-src allows mochi.test:8888`,
get tabURL() {
let queryParts = [
`cors=*`,
`csp=default-src *; manifest-src http://mochi.test:8888`,
remoteFile
];
@ -202,63 +169,81 @@ const tests = [
run(topic) {
is(topic, 'csp-on-violate-policy', this.expected);
}
}
},
// CSP allows fetching over TLS from example.org, so manifest should load.
{
expected: `CSP manifest-src allows example.com over TLS`,
get tabURL() {
let queryParts = [
'cors=*',
'csp=manifest-src https://example.com:443',
httpsManifest
];
// secureURL loads https://example.com:443
// and gets manifest from https://example.org:443
return `${secureURL}?${queryParts.join('&')}`;
},
run(manifest) {
is(manifest.name, 'loaded', this.expected);
}
},
];
//jscs:disable
add_task(function* () {
//jscs:enable
for (let test of tests) {
let tabOptions = {
gBrowser: gBrowser,
url: test.tabURL,
};
yield BrowserTestUtils.withNewTab(
tabOptions,
browser => testObtainingManifest(browser, test)
var testPromises = tests.map(
(test) => ([test, {gBrowser, url: test.tabURL, skipAnimation: true}])
).map(
([test, tabOptions]) => BrowserTestUtils.withNewTab(tabOptions, (browser) => testObtainingManifest(browser, test))
);
}
function* testObtainingManifest(aBrowser, aTest) {
const observer = (/blocks/.test(aTest.expected)) ? new NetworkObserver(aTest) : null;
let manifest;
// Expect an exception (from promise rejection) if there a content policy
// that is violated.
try {
manifest = yield ManifestObtainer.browserObtainManifest(aBrowser);
} catch (e) {
const msg = `Expected promise rejection obtaining.`;
ok(/blocked the loading of a resource/.test(e.message), msg);
if (observer) {
yield observer.finished;
}
return;
}
// otherwise, we test manifest's content.
if (manifest) {
aTest.run(manifest);
}
}
yield Promise.all(testPromises);
});
// Helper object used to observe policy violations. It waits 10 seconds
function* testObtainingManifest(aBrowser, aTest) {
const expectsBlocked = aTest.expected.includes('block');
const observer = (expectsBlocked) ? createNetObserver(aTest) : null;
// Expect an exception (from promise rejection) if there a content policy
// that is violated.
try {
const manifest = yield ManifestObtainer.browserObtainManifest(aBrowser);
aTest.run(manifest);
} catch (e) {
const wasBlocked = e.message.includes('blocked the loading of a resource');
ok(wasBlocked,`Expected promise rejection obtaining ${aTest.tabURL}: ${e.message}`);
if (observer) {
yield observer.untilFinished;
return;
}
throw e;
}
}
// Helper object used to observe policy violations. It waits 1 seconds
// for a response, and then times out causing its associated test to fail.
function NetworkObserver(test) {
function createNetObserver(test) {
let finishedTest;
let success = false;
this.finished = new Promise((resolver) => {
const finished = new Promise((resolver) => {
finishedTest = resolver;
})
this.observe = function observer(subject, topic) {
SpecialPowers.removeObserver(this, 'csp-on-violate-policy');
test.run(topic);
finishedTest();
success = true;
};
SpecialPowers.addObserver(this, 'csp-on-violate-policy', false);
setTimeout(() => {
});
const timeoutId = setTimeout(() => {
if (!success) {
test.run('This test timed out.');
finishedTest();
}
}, 1000);
var observer = {
get untilFinished(){
return finished;
},
observe(subject, topic) {
SpecialPowers.removeObserver(observer, 'csp-on-violate-policy');
test.run(topic);
finishedTest();
clearTimeout(timeoutId);
success = true;
},
};
SpecialPowers.addObserver(observer, 'csp-on-violate-policy', false);
return observer;
}

View File

@ -75,7 +75,7 @@ TelephonyDialCallback::NotifyDialMMISuccess(const nsAString& aStatusMessage)
JSContext* cx = jsapi.cx();
MozMMIResult result;
RootedDictionary<MozMMIResult> result(cx);
result.mSuccess = true;
result.mServiceCode.Assign(mServiceCode);
result.mStatusMessage.Assign(aStatusMessage);
@ -94,7 +94,7 @@ TelephonyDialCallback::NotifyDialMMISuccessWithInteger(const nsAString& aStatusM
JSContext* cx = jsapi.cx();
MozMMIResult result;
RootedDictionary<MozMMIResult> result(cx);
result.mSuccess = true;
result.mServiceCode.Assign(mServiceCode);
result.mStatusMessage.Assign(aStatusMessage);
@ -217,7 +217,7 @@ TelephonyDialCallback::NotifyDialMMIError(const nsAString& aError)
JSContext* cx = jsapi.cx();
MozMMIResult result;
RootedDictionary<MozMMIResult> result(cx);
result.mSuccess = false;
result.mServiceCode.Assign(mServiceCode);
result.mStatusMessage.Assign(aError);
@ -236,7 +236,7 @@ TelephonyDialCallback::NotifyDialMMIErrorWithInfo(const nsAString& aError,
JSContext* cx = jsapi.cx();
MozMMIResult result;
RootedDictionary<MozMMIResult> result(cx);
result.mSuccess = false;
result.mServiceCode.Assign(mServiceCode);
result.mStatusMessage.Assign(aError);

View File

@ -298,7 +298,9 @@ interface CanvasPathMethods {
[Throws, LenientFloat]
void arc(double x, double y, double radius, double startAngle, double endAngle, optional boolean anticlockwise = false);
// NOT IMPLEMENTED [LenientFloat] void ellipse(double x, double y, double radiusX, double radiusY, double rotation, double startAngle, double endAngle, boolean anticlockwise);
[Throws, LenientFloat]
void ellipse(double x, double y, double radiusX, double radiusY, double rotation, double startAngle, double endAngle, optional boolean anticlockwise = false);
};
interface CanvasGradient {

View File

@ -46,14 +46,22 @@ interface KeyframeEffectReadOnly : AnimationEffectReadOnly {
};
// Non-standard extensions
dictionary AnimationPropertyState {
DOMString property;
boolean runningOnCompositor;
DOMString? warning;
dictionary AnimationPropertyValueDetails {
required double offset;
required DOMString value;
DOMString easing;
required CompositeOperation composite;
};
dictionary AnimationPropertyDetails {
required DOMString property;
required boolean runningOnCompositor;
DOMString warning;
required sequence<AnimationPropertyValueDetails> values;
};
partial interface KeyframeEffectReadOnly {
[ChromeOnly] sequence<AnimationPropertyState> getPropertyState();
[ChromeOnly, Throws] sequence<AnimationPropertyDetails> getProperties();
};
[Func="nsDocument::IsWebAnimationsEnabled",

View File

@ -1934,11 +1934,8 @@ RuntimeService::Shutdown()
{
MutexAutoUnlock unlock(mMutex);
AutoSafeJSContext cx;
JSAutoRequest ar(cx);
for (uint32_t index = 0; index < workers.Length(); index++) {
if (!workers[index]->Kill(cx)) {
if (!workers[index]->Kill()) {
NS_WARNING("Failed to cancel worker!");
}
}

View File

@ -9,6 +9,7 @@
#include "nsIChannel.h"
#include "nsIContentPolicy.h"
#include "nsIContentSecurityPolicy.h"
#include "nsIDocShell.h"
#include "nsIHttpChannel.h"
#include "nsIHttpChannelInternal.h"
#include "nsIInputStreamPump.h"
@ -893,6 +894,28 @@ private:
nsLoadFlags loadFlags = nsIRequest::LOAD_NORMAL;
// Get the top-level worker.
WorkerPrivate* topWorkerPrivate = mWorkerPrivate;
WorkerPrivate* parent = topWorkerPrivate->GetParent();
while (parent) {
topWorkerPrivate = parent;
parent = topWorkerPrivate->GetParent();
}
// If the top-level worker is a dedicated worker and has a window, and the
// window has a docshell, the caching behavior of this worker should match
// that of that docshell.
if (topWorkerPrivate->IsDedicatedWorker()) {
nsCOMPtr<nsPIDOMWindowInner> window = topWorkerPrivate->GetWindow();
if (window) {
nsCOMPtr<nsIDocShell> docShell = do_GetInterface(window);
if (docShell) {
nsresult rv = docShell->GetDefaultLoadFlags(&loadFlags);
NS_ENSURE_SUCCESS(rv, rv);
}
}
}
// If we are loading a script for a ServiceWorker then we must not
// try to intercept it. If the interception matches the current
// ServiceWorker's scope then we could deadlock the load.

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