Merge m-c to inbound. a=merge

This commit is contained in:
Ryan VanderMeulen 2016-12-01 09:33:46 -05:00
commit 9bd4ab78e6
34 changed files with 371 additions and 185 deletions

View File

@ -24,6 +24,9 @@ const L10N =
const DURATION_RESOLUTION = 4;
// MIN_PROGRESS_THRESHOLD shoud be between more than 0 to 1.
const MIN_PROGRESS_THRESHOLD = 0.1;
// BOUND_EXCLUDING_TIME should be less than 1ms and is used to exclude start
// and end bounds when dividing duration in createPathSegments.
const BOUND_EXCLUDING_TIME = 0.001;
// Show max 10 iterations for infinite animations
// to give users a clue that the animation does repeat.
const MAX_INFINITE_ANIMATIONS_ITERATIONS = 10;
@ -676,9 +679,10 @@ function createPathSegments(startTime, endTime, minSegmentDuration,
// in the graph.
if (Math.abs(currentSegment.y - previousSegment.y) > minProgressThreshold) {
// Divide the current interval (excluding start and end bounds
// by adding/subtracting 1ms).
// by adding/subtracting BOUND_EXCLUDING_TIME).
pathSegments = pathSegments.concat(
createPathSegments(previousSegment.x + 1, currentSegment.x - 1,
createPathSegments(previousSegment.x + BOUND_EXCLUDING_TIME,
currentSegment.x - BOUND_EXCLUDING_TIME,
minSegmentDuration, minProgressThreshold,
segmentHelper));
}

View File

@ -10,6 +10,7 @@ support-files =
doc_negative_animation.html
doc_pseudo_elements.html
doc_script_animation.html
doc_short_duration_animation.html
doc_simple_animation.html
doc_multiple_animation_types.html
doc_timing_combination_animation.html
@ -58,6 +59,7 @@ skip-if = os == "linux" && !debug # Bug 1227792
[browser_animation_timeline_scrubber_movable.js]
[browser_animation_timeline_scrubber_moves.js]
[browser_animation_timeline_setCurrentTime.js]
[browser_animation_timeline_short_duration.js]
[browser_animation_timeline_shows_delay.js]
[browser_animation_timeline_shows_endDelay.js]
[browser_animation_timeline_shows_iterations.js]

View File

@ -0,0 +1,97 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
requestLongerTimeout(2);
// Test short duration (e.g. 1ms) animation.
add_task(function* () {
yield addTab(URL_ROOT + "doc_short_duration_animation.html");
const { panel, inspector } = yield openAnimationInspector();
const timelineComponent = panel.animationsTimelineComponent;
info("Check the listed time blocks");
for (let i = 0; i < timelineComponent.timeBlocks.length; i++) {
info(`Check the time block ${i}`);
const {containerEl, animation: {state}} = timelineComponent.timeBlocks[i];
checkSummaryGraph(containerEl, state);
}
info("Check the time block one by one");
info("Check #onetime");
yield selectNodeAndWaitForAnimations("#onetime", inspector);
let timeBlock = timelineComponent.timeBlocks[0];
let containerEl = timeBlock.containerEl;
let state = timeBlock.animation.state;
checkSummaryGraph(containerEl, state, true);
info("Check #infinite");
yield selectNodeAndWaitForAnimations("#infinite", inspector);
timeBlock = timelineComponent.timeBlocks[0];
containerEl = timeBlock.containerEl;
state = timeBlock.animation.state;
checkSummaryGraph(containerEl, state, true);
});
function checkSummaryGraph(el, state, isDetail) {
info("Check the coordinates of summary graph");
const pathEls = el.querySelectorAll(".iteration-path");
let expectedIterationCount = 0;
if (isDetail) {
expectedIterationCount = state.iterationCount ? state.iterationCount : 1;
} else {
expectedIterationCount = state.iterationCount ? state.iterationCount : 2;
}
is(pathEls.length, expectedIterationCount,
`The count of path shoud be ${ expectedIterationCount }`);
pathEls.forEach((pathEl, index) => {
const startX = index * state.duration;
const endX = startX + state.duration;
const pathSegList = pathEl.pathSegList;
const firstPathSeg = pathSegList.getItem(0);
is(firstPathSeg.x, startX,
`The x of first segment should be ${ startX }`);
is(firstPathSeg.y, 0, "The y of first segment should be 0");
// The easing of test animation is 'linear'.
// Therefore, the y of second path segment will be 0.
const secondPathSeg = pathSegList.getItem(1);
is(secondPathSeg.x, startX,
`The x of second segment should be ${ startX }`);
is(secondPathSeg.y, 0, "The y of second segment should be 0");
const thirdLastPathSeg = pathSegList.getItem(pathSegList.numberOfItems - 4);
approximate(thirdLastPathSeg.x, endX - 0.001, 0.005,
`The x of third last segment should be approximately ${ endX - 0.001 }`);
approximate(thirdLastPathSeg.y, 0.999, 0.005,
" The y of third last segment should be approximately "
+ thirdLastPathSeg.x);
// The test animation is not 'forwards' fill-mode.
// Therefore, the y of second last path segment will be 0.
const secondLastPathSeg =
pathSegList.getItem(pathSegList.numberOfItems - 3);
is(secondLastPathSeg.x, endX,
`The x of second last segment should be ${ endX }`);
is(secondLastPathSeg.y, 0, "The y of second last segment should be 0");
const lastPathSeg = pathSegList.getItem(pathSegList.numberOfItems - 2);
is(lastPathSeg.x, endX, `The x of last segment should be ${ endX }`);
is(lastPathSeg.y, 0, "The y of last segment should be 0");
const closePathSeg = pathSegList.getItem(pathSegList.numberOfItems - 1);
is(closePathSeg.pathSegType, closePathSeg.PATHSEG_CLOSEPATH,
`The actual last segment should be close path`);
});
}
function approximate(value, expected, permissibleRange, message) {
const min = expected - permissibleRange;
const max = expected + permissibleRange;
ok(min <= value && value <= max, message);
}

View File

@ -0,0 +1,31 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<style>
div {
display: inline-block;
width: 100px;
height: 100px;
background-color: lime;
}
</style>
</head>
<body>
<div id="onetime"></div>
<div id="twotimes"></div>
<div id="infinite"></div>
<script>
"use strict";
let target = document.querySelector("#onetime");
target.animate({ opacity: [0, 1] },
{ duration: 1, iterations: 1 }).pause();
target = document.querySelector("#twotimes");
target.animate({ opacity: [0, 1] },
{ duration: 1, iterations: 2 }).pause();
target = document.querySelector("#infinite");
target.animate({ opacity: [0, 1] },
{ duration: 1, iterations: Infinity }).pause();
</script>
</body>
</html>

View File

@ -673,15 +673,8 @@ public:
}
bool
IsAllowedToPlay()
IsPlaybackBlocked()
{
// The media element has already been paused or blocked, so it can't start
// playback again by script or user's intend until resuming by audio channel.
if (mSuspended == nsISuspendedTypes::SUSPENDED_PAUSE ||
mSuspended == nsISuspendedTypes::SUSPENDED_BLOCK) {
return false;
}
// If the tab hasn't been activated yet, the media element in that tab can't
// be playback now until the tab goes to foreground first time or user clicks
// the unblocking tab icon.
@ -689,10 +682,10 @@ public:
// Even we haven't start playing yet, we still need to notify the audio
// channe system because we need to receive the resume notification later.
UpdateAudioChannelPlayingState(true /* force to start */);
return false;
return true;
}
return true;
return false;
}
float
@ -953,14 +946,14 @@ private:
// It's used when we temporary lost platform audio focus. MediaElement can
// only be resumed when we gain the audio focus again.
// - SUSPENDED_PAUSE_DISPOSABLE
// It's used when user press the pause botton on the remote media-control.
// MediaElement can be resumed by reomte media-control or via play().
// It's used when user press the pause button on the remote media-control.
// MediaElement can be resumed by remote media-control or via play().
// - SUSPENDED_BLOCK
// It's used to reduce the power comsuption, we won't play the auto-play
// It's used to reduce the power consumption, we won't play the auto-play
// audio/video in the page we have never visited before. MediaElement would
// be resumed when the page is active. See bug647429 for more details.
// - SUSPENDED_STOP_DISPOSABLE
// When we permanently lost platform audio focus, we shuold stop playing
// When we permanently lost platform audio focus, we should stop playing
// and stop the audio channel agent. MediaElement can only be restarted by
// play().
SuspendTypes mSuspended;
@ -3568,7 +3561,8 @@ HTMLMediaElement::NotifyXPCOMShutdown()
void
HTMLMediaElement::Play(ErrorResult& aRv)
{
if (!IsAllowedToPlay()) {
if (mAudioChannelWrapper && mAudioChannelWrapper->IsPlaybackBlocked()) {
// NOTE: for promise-based-play, will return a pending promise here.
MaybeDoLoad();
return;
}
@ -3584,6 +3578,11 @@ HTMLMediaElement::Play(ErrorResult& aRv)
nsresult
HTMLMediaElement::PlayInternal()
{
if (!IsAllowedToPlay()) {
// NOTE: for promise-based-play, will return a rejected promise here.
return NS_OK;
}
// Play was not blocked so assume user interacted with the element.
mHasUserInteraction = true;
@ -3657,7 +3656,8 @@ HTMLMediaElement::MaybeDoLoad()
NS_IMETHODIMP HTMLMediaElement::Play()
{
if (!IsAllowedToPlay()) {
if (mAudioChannelWrapper && mAudioChannelWrapper->IsPlaybackBlocked()) {
// NOTE: for promise-based-play, will return a pending promise here.
MaybeDoLoad();
return NS_OK;
}
@ -5489,8 +5489,13 @@ bool HTMLMediaElement::CanActivateAutoplay()
return false;
}
if (mAudioChannelWrapper && !mAudioChannelWrapper->IsAllowedToPlay()) {
return false;
if (mAudioChannelWrapper) {
// Note: SUSPENDED_PAUSE and SUSPENDED_BLOCK will be merged into one single state.
if (mAudioChannelWrapper->GetSuspendType() == nsISuspendedTypes::SUSPENDED_PAUSE ||
mAudioChannelWrapper->GetSuspendType() == nsISuspendedTypes::SUSPENDED_BLOCK ||
mAudioChannelWrapper->IsPlaybackBlocked()) {
return false;
}
}
bool hasData =
@ -6315,7 +6320,13 @@ HTMLMediaElement::IsAllowedToPlay()
// Check our custom playback policy.
if (mAudioChannelWrapper) {
return mAudioChannelWrapper->IsAllowedToPlay();
// Note: SUSPENDED_PAUSE and SUSPENDED_BLOCK will be merged into one single state.
if (mAudioChannelWrapper->GetSuspendType() == nsISuspendedTypes::SUSPENDED_PAUSE ||
mAudioChannelWrapper->GetSuspendType() == nsISuspendedTypes::SUSPENDED_BLOCK) {
return false;
}
return true;
}
// If the mAudioChannelWrapper doesn't exist that means the CC happened.

View File

@ -8,7 +8,6 @@ Cu.import("resource://gre/modules/Services.jsm");
const {PushDB, PushService, PushServiceHttp2} = serviceExports;
var prefs;
var tlsProfile;
var serverPort = -1;
@ -21,12 +20,9 @@ function run_test() {
});
prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
tlsProfile = prefs.getBoolPref("network.http.spdy.enforce-tls-profile");
// Set to allow the cert presented by our H2 server
var oldPref = prefs.getIntPref("network.http.speculative-parallel-limit");
prefs.setIntPref("network.http.speculative-parallel-limit", 0);
prefs.setBoolPref("network.http.spdy.enforce-tls-profile", false);
prefs.setBoolPref("dom.push.enabled", true);
prefs.setBoolPref("dom.push.connection.enabled", true);
@ -183,7 +179,3 @@ add_task(function* test_pushNotifications() {
yield notifyPromise;
});
add_task(function* test_complete() {
prefs.setBoolPref("network.http.spdy.enforce-tls-profile", tlsProfile);
});

View File

@ -8,7 +8,6 @@ Cu.import("resource://gre/modules/Services.jsm");
const {PushDB, PushService, PushServiceHttp2} = serviceExports;
var prefs;
var tlsProfile;
var serverURL;
var serverPort = -1;
@ -19,8 +18,6 @@ function run_test() {
do_get_profile();
prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
tlsProfile = prefs.getBoolPref("network.http.spdy.enforce-tls-profile");
serverURL = "https://localhost:" + serverPort;
run_next_test();
@ -57,7 +54,6 @@ add_task(function* test_TLS() {
// Set to allow the cert presented by our H2 server
var oldPref = prefs.getIntPref("network.http.speculative-parallel-limit");
prefs.setIntPref("network.http.speculative-parallel-limit", 0);
prefs.setBoolPref("network.http.spdy.enforce-tls-profile", false);
addCertOverride("localhost", serverPort,
Ci.nsICertOverrideService.ERROR_UNTRUSTED |
@ -195,7 +191,3 @@ add_task(function* test_pushSubscriptionNot2xxCode() {
let record = yield db.getAllKeyIDs();
ok(record.length === 0, 'Should not store records when respons code is not 201.');
});
add_task(function* test_complete() {
prefs.setBoolPref("network.http.spdy.enforce-tls-profile", tlsProfile);
});

View File

@ -8,7 +8,6 @@ Cu.import("resource://gre/modules/Services.jsm");
const {PushDB, PushService, PushServiceHttp2} = serviceExports;
var prefs;
var tlsProfile;
var serverURL;
var serverPort = -1;
var pushEnabled;
@ -21,14 +20,12 @@ function run_test() {
do_get_profile();
prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
tlsProfile = prefs.getBoolPref("network.http.spdy.enforce-tls-profile");
pushEnabled = prefs.getBoolPref("dom.push.enabled");
pushConnectionEnabled = prefs.getBoolPref("dom.push.connection.enabled");
// Set to allow the cert presented by our H2 server
var oldPref = prefs.getIntPref("network.http.speculative-parallel-limit");
prefs.setIntPref("network.http.speculative-parallel-limit", 0);
prefs.setBoolPref("network.http.spdy.enforce-tls-profile", false);
prefs.setBoolPref("dom.push.enabled", true);
prefs.setBoolPref("dom.push.connection.enabled", true);
@ -122,7 +119,6 @@ add_task(function* test_pushSubscriptionMissingLink2() {
});
add_task(function* test_complete() {
prefs.setBoolPref("network.http.spdy.enforce-tls-profile", tlsProfile);
prefs.setBoolPref("dom.push.enabled", pushEnabled);
prefs.setBoolPref("dom.push.connection.enabled", pushConnectionEnabled);
});

View File

@ -8,7 +8,6 @@ Cu.import("resource://gre/modules/Services.jsm");
const {PushDB, PushService, PushServiceHttp2} = serviceExports;
var prefs;
var tlsProfile;
var pushEnabled;
var pushConnectionEnabled;
@ -20,14 +19,12 @@ function run_test() {
do_get_profile();
prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
tlsProfile = prefs.getBoolPref("network.http.spdy.enforce-tls-profile");
pushEnabled = prefs.getBoolPref("dom.push.enabled");
pushConnectionEnabled = prefs.getBoolPref("dom.push.connection.enabled");
// Set to allow the cert presented by our H2 server
var oldPref = prefs.getIntPref("network.http.speculative-parallel-limit");
prefs.setIntPref("network.http.speculative-parallel-limit", 0);
prefs.setBoolPref("network.http.spdy.enforce-tls-profile", false);
prefs.setBoolPref("dom.push.enabled", true);
prefs.setBoolPref("dom.push.connection.enabled", true);
@ -75,7 +72,6 @@ add_task(function* test_pushUnsubscriptionSuccess() {
});
add_task(function* test_complete() {
prefs.setBoolPref("network.http.spdy.enforce-tls-profile", tlsProfile);
prefs.setBoolPref("dom.push.enabled", pushEnabled);
prefs.setBoolPref("dom.push.connection.enabled", pushConnectionEnabled);
});

View File

@ -12,7 +12,6 @@
#include "nsCOMPtr.h"
#include "nsIObserverService.h"
#include "nsIThreadPool.h"
#include "nsPrintfCString.h"
#include "nsThreadManager.h"
#include "nsThreadUtils.h"
#include "nsXPCOMCIDInternal.h"
@ -162,7 +161,6 @@ class DecodePoolWorker : public Runnable
public:
explicit DecodePoolWorker(DecodePoolImpl* aImpl)
: mImpl(aImpl)
, mSerialNumber(++sNextSerialNumber)
{ }
NS_IMETHOD Run() override
@ -179,10 +177,8 @@ public:
nsThreadManager::get().GetCurrentThread(getter_AddRefs(thisThread));
#ifdef MOZ_ENABLE_PROFILER_SPS
{
const nsPrintfCString threadName("ImgDecoder#%lu", mSerialNumber);
profiler_register_thread(threadName.get(), &stackBaseGuess);
}
// InitCurrentThread() has assigned the thread name.
profiler_register_thread(PR_GetThreadName(PR_GetCurrentThread()), &stackBaseGuess);
#endif // MOZ_ENABLE_PROFILER_SPS
do {
@ -211,14 +207,9 @@ public:
}
private:
static uint32_t sNextSerialNumber;
RefPtr<DecodePoolImpl> mImpl;
uint32_t mSerialNumber;
};
uint32_t DecodePoolWorker::sNextSerialNumber = 0;
/* static */ void
DecodePool::Initialize()
{

View File

@ -6,6 +6,7 @@
/* Utility code for performing CSS Box Alignment */
#include "CSSAlignUtils.h"
#include "ReflowInput.h"
namespace mozilla {

View File

@ -12,6 +12,8 @@
namespace mozilla {
struct ReflowInput;
class CSSAlignUtils {
public:
/**

View File

@ -14,7 +14,7 @@
*/
class MathMLTextRunFactory : public nsTransformingTextRunFactory {
public:
MathMLTextRunFactory(UniquePtr<nsTransformingTextRunFactory> aInnerTransformingTextRunFactory,
MathMLTextRunFactory(mozilla::UniquePtr<nsTransformingTextRunFactory> aInnerTransformingTextRunFactory,
uint32_t aFlags, uint8_t aSSTYScriptLevel,
float aFontInflation)
: mInnerTransformingTextRunFactory(Move(aInnerTransformingTextRunFactory)),
@ -33,7 +33,7 @@ public:
};
protected:
UniquePtr<nsTransformingTextRunFactory> mInnerTransformingTextRunFactory;
mozilla::UniquePtr<nsTransformingTextRunFactory> mInnerTransformingTextRunFactory;
uint32_t mFlags;
float mFontInflation;
uint8_t mSSTYScriptLevel;

View File

@ -36,6 +36,8 @@ nsOverflowAreas::SetAllTo(const nsRect& aRect)
}
}
namespace mozilla {
ReflowOutput::ReflowOutput(const ReflowInput& aState,
uint32_t aFlags)
: mISize(0)
@ -65,3 +67,5 @@ ReflowOutput::UnionOverflowAreasWithDesiredBounds()
o.UnionRect(o, rect);
}
}
} // namespace mozilla

View File

@ -7,9 +7,10 @@
#ifndef mozilla_RubyUtils_h_
#define mozilla_RubyUtils_h_
#include "nsTArray.h"
#include "nsGkAtoms.h"
#include "nsCSSAnonBoxes.h"
#include "nsGkAtoms.h"
#include "nsIFrame.h"
#include "nsTArray.h"
#define RTC_ARRAY_SIZE 1

View File

@ -6,6 +6,9 @@
#ifndef mozilla_layout_ScrollSnap_h_
#define mozilla_layout_ScrollSnap_h_
#include "mozilla/Maybe.h"
#include "nsIScrollableFrame.h"
namespace mozilla {
namespace layers {
@ -27,7 +30,7 @@ struct ScrollSnapUtils {
* not to touch main-thread-only data structures without
* appropriate locking.
*/
static Maybe<nsPoint> GetSnapPointForDestination(
static mozilla::Maybe<nsPoint> GetSnapPointForDestination(
const layers::ScrollSnapInfo& aSnapInfo,
nsIScrollableFrame::ScrollUnit aUnit,
const nsSize& aScrollPortSize,

View File

@ -17,6 +17,7 @@
#include "nsAbsoluteContainingBlock.h"
#include "GeckoProfiler.h"
#include "nsIMozBrowserFrame.h"
#include "nsPlaceholderFrame.h"
using namespace mozilla;
typedef nsAbsoluteContainingBlock::AbsPosReflowFlags AbsPosReflowFlags;

View File

@ -10,6 +10,8 @@
#include "mozilla/dom/HTMLDetailsElement.h"
#include "mozilla/dom/HTMLSummaryElement.h"
#include "nsAbsoluteContainingBlock.h"
#include "nsAttrValue.h"
#include "nsAttrValueInlines.h"
#include "nsIDocument.h"
#include "nsPresContext.h"
#include "nsStyleContext.h"
@ -29,6 +31,7 @@
#include "nsBoxLayoutState.h"
#include "nsCSSFrameConstructor.h"
#include "nsBlockFrame.h"
#include "nsBulletFrame.h"
#include "nsPlaceholderFrame.h"
#include "mozilla/AutoRestore.h"
#include "nsIFrameInlines.h"

View File

@ -9,8 +9,7 @@
#include "nsIPresShell.h"
#include "nsSimplePageSequenceFrame.h"
using mozilla::LogicalSize;
using mozilla::WritingMode;
using namespace mozilla;
nsPageContentFrame*
NS_NewPageContentFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)

View File

@ -22,6 +22,7 @@
#include "RubyUtils.h"
using namespace mozilla;
using namespace mozilla::gfx;
//----------------------------------------------------------------------

View File

@ -13,6 +13,8 @@
#include "nsUnicharUtils.h"
#include <algorithm>
using namespace mozilla;
static bool IsDiscardable(char16_t ch, uint32_t* aFlags)
{
// Unlike IS_DISCARDABLE, we don't discard \r. \r will be ignored by gfxTextRun

View File

@ -20,6 +20,7 @@
#include "IrishCasing.h"
using namespace mozilla;
using namespace mozilla::gfx;
// Unicode characters needing special casing treatment in tr/az languages
#define LATIN_CAPITAL_LETTER_I_WITH_DOT_ABOVE 0x0130

View File

@ -78,7 +78,7 @@ public:
// via the fontgroup.
// Takes ownership of aInnerTransformTextRunFactory
explicit nsCaseTransformTextRunFactory(UniquePtr<nsTransformingTextRunFactory> aInnerTransformingTextRunFactory,
explicit nsCaseTransformTextRunFactory(mozilla::UniquePtr<nsTransformingTextRunFactory> aInnerTransformingTextRunFactory,
bool aAllUppercase = false)
: mInnerTransformingTextRunFactory(Move(aInnerTransformingTextRunFactory)),
mAllUppercase(aAllUppercase) {}

View File

@ -110,40 +110,33 @@ nsConditionalResetStyleData::GetConditionalStyleData(nsStyleStructID aSID,
return nullptr;
}
// Creates an imgRequestProxy based on the specified value in
// aValue and calls aCallback with it. If the nsPresContext
// is static (e.g. for printing), then a static request (i.e.
// showing the first frame, without animation) will be created.
// (The expectation is then that aCallback will set the resulting
// imgRequestProxy in a style struct somewhere.)
static void
SetImageRequest(std::function<void(imgRequestProxy*)> aCallback,
nsPresContext* aPresContext,
const nsCSSValue& aValue)
// Creates an imgRequestProxy based on the specified value in aValue and
// returns it. If the nsPresContext is static (e.g. for printing), then
// a static request (i.e. showing the first frame, without animation)
// will be created.
static already_AddRefed<imgRequestProxy>
CreateImageRequest(nsPresContext* aPresContext, const nsCSSValue& aValue)
{
RefPtr<imgRequestProxy> req =
aValue.GetPossiblyStaticImageValue(aPresContext->Document(),
aPresContext);
aCallback(req);
return req.forget();
}
static void
SetStyleImageRequest(std::function<void(nsStyleImageRequest*)> aCallback,
nsPresContext* aPresContext,
const nsCSSValue& aValue,
nsStyleImageRequest::Mode aModeFlags =
nsStyleImageRequest::Mode::Track)
static already_AddRefed<nsStyleImageRequest>
CreateStyleImageRequest(nsPresContext* aPresContext, const nsCSSValue& aValue,
nsStyleImageRequest::Mode aModeFlags =
nsStyleImageRequest::Mode::Track)
{
SetImageRequest([&](imgRequestProxy* aProxy) {
css::ImageValue* imageValue = aValue.GetImageStructValue();
ImageTracker* imageTracker =
(aModeFlags & nsStyleImageRequest::Mode::Track)
? aPresContext->Document()->ImageTracker()
: nullptr;
RefPtr<nsStyleImageRequest> request =
new nsStyleImageRequest(aModeFlags, aProxy, imageValue, imageTracker);
aCallback(request);
}, aPresContext, aValue);
css::ImageValue* imageValue = aValue.GetImageStructValue();
ImageTracker* imageTracker =
(aModeFlags & nsStyleImageRequest::Mode::Track)
? aPresContext->Document()->ImageTracker()
: nullptr;
RefPtr<imgRequestProxy> proxy = CreateImageRequest(aPresContext, aValue);
RefPtr<nsStyleImageRequest> request =
new nsStyleImageRequest(aModeFlags, proxy, imageValue, imageTracker);
return request.forget();
}
template<typename ReferenceBox>
@ -1317,9 +1310,8 @@ static void SetStyleImageToImageRect(nsStyleContext* aStyleContext,
// <uri>
if (arr->Item(1).GetUnit() == eCSSUnit_Image) {
SetStyleImageRequest([&](nsStyleImageRequest* req) {
aResult.SetImageRequest(do_AddRef(req));
}, aStyleContext->PresContext(), arr->Item(1));
nsPresContext* pc = aStyleContext->PresContext();
aResult.SetImageRequest(CreateStyleImageRequest(pc, arr->Item(1)));
} else {
NS_WARNING("nsCSSValue::Image::Image() failed?");
}
@ -1351,11 +1343,10 @@ static void SetStyleImage(nsStyleContext* aStyleContext,
aResult.SetNull();
nsPresContext* presContext = aStyleContext->PresContext();
switch (aValue.GetUnit()) {
case eCSSUnit_Image:
SetStyleImageRequest([&](nsStyleImageRequest* req) {
aResult.SetImageRequest(do_AddRef(req));
}, aStyleContext->PresContext(), aValue);
aResult.SetImageRequest(CreateStyleImageRequest(presContext, aValue));
break;
case eCSSUnit_Function:
if (aValue.EqualsFunction(eCSSKeyword__moz_image_rect)) {
@ -1367,8 +1358,7 @@ static void SetStyleImage(nsStyleContext* aStyleContext,
case eCSSUnit_Gradient:
{
nsStyleGradient* gradient = new nsStyleGradient();
SetGradient(aValue, aStyleContext->PresContext(), aStyleContext,
*gradient, aConditions);
SetGradient(aValue, presContext, aStyleContext, *gradient, aConditions);
aResult.SetGradientData(gradient);
break;
}
@ -1400,7 +1390,7 @@ static void SetStyleImage(nsStyleContext* aStyleContext,
// Check #3.
bool isEqualExceptRef = false;
if (!isLocalRef) {
nsIDocument* currentDoc = aStyleContext->PresContext()->Document();
nsIDocument* currentDoc = presContext->Document();
nsIURI* docURI = currentDoc->GetDocumentURI();
nsIURI* imageURI = aValue.GetURLValue();
imageURI->EqualsExceptRef(docURI, &isEqualExceptRef);
@ -5172,16 +5162,15 @@ nsRuleNode::ComputeUserInterfaceData(void* aStartStruct,
const nsCSSValueList* list = cursorValue->GetListValue();
for ( ; list->mValue.GetUnit() == eCSSUnit_Array; list = list->mNext) {
nsCSSValue::Array* arr = list->mValue.GetArrayValue();
SetStyleImageRequest([&](nsStyleImageRequest* req) {
nsCursorImage* item = ui->mCursorImages.AppendElement();
item->mImage = req;
if (arr->Item(1).GetUnit() != eCSSUnit_Null) {
item->mHaveHotspot = true;
item->mHotspotX = arr->Item(1).GetFloatValue();
item->mHotspotY = arr->Item(2).GetFloatValue();
}
}, aContext->PresContext(), arr->Item(0),
nsStyleImageRequest::Mode::Discard);
nsCursorImage* item = ui->mCursorImages.AppendElement();
item->mImage =
CreateStyleImageRequest(aContext->PresContext(), arr->Item(0),
nsStyleImageRequest::Mode::Discard);
if (arr->Item(1).GetUnit() != eCSSUnit_Null) {
item->mHaveHotspot = true;
item->mHotspotX = arr->Item(1).GetFloatValue();
item->mHotspotY = arr->Item(2).GetFloatValue();
}
}
NS_ASSERTION(list, "Must have non-array value at the end");
@ -8020,9 +8009,8 @@ nsRuleNode::ComputeListData(void* aStartStruct,
// list-style-image: url, none, inherit
const nsCSSValue* imageValue = aRuleData->ValueForListStyleImage();
if (eCSSUnit_Image == imageValue->GetUnit()) {
SetStyleImageRequest([&](nsStyleImageRequest* req) {
list->mListStyleImage = req;
}, mPresContext, *imageValue, nsStyleImageRequest::Mode(0));
list->mListStyleImage = CreateStyleImageRequest(
mPresContext, *imageValue, nsStyleImageRequest::Mode(0));
}
else if (eCSSUnit_None == imageValue->GetUnit() ||
eCSSUnit_Initial == imageValue->GetUnit()) {
@ -8925,9 +8913,7 @@ nsRuleNode::ComputeContentData(void* aStartStruct,
}
data.mType = type;
if (type == eStyleContentType_Image) {
SetImageRequest([&](imgRequestProxy* req) {
data.SetImage(req);
}, mPresContext, value);
data.SetImage(CreateImageRequest(mPresContext, value));
} else if (type <= eStyleContentType_Attr) {
value.GetStringValue(buffer);
data.mContent.mString = NS_strdup(buffer.get());

View File

@ -3190,12 +3190,12 @@ struct nsStyleContentData
void TrackImage(mozilla::dom::ImageTracker* aImageTracker);
void UntrackImage(mozilla::dom::ImageTracker* aImageTracker);
void SetImage(imgRequestProxy* aRequest)
void SetImage(already_AddRefed<imgRequestProxy> aRequest)
{
MOZ_ASSERT(!mImageTracked,
"Setting a new image without untracking the old one!");
MOZ_ASSERT(mType == eStyleContentType_Image, "Wrong type!");
NS_IF_ADDREF(mContent.mImage = aRequest);
mContent.mImage = aRequest.take();
}
};

View File

@ -5,7 +5,6 @@ var h2Port;
var prefs;
var spdypref;
var http2pref;
var tlspref;
var altsvcpref1;
var altsvcpref2;
@ -34,13 +33,11 @@ function run_test() {
spdypref = prefs.getBoolPref("network.http.spdy.enabled");
http2pref = prefs.getBoolPref("network.http.spdy.enabled.http2");
tlspref = prefs.getBoolPref("network.http.spdy.enforce-tls-profile");
altsvcpref1 = prefs.getBoolPref("network.http.altsvc.enabled");
altsvcpref2 = prefs.getBoolPref("network.http.altsvc.oe", true);
prefs.setBoolPref("network.http.spdy.enabled", true);
prefs.setBoolPref("network.http.spdy.enabled.http2", true);
prefs.setBoolPref("network.http.spdy.enforce-tls-profile", false);
prefs.setBoolPref("network.http.altsvc.enabled", true);
prefs.setBoolPref("network.http.altsvc.oe", true);
prefs.setCharPref("network.dns.localDomains", "foo.example.com, bar.example.com");
@ -114,7 +111,6 @@ function h1ServerWK(metadata, response) {
function resetPrefs() {
prefs.setBoolPref("network.http.spdy.enabled", spdypref);
prefs.setBoolPref("network.http.spdy.enabled.http2", http2pref);
prefs.setBoolPref("network.http.spdy.enforce-tls-profile", tlspref);
prefs.setBoolPref("network.http.altsvc.enabled", altsvcpref1);
prefs.setBoolPref("network.http.altsvc.oe", altsvcpref2);
prefs.clearUserPref("network.dns.localDomains");

View File

@ -1025,7 +1025,6 @@ var prefs;
var spdypref;
var spdypush;
var http2pref;
var tlspref;
var altsvcpref1;
var altsvcpref2;
var loadGroup;
@ -1037,7 +1036,6 @@ function resetPrefs() {
prefs.setBoolPref("network.http.spdy.enabled", spdypref);
prefs.setBoolPref("network.http.spdy.allow-push", spdypush);
prefs.setBoolPref("network.http.spdy.enabled.http2", http2pref);
prefs.setBoolPref("network.http.spdy.enforce-tls-profile", tlspref);
prefs.setBoolPref("network.http.altsvc.enabled", altsvcpref1);
prefs.setBoolPref("network.http.altsvc.oe", altsvcpref2);
prefs.clearUserPref("network.dns.localDomains");
@ -1072,7 +1070,6 @@ function run_test() {
spdypref = prefs.getBoolPref("network.http.spdy.enabled");
spdypush = prefs.getBoolPref("network.http.spdy.allow-push");
http2pref = prefs.getBoolPref("network.http.spdy.enabled.http2");
tlspref = prefs.getBoolPref("network.http.spdy.enforce-tls-profile");
altsvcpref1 = prefs.getBoolPref("network.http.altsvc.enabled");
altsvcpref2 = prefs.getBoolPref("network.http.altsvc.oe", true);
@ -1080,7 +1077,6 @@ function run_test() {
prefs.setBoolPref("network.http.spdy.enabled.v3-1", true);
prefs.setBoolPref("network.http.spdy.allow-push", true);
prefs.setBoolPref("network.http.spdy.enabled.http2", true);
prefs.setBoolPref("network.http.spdy.enforce-tls-profile", false);
prefs.setBoolPref("network.http.altsvc.enabled", true);
prefs.setBoolPref("network.http.altsvc.oe", true);
prefs.setCharPref("network.dns.localDomains", "foo.example.com, bar.example.com");

View File

@ -4,7 +4,6 @@ Cu.import("resource://gre/modules/NetUtil.jsm");
var prefs;
var spdypref;
var http2pref;
var tlspref;
var origin;
function run_test() {
@ -19,11 +18,9 @@ function run_test() {
spdypref = prefs.getBoolPref("network.http.spdy.enabled");
http2pref = prefs.getBoolPref("network.http.spdy.enabled.http2");
tlspref = prefs.getBoolPref("network.http.spdy.enforce-tls-profile");
prefs.setBoolPref("network.http.spdy.enabled", true);
prefs.setBoolPref("network.http.spdy.enabled.http2", true);
prefs.setBoolPref("network.http.spdy.enforce-tls-profile", false);
prefs.setCharPref("network.dns.localDomains", "foo.example.com, bar.example.com");
// The moz-http2 cert is for foo.example.com and is signed by CA.cert.der
@ -40,7 +37,6 @@ function run_test() {
function resetPrefs() {
prefs.setBoolPref("network.http.spdy.enabled", spdypref);
prefs.setBoolPref("network.http.spdy.enabled.http2", http2pref);
prefs.setBoolPref("network.http.spdy.enforce-tls-profile", tlspref);
prefs.clearUserPref("network.dns.localDomains");
}

View File

@ -140,8 +140,10 @@ The remainder of the run section is specific to the run-using implementation.
The effect of a job description is to say "run this thing on this worker". The
job description must contain enough information about the worker to identify
the workerType and the implementation (docker-worker, generic-worker, etc.).
Any other task-description information is passed along verbatim, although it is
augmented by the run-using implementation.
Alternatively, job descriptions can specify the ``platforms`` field in
conjunction with the ``by-platform`` key to specify multiple workerTypes and
implementations. Any other task-description information is passed along
verbatim, although it is augmented by the run-using implementation.
The run-using implementations are all located in
``taskcluster/taskgraph/transforms/job``, along with the schemas for their

View File

@ -108,7 +108,7 @@ class TestKeyedBy(unittest.TestCase):
}
self.assertEqual(get_keyed_by(test, 'option', 'x'), 30)
def test_by_value_invalid_dict(self):
def test_by_value_dict(self):
test = {
'test-name': 'tname',
'option': {
@ -116,7 +116,7 @@ class TestKeyedBy(unittest.TestCase):
'by-other-value': {},
},
}
self.assertRaises(Exception, get_keyed_by, test, 'option', 'x')
self.assertEqual(get_keyed_by(test, 'option', 'x'), test['option'])
def test_by_value_invalid_no_default(self):
test = {
@ -130,14 +130,14 @@ class TestKeyedBy(unittest.TestCase):
}
self.assertRaises(Exception, get_keyed_by, test, 'option', 'x')
def test_by_value_invalid_no_by(self):
def test_by_value_no_by(self):
test = {
'test-name': 'tname',
'option': {
'other-value': {},
},
}
self.assertRaises(Exception, get_keyed_by, test, 'option', 'x')
self.assertEqual(get_keyed_by(test, 'option', 'x'), test['option'])
if __name__ == '__main__':
main()

View File

@ -103,26 +103,23 @@ def get_keyed_by(item, field, item_name, subfield=None):
if not isinstance(value, dict):
return value
assert len(value) == 1, "Invalid attribute {} in {}".format(field, item_name)
keyed_by = value.keys()[0]
if len(value) > 1 or not keyed_by.startswith('by-'):
return value
values = value[keyed_by]
if keyed_by.startswith('by-'):
keyed_by = keyed_by[3:] # extract just the keyed-by field name
if item[keyed_by] in values:
return values[item[keyed_by]]
for k in values.keys():
if re.match(k, item[keyed_by]):
return values[k]
if 'default' in values:
return values['default']
for k in item[keyed_by], 'default':
if k in values:
return values[k]
else:
raise Exception(
"Neither {} {} nor 'default' found while determining item {} in {}".format(
keyed_by, item[keyed_by], field, item_name))
keyed_by = keyed_by[3:] # strip 'by-' off the keyed-by field name
if item[keyed_by] in values:
return values[item[keyed_by]]
for k in values.keys():
if re.match(k, item[keyed_by]):
return values[k]
if 'default' in values:
return values['default']
for k in item[keyed_by], 'default':
if k in values:
return values[k]
else:
raise Exception(
"Invalid attribute {} keyed-by value {} in {}".format(
field, keyed_by, item_name))
"Neither {} {} nor 'default' found while determining item {} in {}".format(
keyed_by, item[keyed_by], field, item_name))

View File

@ -15,13 +15,14 @@ import copy
import logging
import os
from taskgraph.transforms.base import validate_schema, TransformSequence
from taskgraph.transforms.base import get_keyed_by, validate_schema, TransformSequence
from taskgraph.transforms.task import task_description_schema
from voluptuous import (
Any,
Extra,
Optional,
Required,
Schema,
Extra,
)
logger = logging.getLogger(__name__)
@ -52,9 +53,7 @@ job_description_schema = Schema({
Optional('index'): task_description_schema['index'],
Optional('run-on-projects'): task_description_schema['run-on-projects'],
Optional('coalesce-name'): task_description_schema['coalesce-name'],
Optional('worker-type'): task_description_schema['worker-type'],
Optional('needs-sccache'): task_description_schema['needs-sccache'],
Required('worker'): task_description_schema['worker'],
Optional('when'): task_description_schema['when'],
# A description of how to run this job.
@ -66,6 +65,15 @@ job_description_schema = Schema({
# own schema.
Extra: object,
},
Optional('platforms'): [basestring],
Required('worker-type'): Any(
task_description_schema['worker-type'],
{'by-platform': {basestring: task_description_schema['worker-type']}},
),
Required('worker'): Any(
task_description_schema['worker'],
{'by-platform': {basestring: task_description_schema['worker']}},
),
})
transforms = TransformSequence()
@ -78,6 +86,36 @@ def validate(config, jobs):
"In job {!r}:".format(job['name']))
@transforms.add
def expand_platforms(config, jobs):
for job in jobs:
if 'platforms' not in job:
yield job
continue
for platform in job['platforms']:
pjob = copy.deepcopy(job)
pjob['platform'] = platform
del pjob['platforms']
platform, buildtype = platform.rsplit('/', 1)
pjob['name'] = '{}-{}-{}'.format(pjob['name'], platform, buildtype)
yield pjob
@transforms.add
def resolve_keyed_by(config, jobs):
fields = [
'worker-type',
'worker',
]
for job in jobs:
for field in fields:
job[field] = get_keyed_by(item=job, field=field, item_name=job['name'])
yield job
@transforms.add
def make_task_description(config, jobs):
"""Given a build description, create a task description"""
@ -90,6 +128,10 @@ def make_task_description(config, jobs):
job['label'] = '{}-{}'.format(config.kind, job['name'])
if job['name']:
del job['name']
if 'platform' in job:
if 'treeherder' in job:
job['treeherder']['platform'] = job['platform']
del job['platform']
taskdesc = copy.deepcopy(job)

View File

@ -1067,14 +1067,7 @@ public:
return; // Already shut down.
}
const auto& layerClient = GeckoLayerClient::Ref::From(aClient);
// If resetting is true, Android destroyed our GeckoApp activity and we
// had to recreate it, but all the Gecko-side things were not
// destroyed. We therefore need to link up the new java objects to
// Gecko, and that's what we do here.
const bool resetting = !!mLayerClient;
mLayerClient = layerClient;
mLayerClient = GeckoLayerClient::Ref::From(aClient);
MOZ_ASSERT(aNPZC);
auto npzc = NativePanZoomController::LocalRef(
@ -1082,15 +1075,12 @@ public:
NativePanZoomController::Ref::From(aNPZC));
mWindow->mNPZCSupport.Attach(npzc, mWindow, npzc);
layerClient->OnGeckoReady();
mLayerClient->OnGeckoReady();
if (resetting) {
// Since we are re-linking the new java objects to Gecko, we need
// to get the viewport from the compositor (since the Java copy was
// thrown away) and we do that by setting the first-paint flag.
if (RefPtr<CompositorBridgeParent> bridge = mWindow->GetCompositorBridgeParent()) {
bridge->ForceIsFirstPaint();
}
// Set the first-paint flag so that we (re-)link any new Java objects
// to Gecko, co-ordinate viewports, etc.
if (RefPtr<CompositorBridgeParent> bridge = mWindow->GetCompositorBridgeParent()) {
bridge->ForceIsFirstPaint();
}
}

View File

@ -332,14 +332,25 @@ protected:
RefPtr<MozPromise> mPromise;
};
explicit ThenValueBase(AbstractThread* aResponseTarget, const char* aCallSite)
: mResponseTarget(aResponseTarget), mCallSite(aCallSite) {}
ThenValueBase(AbstractThread* aResponseTarget,
const char* aCallSite,
bool aInitCompletionPromise = false)
: mResponseTarget(aResponseTarget)
, mCallSite(aCallSite)
, mInitCompletionPromise(aInitCompletionPromise)
{
if (mInitCompletionPromise) {
mCompletionPromise = new MozPromise::Private(
"<completion promise>", true /* aIsCompletionPromise */);
}
}
MozPromise* CompletionPromise() override
{
MOZ_DIAGNOSTIC_ASSERT(mResponseTarget->IsCurrentThreadIn());
MOZ_DIAGNOSTIC_ASSERT(mInitCompletionPromise ||
mResponseTarget->IsCurrentThreadIn());
MOZ_DIAGNOSTIC_ASSERT(!Request::mComplete);
if (!mCompletionPromise) {
if (!mInitCompletionPromise && !mCompletionPromise) {
mCompletionPromise = new MozPromise::Private(
"<completion promise>", true /* aIsCompletionPromise */);
}
@ -433,6 +444,10 @@ protected:
RefPtr<MozPromise> mCompletionPromise;
const char* mCallSite;
// True if mCompletionPromise should be initialized in the constructor
// to make CompletionPromise() thread-safe.
const bool mInitCompletionPromise;
};
/*
@ -484,8 +499,8 @@ protected:
public:
MethodThenValue(AbstractThread* aResponseTarget, ThisType* aThisVal,
ResolveMethodType aResolveMethod, RejectMethodType aRejectMethod,
const char* aCallSite)
: ThenValueBase(aResponseTarget, aCallSite)
const char* aCallSite, bool aInitCompletionPromise = false)
: ThenValueBase(aResponseTarget, aCallSite, aInitCompletionPromise)
, mThisVal(aThisVal)
, mResolveMethod(aResolveMethod)
, mRejectMethod(aRejectMethod) {}
@ -533,8 +548,9 @@ protected:
FunctionThenValue(AbstractThread* aResponseTarget,
ResolveFunction&& aResolveFunction,
RejectFunction&& aRejectFunction,
const char* aCallSite)
: ThenValueBase(aResponseTarget, aCallSite)
const char* aCallSite,
bool aInitCompletionPromise = false)
: ThenValueBase(aResponseTarget, aCallSite, aInitCompletionPromise)
{
mResolveFunction.emplace(Move(aResolveFunction));
mRejectFunction.emplace(Move(aRejectFunction));
@ -603,7 +619,7 @@ public:
template<typename ThisType, typename ResolveMethodType, typename RejectMethodType>
RefPtr<Request> Then(AbstractThread* aResponseThread, const char* aCallSite, ThisType* aThisVal,
ResolveMethodType aResolveMethod, RejectMethodType aRejectMethod)
ResolveMethodType aResolveMethod, RejectMethodType aRejectMethod)
{
RefPtr<ThenValueBase> thenValue = new MethodThenValue<ThisType, ResolveMethodType, RejectMethodType>(
aResponseThread, aThisVal, aResolveMethod, aRejectMethod, aCallSite);
@ -613,7 +629,7 @@ public:
template<typename ResolveFunction, typename RejectFunction>
RefPtr<Request> Then(AbstractThread* aResponseThread, const char* aCallSite,
ResolveFunction&& aResolveFunction, RejectFunction&& aRejectFunction)
ResolveFunction&& aResolveFunction, RejectFunction&& aRejectFunction)
{
RefPtr<ThenValueBase> thenValue = new FunctionThenValue<ResolveFunction, RejectFunction>(aResponseThread,
Move(aResolveFunction), Move(aRejectFunction), aCallSite);
@ -621,6 +637,41 @@ public:
return thenValue.forget(); // Implicit conversion from already_AddRefed<ThenValueBase> to RefPtr<Request>.
}
// Equivalent to Then(target, ...)->CompletionPromise()
// without the restriction that CompletionPromise() must be called on the
// |target| thread. So ThenPromise() can be called on any thread as Then().
// The syntax is close to JS promise and makes promise chaining easier
// where you can do: p->ThenPromise()->ThenPromise()->ThenPromise();
//
// Note you would have to call Then() instead when the result needs to be held
// by a MozPromiseRequestHolder for future disconnection.
//
// TODO: replace Then()->CompletionPromise() with ThenPromise() and
// stop exposing CompletionPromise() to the client code.
template<typename ThisType, typename ResolveMethodType, typename RejectMethodType>
MOZ_MUST_USE RefPtr<MozPromise>
ThenPromise(AbstractThread* aResponseThread, const char* aCallSite, ThisType* aThisVal,
ResolveMethodType aResolveMethod, RejectMethodType aRejectMethod)
{
using ThenType = MethodThenValue<ThisType, ResolveMethodType, RejectMethodType>;
RefPtr<ThenValueBase> thenValue = new ThenType(aResponseThread, aThisVal, aResolveMethod,
aRejectMethod, aCallSite, true /* aInitCompletionPromise */);
ThenInternal(aResponseThread, thenValue, aCallSite);
return thenValue->CompletionPromise();
}
template<typename ResolveFunction, typename RejectFunction>
MOZ_MUST_USE RefPtr<MozPromise>
ThenPromise(AbstractThread* aResponseThread, const char* aCallSite,
ResolveFunction&& aResolveFunction, RejectFunction&& aRejectFunction)
{
using ThenType = FunctionThenValue<ResolveFunction, RejectFunction>;
RefPtr<ThenValueBase> thenValue = new ThenType(aResponseThread, Move(aResolveFunction),
Move(aRejectFunction), aCallSite, true /* aInitCompletionPromise */);
ThenInternal(aResponseThread, thenValue, aCallSite);
return thenValue->CompletionPromise();
}
void ChainTo(already_AddRefed<Private> aChainedPromise, const char* aCallSite)
{
MutexAutoLock lock(mMutex);