Browse Source

import changes from `dev' branch of rmottola/Arctic-Fox:

- Bug 1134252 - Don't crash the content process if RenderFrameParent is not constructed successfully. r=billm. (2564cb0e6a)
- Bug 1180644: Fix crashes after enabling OOP on B2GDroid. r=snorp (d585c571e3)
- Bug 1198674 - null-check mFrameLoader in RenderFrameParent. r=sotaro (86f26b2046)
- Bug 1198674 - Null-check mFrameLoader before calling GetFrom in RenderFrameParent. r=sotaro (33bd495e75)
- Bug 1200778 - Make sure to update the APZCTreeManager associated with a RenderFrameParent when it is dragged to a new window. r=mstange (bf2d25616c)
- Bug 1202703 - Part 1 - CreateRenderingContext can fail. r=mattwoodrow (50de4cd050)
- Bug 1185747 part 1 - Use pref/meta-viewport tag instead of DOMWindowUtils to set the CSS viewport for mochitests. r=tn (62a8c1d460)
- Bug 1147038 - Update some tests to pass on desktop platforms. r=tn (afa54f4dc9)
- Bug 1169666 - Revert reftest sanity flag ordering, fixes failures on OS X. (553743b4ce)
- Bug 1114526. Add reftest. (ef2589e3b8)
- Bug 1192616 - Skip over some reftests which fail on the pandaboards with the new dynamic toolbar implementation due to the screen size being too small. r=gbrown (fd3a0a523c)
- Bug 1185747 part 2 - Remove magical reftest harness properties and use standard meta-viewport tags instead. r=tn (73d2d442d9)
- Bug 1194811 Part 1 - Recompute the zoom constraints if the available screen area changes. r=botond (620dc82022)
- Bug 1194811 Part 2 - Use the content viewer size rather than the composition size of the root frame when computing the CSS viewport. r=botond (089459fcb5)
- Bug 1185747 part 3 - Rip out code to explicitly override the CSS viewport. r=tn (00ea1c7277)
- Bug 1178354 - Ensure we fire a before-first-paint event for printing as well. r=tn (3dfd7f0f76)
- Bug 1152254 - Handle vertical text frames when clipping display list for drag image. r=smontagu (965256a547)
- Bug 1156135. Add runtime testing of graphics features. r=mattwoodrow,mossop (6a8cb24421)
- Refactor the graphics sanity test to support multiple snapshots. (bug 1173117 part 1, r=mattwoodrow) (8a0a78e4d3)
- Add an observer service notification for the first widget paint message. (bug 1173117 part 2, r=roc) (e421003dcd)
- Fix a widget size check bug in nsWindow::CaptureWidgetOnScreen. (bug 1173117 part 3, r=mattwoodrow) (485694c380)
- Add OS snapshotting to the gfx sanity test and report whether or not it matches the compositing test results. (bug 1173117 part 4, r=mattwoodrow,vladan) (38e82d10ad)
- Bug 1191608 - initialize element to null in CanvasRenderingContext2D::DrawImage. r=bas (e26dd8b8ce)
master
roytam1 2 months ago
parent
commit
e0e5f031a0
  1. 6
      browser/installer/package-manifest.in
  2. 19
      dom/base/nsDOMWindowUtils.cpp
  3. 2
      dom/canvas/CanvasRenderingContext2D.cpp
  4. 11
      dom/interfaces/base/nsIDOMWindowUtils.idl
  5. 18
      dom/ipc/TabParent.cpp
  6. 2
      dom/media/fmp4/MP4Decoder.cpp
  7. 5
      dom/tests/mochitest/dom-level0/innerWidthHeight_script.html
  8. 3
      dom/tests/mochitest/dom-level0/test_innerWidthHeight_script.html
  9. 6
      gfx/src/nsDeviceContext.cpp
  10. 2
      gfx/thebes/gfxAndroidPlatform.cpp
  11. 18
      layout/base/ZoomConstraintsClient.cpp
  12. 1
      layout/base/ZoomConstraintsClient.h
  13. 12
      layout/base/nsIPresShell.h
  14. 11
      layout/base/nsLayoutUtils.cpp
  15. 6
      layout/base/nsLayoutUtils.h
  16. 98
      layout/base/nsPresShell.cpp
  17. 8
      layout/base/nsPresShell.h
  18. 7
      layout/generic/nsSimplePageSequenceFrame.cpp
  19. 15
      layout/ipc/RenderFrameParent.cpp
  20. 7
      layout/printing/nsPrintEngine.cpp
  21. 5
      layout/reftests/bugs/1114526-1-ref.html
  22. BIN
      layout/reftests/bugs/1114526-1.gif
  23. 64
      layout/reftests/bugs/1114526-1.html
  24. 3
      layout/reftests/bugs/593243-1.html
  25. 3
      layout/reftests/bugs/593243-2.html
  26. 15
      layout/reftests/bugs/reftest.list
  27. 2
      layout/reftests/canvas/reftest.list
  28. 2
      layout/reftests/css-default/submit-button/reftest.list
  29. 4
      layout/reftests/css-gradients/reftest.list
  30. 16
      layout/reftests/reftest-sanity/reftest.list
  31. 4
      layout/reftests/reftest-sanity/test-bg-attachment-fixed-ref.html
  32. 2
      layout/reftests/reftest-sanity/test-bg-attachment-fixed.html
  33. 4
      layout/reftests/reftest-sanity/test-displayport-2.html
  34. 4
      layout/reftests/reftest-sanity/test-displayport-bg.html
  35. 4
      layout/reftests/reftest-sanity/test-pos-fixed-ref.html
  36. 3
      layout/reftests/reftest-sanity/test-pos-fixed-transform-ref.html
  37. 4
      layout/reftests/reftest-sanity/test-pos-fixed-transform.html
  38. 4
      layout/reftests/reftest-sanity/test-pos-fixed.html
  39. 11
      layout/tools/reftest/README.txt
  40. 10
      layout/tools/reftest/reftest-content.js
  41. 3
      toolkit/components/gfx/GfxSanityTest.manifest
  42. 290
      toolkit/components/gfx/SanityTest.js
  43. 6
      toolkit/components/gfx/content/sanitytest.html
  44. BIN
      toolkit/components/gfx/content/videotest.mp4
  45. 8
      toolkit/components/gfx/jar.mn
  46. 15
      toolkit/components/gfx/moz.build
  47. 1
      toolkit/components/moz.build
  48. 8
      toolkit/components/telemetry/Histograms.json
  49. 1
      widget/GfxInfoBase.cpp
  50. 2
      widget/windows/nsWindow.cpp

6
browser/installer/package-manifest.in

@ -845,3 +845,9 @@ bin/libfreebl_32int64_3.so
#if defined(MOZ_ASAN) && defined(CLANG_CL)
@BINPATH@/clang_rt.asan_dynamic-i386.dll
#endif
; gfx
#ifdef XP_WIN
@RESPATH@/components/GfxSanityTest.manifest
@RESPATH@/components/SanityTest.js
#endif

19
dom/base/nsDOMWindowUtils.cpp

@ -297,25 +297,6 @@ nsDOMWindowUtils::UpdateLayerTree()
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::SetCSSViewport(float aWidthPx, float aHeightPx)
{
MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
if (!(aWidthPx >= 0.0 && aHeightPx >= 0.0)) {
return NS_ERROR_ILLEGAL_VALUE;
}
nsIPresShell* presShell = GetPresShell();
if (!presShell) {
return NS_ERROR_FAILURE;
}
nsLayoutUtils::SetCSSViewport(presShell, CSSSize(aWidthPx, aHeightPx));
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::GetViewportInfo(uint32_t aDisplayWidth,
uint32_t aDisplayHeight,

2
dom/canvas/CanvasRenderingContext2D.cpp

@ -4403,7 +4403,7 @@ CanvasRenderingContext2D::DrawImage(const CanvasImageSource& image,
RefPtr<SourceSurface> srcSurf;
gfx::IntSize imgSize;
Element* element;
Element* element = nullptr;
EnsureTarget();
if (image.IsHTMLCanvasElement()) {

11
dom/interfaces/base/nsIDOMWindowUtils.idl

@ -49,7 +49,7 @@ interface nsIJSRAIIHelper;
interface nsIContentPermissionRequest;
interface nsIObserver;
[scriptable, uuid(6ddc9a79-18cd-4dbc-9975-68928e6c9857)]
[scriptable, uuid(a30a95ac-3b95-4251-88dc-8efa89ba9f9c)]
interface nsIDOMWindowUtils : nsISupports {
/**
@ -106,15 +106,6 @@ interface nsIDOMWindowUtils : nsISupports {
*/
void updateLayerTree();
/**
* Set the CSS viewport to be |widthPx| x |heightPx| in units of CSS
* pixels, regardless of the size of the enclosing widget/view.
* This will trigger reflow.
*
* The caller of this method must have chrome privileges.
*/
void setCSSViewport(in float aWidthPx, in float aHeightPx);
/**
* Information retrieved from the <meta name="viewport"> tag.
* See nsContentUtils::GetViewportInfo for more information.

18
dom/ipc/TabParent.cpp

@ -2715,18 +2715,16 @@ TabParent::AllocPRenderFrameParent()
TextureFactoryIdentifier textureFactoryIdentifier;
uint64_t layersId = 0;
bool success = false;
if(frameLoader) {
PRenderFrameParent* renderFrame =
new RenderFrameParent(frameLoader,
&textureFactoryIdentifier,
&layersId,
&success);
MOZ_ASSERT(success);
PRenderFrameParent* renderFrame =
new RenderFrameParent(frameLoader,
&textureFactoryIdentifier,
&layersId,
&success);
if (success) {
AddTabParentToTable(layersId, this);
return renderFrame;
} else {
return nullptr;
}
return renderFrame;
}
bool

2
dom/media/fmp4/MP4Decoder.cpp

@ -209,7 +209,7 @@ IsAndroidAvailable()
return false;
#else
// We need android.media.MediaCodec which exists in API level 16 and higher.
return AndroidBridge::Bridge()->GetAPIVersion() >= 16;
return AndroidBridge::Bridge() && (AndroidBridge::Bridge()->GetAPIVersion() >= 16);
#endif
}

5
dom/tests/mochitest/dom-level0/innerWidthHeight_script.html

@ -6,11 +6,6 @@
<script class="testbody" type="text/javascript">
function runSubTest()
{
// Firefox doesn't support the metaviewport tag on desktop, so we force
// css viewport here using nsIDomWindowUtils
var cwu = SpecialPowers.getDOMWindowUtils(window);
cwu.setCSSViewport(320, 320);
var oldWidth = window.innerWidth;
var oldHeight = window.innerHeight;

3
dom/tests/mochitest/dom-level0/test_innerWidthHeight_script.html

@ -23,7 +23,8 @@
}
function startTest() {
SpecialPowers.pushPrefEnv({"set": [["dom.disable_window_move_resize", false]]}, runTest);
SpecialPowers.pushPrefEnv({"set": [["dom.disable_window_move_resize", false],
["dom.meta-viewport.enabled", true ]]}, runTest);
}
</script>
</body>

6
gfx/src/nsDeviceContext.cpp

@ -413,9 +413,11 @@ nsDeviceContext::CreateRenderingContext()
gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(printingSurface,
gfx::IntSize(mWidth, mHeight));
// This can legitimately happen - CreateDrawTargetForSurface will fail
// to create a draw target if the size is too large, for instance.
if (!dt) {
gfxCriticalError() << "Failed to create draw target in device context sized " << mWidth << "x" << mHeight << " and pointers " << hexa(mPrintingSurface) << " and " << hexa(printingSurface);
MOZ_CRASH("Cannot CreateDrawTargetForSurface");
gfxCriticalNote << "Failed to create draw target in device context sized " << mWidth << "x" << mHeight << " and pointers " << hexa(mPrintingSurface) << " and " << hexa(printingSurface);
return nullptr;
}
#ifdef XP_MACOSX

2
gfx/thebes/gfxAndroidPlatform.cpp

@ -416,7 +416,7 @@ gfxAndroidPlatform::UseAcceleratedSkiaCanvas()
bool gfxAndroidPlatform::HaveChoiceOfHWAndSWCanvas()
{
#ifdef MOZ_WIDGET_ANDROID
if (AndroidBridge::Bridge()->GetAPIVersion() < 11) {
if (!AndroidBridge::Bridge() || AndroidBridge::Bridge()->GetAPIVersion() < 11) {
// It's slower than software due to not having a compositing fast path
return false;
}

18
layout/base/ZoomConstraintsClient.cpp

@ -133,6 +133,13 @@ ZoomConstraintsClient::Observe(nsISupports* aSubject, const char* aTopic, const
return NS_OK;
}
void
ZoomConstraintsClient::ScreenSizeChanged()
{
ZCC_LOG("Got a screen-size change notification in %p\n", this);
RefreshZoomConstraints();
}
mozilla::layers::ZoomConstraints
ComputeZoomConstraintsFromViewportInfo(const nsViewportInfo& aViewportInfo)
{
@ -161,14 +168,10 @@ ZoomConstraintsClient::RefreshZoomConstraints()
return;
}
nsIFrame* rootFrame = mPresShell->GetRootScrollFrame();
if (!rootFrame) {
rootFrame = mPresShell->GetRootFrame();
LayoutDeviceIntSize screenSize;
if (!nsLayoutUtils::GetContentViewerSize(mPresShell->GetPresContext(), screenSize)) {
return;
}
nsSize size = nsLayoutUtils::CalculateCompositionSizeForFrame(rootFrame, false);
int32_t auPerDevPixel = mPresShell->GetPresContext()->AppUnitsPerDevPixel();
LayoutDeviceIntSize screenSize = LayoutDeviceIntSize::FromAppUnitsRounded(
size, auPerDevPixel);
nsViewportInfo viewportInfo = nsContentUtils::GetViewportInfo(
mDocument,
@ -180,6 +183,7 @@ ZoomConstraintsClient::RefreshZoomConstraints()
if (zoomConstraints.mAllowDoubleTapZoom) {
// If the CSS viewport is narrower than the screen (i.e. width <= device-width)
// then we disable double-tap-to-zoom behaviour.
int32_t auPerDevPixel = mPresShell->GetPresContext()->AppUnitsPerDevPixel();
CSSToLayoutDeviceScale scale(
(float)nsPresContext::AppUnitsPerCSSPixel() / auPerDevPixel);
if ((viewportInfo.GetSize() * scale).width <= screenSize.width) {

1
layout/base/ZoomConstraintsClient.h

@ -33,6 +33,7 @@ private:
public:
void Init(nsIPresShell* aPresShell, nsIDocument *aDocument);
void Destroy();
void ScreenSizeChanged();
private:
void RefreshZoomConstraints();

12
layout/base/nsIPresShell.h

@ -139,10 +139,10 @@ typedef struct CapturingContentInfo {
mozilla::StaticRefPtr<nsIContent> mContent;
} CapturingContentInfo;
// 4f512d0b-c58c-4fc9-ae42-8aa6d992e7ae
// b07c5323-3061-4ca9-95ed-84cccbffadac
#define NS_IPRESSHELL_IID \
{ 0x4f512d0b, 0xc58c, 0x4fc9, \
{ 0xae, 0x42, 0x8a, 0xa6, 0xd9, 0x92, 0xe7, 0xae } }
{ 0xb07c5323, 0x3061, 0x4ca9, \
{ 0x95, 0xed, 0x84, 0xcc, 0xcb, 0xff, 0xad, 0xac } }
// debug VerifyReflow flags
#define VERIFY_REFLOW_ON 0x01
@ -404,12 +404,6 @@ public:
* coordinates for aWidth and aHeight must be in standard nscoord's.
*/
virtual nsresult ResizeReflow(nscoord aWidth, nscoord aHeight) = 0;
/**
* Reflow, and also change presshell state so as to only permit
* reflowing off calls to ResizeReflowOverride() in the future.
* ResizeReflow() calls are ignored after ResizeReflowOverride().
*/
virtual nsresult ResizeReflowOverride(nscoord aWidth, nscoord aHeight) = 0;
/**
* Do the same thing as ResizeReflow but even if ResizeReflowOverride was
* called previously.

11
layout/base/nsLayoutUtils.cpp

@ -8339,17 +8339,6 @@ nsLayoutUtils::SetScrollPositionClampingScrollPortSize(nsIPresShell* aPresShell,
MaybeReflowForInflationScreenSizeChange(presContext);
}
/* static */ void
nsLayoutUtils::SetCSSViewport(nsIPresShell* aPresShell, CSSSize aSize)
{
MOZ_ASSERT(aSize.width >= 0.0 && aSize.height >= 0.0);
nscoord width = nsPresContext::CSSPixelsToAppUnits(aSize.width);
nscoord height = nsPresContext::CSSPixelsToAppUnits(aSize.height);
aPresShell->ResizeReflowOverride(width, height);
}
/* static */ FrameMetrics
nsLayoutUtils::ComputeFrameMetrics(nsIFrame* aForFrame,
nsIFrame* aScrollFrame,

6
layout/base/nsLayoutUtils.h

@ -2707,12 +2707,6 @@ public:
static void SetScrollPositionClampingScrollPortSize(nsIPresShell* aPresShell,
CSSSize aSize);
/**
* Set the CSS viewport to the given size
* (see nsIDOMWindowUtils.setCSSViewport).
*/
static void SetCSSViewport(nsIPresShell* aPresShell, CSSSize aSize);
static FrameMetrics ComputeFrameMetrics(nsIFrame* aForFrame,
nsIFrame* aScrollFrame,
nsIContent* aContent,

98
layout/base/nsPresShell.cpp

@ -785,7 +785,6 @@ PresShell::PresShell()
#endif
mRenderFlags = 0;
mResolution = 1.0;
mViewportOverridden = false;
mScrollPositionClampingScrollPortSizeSet = false;
@ -807,6 +806,7 @@ PresShell::PresShell()
mPaintingIsFrozen = false;
mHasCSSBackgroundColor = true;
mIsLastChromeOnlyEscapeKeyConsumed = false;
mHasReceivedPaintMessage = false;
}
NS_IMPL_ISUPPORTS(PresShell, nsIPresShell, nsIDocumentObserver,
@ -1749,6 +1749,12 @@ PresShell::Initialize(nscoord aWidth, nscoord aHeight)
}
}
// If we get here and painting is not suppressed, then we can paint anytime
// and we should fire the before-first-paint notification
if (!mPaintingSuppressed) {
ScheduleBeforeFirstPaint();
}
if (root && root->IsXULElement()) {
mozilla::Telemetry::AccumulateTimeDelta(Telemetry::XUL_INITIAL_FRAME_CONSTRUCTION,
timerStart);
@ -1771,35 +1777,15 @@ PresShell::AsyncResizeEventCallback(nsITimer* aTimer, void* aPresShell)
static_cast<PresShell*>(aPresShell)->FireResizeEvent();
}
nsresult
PresShell::ResizeReflowOverride(nscoord aWidth, nscoord aHeight)
{
mViewportOverridden = true;
if (mMobileViewportManager) {
// Once the viewport is explicitly overridden, we don't need the
// MobileViewportManager any more (in this presShell at least). Destroying
// it simplifies things because then it can maintain an invariant that any
// time it gets a meta-viewport change (for example) it knows it must
// recompute the CSS viewport and do a reflow. If we didn't destroy it here
// then there would be times where a meta-viewport change would have no
// effect.
mMobileViewportManager->Destroy();
mMobileViewportManager = nullptr;
}
return ResizeReflowIgnoreOverride(aWidth, aHeight);
}
nsresult
PresShell::ResizeReflow(nscoord aWidth, nscoord aHeight)
{
if (mViewportOverridden) {
// The viewport has been overridden, and this reflow request
// didn't ask to ignore the override. Pretend it didn't happen.
return NS_OK;
if (mZoomConstraintsClient) {
// If we have a ZoomConstraintsClient and the available screen area
// changed, then we might need to disable double-tap-to-zoom, so notify
// the ZCC to update itself.
mZoomConstraintsClient->ScreenSizeChanged();
}
if (mMobileViewportManager) {
// If we have a mobile viewport manager, request a reflow from it. It can
// recompute the final CSS viewport and trigger a call to
@ -2923,11 +2909,15 @@ PresShell::CreateReferenceRenderingContext()
if (mPresContext->IsScreen()) {
rc = new gfxContext(gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget());
} else {
// We assume the devCtx has positive width and height for this call
// We assume the devCtx has positive width and height for this call.
// However, width and height, may be outside of the reasonable range
// so rc may still be null.
rc = devCtx->CreateRenderingContext();
if (!rc) {
return nullptr;
}
}
MOZ_ASSERT(rc, "shouldn't break promise to return non-null");
return rc.forget();
}
@ -3764,6 +3754,17 @@ PresShell::CaptureHistoryState(nsILayoutHistoryState** aState)
return NS_OK;
}
void
PresShell::ScheduleBeforeFirstPaint()
{
if (!mDocument->IsResourceDoc()) {
// Notify observers that a new page is about to be drawn. Execute this
// as soon as it is safe to run JS, which is guaranteed to be before we
// go back to the event loop and actually draw the page.
nsContentUtils::AddScriptRunner(new nsBeforeFirstPaintDispatcher(mDocument));
}
}
void
PresShell::UnsuppressAndInvalidate()
{
@ -3775,12 +3776,7 @@ PresShell::UnsuppressAndInvalidate()
return;
}
if (!mDocument->IsResourceDoc()) {
// Notify observers that a new page is about to be drawn. Execute this
// as soon as it is safe to run JS, which is guaranteed to be before we
// go back to the event loop and actually draw the page.
nsContentUtils::AddScriptRunner(new nsBeforeFirstPaintDispatcher(mDocument));
}
ScheduleBeforeFirstPaint();
mPaintingSuppressed = false;
nsIFrame* rootFrame = mFrameConstructor->GetRootFrame();
@ -4775,14 +4771,21 @@ PresShell::ClipListToRange(nsDisplayListBuilder *aBuilder,
frame->GetPointFromOffset(hilightStart, &startPoint);
frame->GetPointFromOffset(hilightEnd, &endPoint);
// the clip rectangle is determined by taking the the start and
// The clip rectangle is determined by taking the the start and
// end points of the range, offset from the reference frame.
// Because of rtl, the end point may be to the left of the
// start point, so x is set to the lowest value
// Because of rtl, the end point may be to the left of (or above,
// in vertical mode) the start point, so x (or y) is set to the
// lower of the values.
nsRect textRect(aBuilder->ToReferenceFrame(frame), frame->GetSize());
nscoord x = std::min(startPoint.x, endPoint.x);
textRect.x += x;
textRect.width = std::max(startPoint.x, endPoint.x) - x;
if (frame->GetWritingMode().IsVertical()) {
nscoord y = std::min(startPoint.y, endPoint.y);
textRect.y += y;
textRect.height = std::max(startPoint.y, endPoint.y) - y;
} else {
nscoord x = std::min(startPoint.x, endPoint.x);
textRect.x += x;
textRect.width = std::max(startPoint.x, endPoint.x) - x;
}
surfaceRect.UnionRect(surfaceRect, textRect);
DisplayItemClip newClip;
@ -8602,6 +8605,19 @@ PresShell::DidPaintWindow()
// about compositing of popups.
return;
}
if (!mHasReceivedPaintMessage) {
mHasReceivedPaintMessage = true;
nsCOMPtr<nsIObserverService> obsvc = services::GetObserverService();
if (obsvc && mDocument) {
nsPIDOMWindow* window = mDocument->GetWindow();
nsCOMPtr<nsIDOMChromeWindow> chromeWin(do_QueryInterface(window));
if (chromeWin) {
obsvc->NotifyObservers(chromeWin, "widget-first-paint", nullptr);
}
}
}
}
bool
@ -8951,6 +8967,7 @@ PresShell::DoReflow(nsIFrame* target, bool aInterruptible)
nsIFrame* rootFrame = mFrameConstructor->GetRootFrame();
// CreateReferenceRenderingContext can return nullptr
nsRenderingContext rcx(CreateReferenceRenderingContext());
#ifdef DEBUG
@ -10884,6 +10901,7 @@ nsIPresShell::SyncWindowProperties(nsView* aView)
{
nsIFrame* frame = aView->GetFrame();
if (frame && mPresContext) {
// CreateReferenceRenderingContext can return nullptr
nsRenderingContext rcx(CreateReferenceRenderingContext());
nsContainerFrame::SyncWindowProperties(mPresContext, frame, aView, &rcx, 0);
}

8
layout/base/nsPresShell.h

@ -105,7 +105,6 @@ public:
virtual void EndObservingDocument() override;
virtual nsresult Initialize(nscoord aWidth, nscoord aHeight) override;
virtual nsresult ResizeReflow(nscoord aWidth, nscoord aHeight) override;
virtual nsresult ResizeReflowOverride(nscoord aWidth, nscoord aHeight) override;
virtual nsresult ResizeReflowIgnoreOverride(nscoord aWidth, nscoord aHeight) override;
virtual nsIPageSequenceFrame* GetPageSequenceFrame() const override;
virtual nsCanvasFrame* GetCanvasFrame() const override;
@ -355,7 +354,7 @@ public:
virtual nsresult SetIsActive(bool aIsActive) override;
virtual bool GetIsViewportOverridden() override {
return mViewportOverridden || (mMobileViewportManager != nullptr);
return (mMobileViewportManager != nullptr);
}
virtual bool IsLayoutFlushObserver() override
@ -409,6 +408,7 @@ protected:
void HandlePostedReflowCallbacks(bool aInterruptible);
void CancelPostedReflowCallbacks();
void ScheduleBeforeFirstPaint();
void UnsuppressAndInvalidate();
void WillCauseReflow() {
@ -853,7 +853,6 @@ protected:
bool mDocumentLoading : 1;
bool mIgnoreFrameDestruction : 1;
bool mHaveShutDown : 1;
bool mViewportOverridden : 1;
bool mLastRootReflowHadUnconstrainedBSize : 1;
bool mNoDelayedMouseEvents : 1;
bool mNoDelayedKeyEvents : 1;
@ -883,6 +882,9 @@ protected:
// Whether the last chrome-only escape key event is consumed.
bool mIsLastChromeOnlyEscapeKeyConsumed : 1;
// Whether the widget has received a paint message yet.
bool mHasReceivedPaintMessage : 1;
static bool sDisableNonTestMouseEvents;
};

7
layout/generic/nsSimplePageSequenceFrame.cpp

@ -645,6 +645,7 @@ nsSimplePageSequenceFrame::PrePrintNextPage(nsITimerCallback* aCallback, bool* a
mCalledBeginPage = true;
nsRefPtr<gfxContext> renderingContext = dc->CreateRenderingContext();
NS_ENSURE_TRUE(renderingContext, NS_ERROR_OUT_OF_MEMORY);
nsRefPtr<gfxASurface> renderingSurface =
renderingContext->CurrentSurface();
@ -773,7 +774,11 @@ nsSimplePageSequenceFrame::PrintNextPage()
PR_PL(("SeqFr::PrintNextPage -> %p PageNo: %d", pf, mPageNum));
nsRenderingContext renderingContext(dc->CreateRenderingContext());
// CreateRenderingContext can fail
nsRefPtr<gfxContext> gCtx = dc->CreateRenderingContext();
NS_ENSURE_TRUE(gCtx, NS_ERROR_OUT_OF_MEMORY);
nsRenderingContext renderingContext(gCtx);
nsRect drawingRect(nsPoint(0, 0), currentPage->GetSize());
nsRegion drawingRegion(drawingRect);

15
layout/ipc/RenderFrameParent.cpp

@ -218,7 +218,8 @@ public:
virtual void PostDelayedTask(Task* aTask, int aDelayMs) override
{
MessageLoop::current()->PostDelayedTask(FROM_HERE, aTask, aDelayMs);
(MessageLoop::current() ? MessageLoop::current() : mUILoop)->
PostDelayedTask(FROM_HERE, aTask, aDelayMs);
}
virtual bool GetTouchSensitiveRegion(CSSRect* aOutRegion) override
@ -292,13 +293,12 @@ RenderFrameParent::RenderFrameParent(nsFrameLoader* aFrameLoader,
, mBackgroundColor(gfxRGBA(1, 1, 1))
, mAsyncPanZoomEnabled(false)
{
*aId = 0;
*aSuccess = false;
if (!mFrameLoader) {
return;
}
*aId = 0;
nsRefPtr<LayerManager> lm = GetFrom(mFrameLoader);
mAsyncPanZoomEnabled = lm && lm->AsyncPanZoomEnabled();
@ -414,16 +414,19 @@ RenderFrameParent::BuildLayer(nsDisplayListBuilder* aBuilder,
void
RenderFrameParent::OwnerContentChanged(nsIContent* aContent)
{
MOZ_ASSERT(mFrameLoader->GetOwnerContent() == aContent,
MOZ_ASSERT(!mFrameLoader || mFrameLoader->GetOwnerContent() == aContent,
"Don't build new map if owner is same!");
nsRefPtr<LayerManager> lm = GetFrom(mFrameLoader);
nsRefPtr<LayerManager> lm = mFrameLoader ? GetFrom(mFrameLoader) : nullptr;
// Perhaps the document containing this frame currently has no presentation?
if (lm && lm->GetBackendType() == LayersBackend::LAYERS_CLIENT) {
ClientLayerManager *clientManager =
static_cast<ClientLayerManager*>(lm.get());
clientManager->GetRemoteRenderer()->SendAdoptChild(mLayersId);
}
// The APZCTreeManager associated with this RenderFrameParent may have changed
// so reset it and let GetApzcTreeManager() pick it up again.
mApzcTreeManager = nullptr;
}
void
@ -586,7 +589,7 @@ RenderFrameParent::HitTest(const nsRect& aRect)
void
RenderFrameParent::GetTextureFactoryIdentifier(TextureFactoryIdentifier* aTextureFactoryIdentifier)
{
nsRefPtr<LayerManager> lm = GetFrom(mFrameLoader);
nsRefPtr<LayerManager> lm = mFrameLoader ? GetFrom(mFrameLoader) : nullptr;
// Perhaps the document containing this frame currently has no presentation?
if (lm && lm->GetBackendType() == LayersBackend::LAYERS_CLIENT) {
*aTextureFactoryIdentifier =

7
layout/printing/nsPrintEngine.cpp

@ -2490,7 +2490,12 @@ nsPrintEngine::DoPrint(nsPrintObject * aPO)
// temporarily creating rendering context
// which is needed to find the selection frames
// mPrintDC must have positive width and height for this call
nsRenderingContext rc(mPrt->mPrintDC->CreateRenderingContext());
// CreateRenderingContext can fail for large dimensions
nsRefPtr<gfxContext> gCtx = mPrt->mPrintDC->CreateRenderingContext();
NS_ENSURE_TRUE(gCtx, NS_ERROR_OUT_OF_MEMORY);
nsRenderingContext rc(gCtx);
// find the starting and ending page numbers
// via the selection

5
layout/reftests/bugs/1114526-1-ref.html

@ -0,0 +1,5 @@
<!DOCTYPE html>
<html>
<body>
</body>
</html>

BIN
layout/reftests/bugs/1114526-1.gif

Binary file not shown.

After

Width:  |  Height:  |  Size: 317 B

64
layout/reftests/bugs/1114526-1.html

@ -0,0 +1,64 @@
<!DOCTYPE html>
<html class="reftest-wait">
<head>
<script>
var startPaintCount = 0;
function doTest() {
startPaintCount = window.mozPaintCount;
setTimeout(check, 200);
}
var calls = 0;
function check() {
calls++;
if ((window.mozPaintCount - startPaintCount) > 2) {
finishSuccess();
return;
}
if (calls > 10) {
finishFail();
return;
}
setTimeout(check, 200);
}
function finishSuccess() {
cleanup();
document.documentElement.className = "";
}
function finishFail() {
cleanup();
document.body.appendChild(document.createTextNode("FAIL FAIL FAIL"));
document.documentElement.className = "";
}
function cleanup() {
var src = document.getElementById("src");
var dest = document.getElementById("dest");
src.parentNode.removeChild(src);
dest.parentNode.removeChild(dest);
}
</script>
<style>
div {
width: 100px;
height: 100px;
position: absolute;
}
#src {
background-image: url('1114526-1.gif');
top: -500px;
}
#dest {
background-image: -moz-element(#src);
top: 100px;
}
</style>
</head>
<body>
<div id="src"></div>
<div id="dest"></div>
<script>
window.addEventListener("MozReftestInvalidate", doTest, false);
</script>
</body>
</html>

3
layout/reftests/bugs/593243-1.html

@ -1,9 +1,10 @@
<!DOCTYPE HTML>
<html class="reftest-wait"
reftest-viewport-w="600" reftest-viewport-h="400"
reftest-scrollport-w="800" reftest-scrollport-h="1000"
reftest-displayport-w="800" reftest-displayport-h="1000"
reftest-no-sync-layers>
<head>
<meta name="viewport" content="width=600; height=400; initial-scale=1.0">
<title></title>
<script type="text/javascript">
function initialPaint() {

3
layout/reftests/bugs/593243-2.html

@ -1,9 +1,10 @@
<!DOCTYPE HTML>
<html class="reftest-wait"
reftest-viewport-w="600" reftest-viewport-h="400"
reftest-scrollport-w="800" reftest-scrollport-h="1000"
reftest-displayport-w="800" reftest-displayport-h="1000"
reftest-no-sync-layers>
<head>
<meta name="viewport" content="width=600; height=400; initial-scale=1.0">
<title></title>
<script type="text/javascript">
function initialPaint() {

15
layout/reftests/bugs/reftest.list

@ -1594,8 +1594,8 @@ skip-if(B2G||Mulet) fuzzy-if(d2d,52,1051) fuzzy-if(OSX==1008,129,1068) == 586683
== 589615-1b.html 589615-1-ref.html
== 589672-1.html 589672-1-ref.html
!= 589682-1.html 589682-1-notref.html
skip-if(!asyncPanZoom) == 593243-1.html 593243-1-ref.html # bug 593168
skip-if(!asyncPanZoom) == 593243-2.html 593243-2-ref.html # bug 593168
pref(dom.meta-viewport.enabled,true) skip-if(Android) == 593243-1.html 593243-1-ref.html # bug 593168
pref(dom.meta-viewport.enabled,true) skip-if(Android) == 593243-2.html 593243-2-ref.html # bug 593168
== 593544-1.html 593544-1-ref.html
random-if(Android) == 594333-1.html 594333-1-ref.html
fuzzy-if(B2G,1,40000) == 594624-1.html 594624-1-ref.html
@ -1755,12 +1755,12 @@ skip-if(B2G||Mulet) fuzzy-if(Android,4,400) == 815593-1.html 815593-1-ref.html #
== 816359-1.html 816359-1-ref.html
== 816458-1.html 816458-1-ref.html
== 816948-1.html 816948-1-ref.html
== 817019-1.html about:blank
random-if(Android&&AndroidVersion==15) == 817019-1.html about:blank # see bug 1192616, re-enable once we're off the pandaboards
skip-if(B2G||Mulet) == 818276-1.html 818276-1-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
fuzzy-if(asyncPan,190,510) fuzzy-if(asyncPan&&!layersGPUAccelerated,102,510) == 825999.html 825999-ref.html
== 827577-1a.html 827577-1-ref.html
== 827577-1b.html 827577-1-ref.html
== 827799-1.html about:blank
random-if(Android&&AndroidVersion==15) == 827799-1.html about:blank # see bug 1192616, re-enable once we're off the pandaboards
== 829958.html 829958-ref.html
== 836844-1.html 836844-1-ref.html
== 841192-1.html 841192-1-ref.html
@ -1840,7 +1840,7 @@ pref(browser.display.use_document_fonts,0) == 1022481-1.html 1022481-1-ref.html
== 1044198-1.html 1044198-1-ref.html
== 1049499-1.html 1049499-1-ref.html
== 1050493-1.html 1050493-1-ref.html
== 1050788-1.html about:blank
random-if(Android&&AndroidVersion==15) == 1050788-1.html about:blank # see bug 1192616, re-enable once we're off the pandaboards
== 1053035-1-flex.html 1053035-1-ref.html
test-pref(layout.css.grid.enabled,true) == 1053035-1-grid.html 1053035-1-ref.html
== 1059167-1.html 1059167-1-ref.html
@ -1852,14 +1852,15 @@ fails-if(Android) fuzzy-if(Mulet,1,5) == 1062792-1.html 1062792-1-ref.html
== 1062963-floatmanager-reflow.html 1062963-floatmanager-reflow-ref.html
test-pref(dom.webcomponents.enabled,true) == 1066554-1.html 1066554-1-ref.html
== 1069716-1.html 1069716-1-ref.html
== 1078262-1.html about:blank
random-if(Android&&AndroidVersion==15) == 1078262-1.html about:blank # see bug 1192616, re-enable once we're off the pandaboards
test-pref(layout.testing.overlay-scrollbars.always-visible,false) == 1081072-1.html 1081072-1-ref.html
== 1081185-1.html 1081185-1-ref.html
== 1097437-1.html 1097437-1-ref.html
== 1103258-1.html 1103258-1-ref.html # assertion crash test with layers culling test
== 1105137-1.html 1105137-1-ref.html
fuzzy-if(d2d,36,304) HTTP(..) == 1116480-1-fakeitalic-overflow.html 1116480-1-fakeitalic-overflow-ref.html
== 1111753-1.html about:blank
random-if(Android&&AndroidVersion==15) == 1111753-1.html about:blank # see bug 1192616, re-enable once we're off the pandaboards
== 1114526-1.html 1114526-1-ref.html
== 1119117-1a.html 1119117-1-ref.html
== 1119117-1b.html 1119117-1-ref.html
== 1120431-1.html 1120431-1-ref.html

2
layout/reftests/canvas/reftest.list

@ -8,7 +8,7 @@ skip-if(B2G||Mulet) fuzzy-if(Android&&AndroidVersion>=15,8,1000) == size-1.html
skip-if(B2G||Mulet) asserts-if(cocoaWidget,0-2) == size-change-1.html size-change-1-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
random-if(cocoaWidget) == subpixel-1.html about:blank
random-if(cocoaWidget||(Android&&AndroidVersion==15)) == subpixel-1.html about:blank # see bug 1192616, re-enable once we're off the pandaboards
!= text-ltr-left.html text-blank.html
!= text-ltr-right.html text-blank.html

2
layout/reftests/css-default/submit-button/reftest.list

@ -1,7 +1,7 @@
== default-submit-button-1.html default-submit-button-ref.html
== default-submit-button-2.html default-submit-button-ref.html
== default-submit-button-3.html default-submit-button-ref.html
== default-submit-button-4.html about:blank
random-if(Android&&AndroidVersion==15) == default-submit-button-4.html about:blank # see bug 1192616, re-enable once we're off the pandaboards
== default-submit-button-5.html default-submit-button-ref.html
== default-submit-button-6.html default-submit-button-ref.html
== default-submit-button-7.html default-submit-button-ref.html

4
layout/reftests/css-gradients/reftest.list

@ -54,8 +54,8 @@ fuzzy-if(!contentSameGfxBackendAsCanvas,3,88500) fuzzy-if(azureSkiaGL,3,89700) f
fails-if(OSX==1010) fuzzy-if(Android,4,248) == linear-zero-length-1a.html linear-zero-length-1-ref.html
fails-if(OSX==1010) fuzzy-if(Android,4,248) == linear-zero-length-1b.html linear-zero-length-1-ref.html
fails-if(OSX==1010) fuzzy-if(Android,4,248) == linear-zero-length-1c.html linear-zero-length-1-ref.html
== nostops.html about:blank
== onestop.html about:blank
random-if(Android&&AndroidVersion==15) == nostops.html about:blank # see bug 1192616, re-enable once we're off the pandaboards
random-if(Android&&AndroidVersion==15) == onestop.html about:blank # see bug 1192616, re-enable once we're off the pandaboards
fuzzy-if(!contentSameGfxBackendAsCanvas,1,5884) fuzzy-if(cocoaWidget,9,87824) fuzzy-if(azureSkiaGL,6,88024) random-if(d2d) == radial-1a.html radial-1-ref.html
fuzzy-if(!contentSameGfxBackendAsCanvas,1,5884) fuzzy-if(cocoaWidget,9,87824) fuzzy-if(azureSkiaGL,6,88024) random-if(d2d) == radial-1b.html radial-1-ref.html
fuzzy-if(!contentSameGfxBackendAsCanvas,1,5884) fuzzy-if(cocoaWidget,9,87824) fuzzy-if(azureSkiaGL,6,88024) random-if(d2d) == radial-1c.html radial-1-ref.html

16
layout/reftests/reftest-sanity/reftest.list

@ -71,8 +71,8 @@ include default-preferences-tests.list
# test that all corners are visible
!= corners-1.html corners-1-ref.html
!= corners-2.html corners-2-ref.html
!= corners-3.html corners-3-ref.html
!= corners-4.html corners-4-ref.html
skip-if(Android&&AndroidVersion==15) != corners-3.html corners-3-ref.html # see bug 1192616; reenable once we're off the pandaboards
skip-if(Android&&AndroidVersion==15) != corners-4.html corners-4-ref.html # see bug 1192616; reenable once we're off the pandaboards
# Test that the harness gives the correct page dimensions.
!= page-width-3.9in.html page-width-4in.html
@ -90,16 +90,16 @@ fails == data:text/plain,HELLO about:blank
needs-focus == data:text/plain, about:blank
# Sanity check of viewport+displayport overrides
skip-if(!browserIsRemote) != test-displayport-2.html test-displayport-ref.html # bug 593168
fuzzy-if(layersOMTC,1,1390) skip-if(!browserIsRemote) fails-if(OSX&&layersGPUAccelerated) random-if(Android&&AndroidVersion<15) random-if(B2G||B2GDT||Mulet) random-if(transparentScrollbars) == 647192-1.html 647192-1-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
pref(dom.meta-viewport.enabled,true) skip-if(!browserIsRemote) != test-displayport-2.html test-displayport-ref.html # bug 593168
skip-if(!browserIsRemote) fails-if(OSX&&layersGPUAccelerated) fuzzy-if(layersOMTC,1,1390) random-if(Android&&AndroidVersion<15) random-if(B2G||B2GDT||Mulet) random-if(transparentScrollbars) == 647192-1.html 647192-1-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(!browserIsRemote||((B2G&&browserIsRemote)||Mulet)) == 656041-1.html 656041-1-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
skip-if(!browserIsRemote||layersOMTC) == test-displayport-bg.html test-displayport-ref.html # bug 694706
pref(dom.meta-viewport.enabled,true) skip-if(!browserIsRemote||layersOMTC) == test-displayport-bg.html test-displayport-ref.html # bug 694706
# IPC Position-fixed frames/layers test
# Fixed layers are temporarily disabled (bug 656167).
#skip-if(!browserIsRemote) == test-pos-fixed.html test-pos-fixed-ref.html
#skip-if(!browserIsRemote) == test-bg-attachment-fixed.html test-bg-attachment-fixed-ref.html
skip-if(!browserIsRemote) == test-pos-fixed-transform.html test-pos-fixed-transform-ref.html
#pref(dom.meta-viewport.enabled,true) skip-if(!browserIsRemote) == test-pos-fixed.html test-pos-fixed-ref.html
#pref(dom.meta-viewport.enabled,true) skip-if(!browserIsRemote) == test-bg-attachment-fixed.html test-bg-attachment-fixed-ref.html
pref(dom.meta-viewport.enabled,true) skip-if(!browserIsRemote) == test-pos-fixed-transform.html test-pos-fixed-transform-ref.html
# reftest syntax: require-or
require-or(unrecognizedCondition,skip) script scripttest-fail.html

4
layout/reftests/reftest-sanity/test-bg-attachment-fixed-ref.html

@ -1,6 +1,6 @@
<html reftest-viewport-w="800" reftest-viewport-h="1000"
reftest-displayport-w="800" reftest-displayport-h="1000">
<html reftest-displayport-w="800" reftest-displayport-h="1000">
<head>
<meta name="viewport" content="width=800; height=1000; initial-scale=1.0">
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<style type="text/css">
body

2
layout/reftests/reftest-sanity/test-bg-attachment-fixed.html

@ -1,7 +1,7 @@
<html style="overflow:hidden"
reftest-viewport-w="800" reftest-viewport-h="1000"
reftest-displayport-w="800" reftest-displayport-h="1000">
<head>
<meta name="viewport" content="width=800; height=1000; initial-scale=1.0">
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<script>
function run() {

4
layout/reftests/reftest-sanity/test-displayport-2.html

@ -1,6 +1,6 @@
<!DOCTYPE HTML>
<html reftest-viewport-w="100" reftest-viewport-h="100"
reftest-displayport-w="200" reftest-displayport-h="200">
<html reftest-displayport-w="200" reftest-displayport-h="200">
<meta name="viewport" content="width=100; height=100; initial-scale=1.0">
<body>
<div style="position: absolute; left:0px; top:0px;width:800px; height:1000px; background:green;"></div>
</body>

4
layout/reftests/reftest-sanity/test-displayport-bg.html

@ -1,7 +1,7 @@
<!DOCTYPE HTML>
<html reftest-viewport-w="100" reftest-viewport-h="100"
reftest-displayport-w="400" reftest-displayport-h="500"
<html reftest-displayport-w="400" reftest-displayport-h="500"
reftest-async-scroll>
<meta name="viewport" content="width=100; height=100; initial-scale=1.0">
<body bgcolor=green style="position: absolute; left:0px; top:0px;width:800px; height:1000px;"></body>
</html>

4
layout/reftests/reftest-sanity/test-pos-fixed-ref.html

@ -1,6 +1,6 @@
<!DOCTYPE HTML>
<html reftest-viewport-w="200" reftest-viewport-h="100"
reftest-displayport-w="200" reftest-displayport-h="100"
<html reftest-displayport-w="200" reftest-displayport-h="100"
<meta name="viewport" content="width=200; height=100; initial-scale=1.0">
<body>
<div style="position:fixed;top:0px;width:100%;height:10px;background-color:green;"></div>
</body>

3
layout/reftests/reftest-sanity/test-pos-fixed-transform-ref.html

@ -1,5 +1,6 @@
<!DOCTYPE HTML>
<html reftest-viewport-w="800" reftest-viewport-h="1000">
<html>
<meta name="viewport" content="width=800; height=1000; initial-scale=1.0">
<body>
<div style="position: fixed; background: lightblue; top: 0; left: 0; width:100px; height:100px; -moz-transform: translate(360px,0px);"/>
</body>

4
layout/reftests/reftest-sanity/test-pos-fixed-transform.html

@ -1,6 +1,6 @@
<!DOCTYPE HTML>
<html reftest-viewport-w="800" reftest-viewport-h="1000"
reftest-displayport-w="800" reftest-displayport-h="1000">
<html reftest-displayport-w="800" reftest-displayport-h="1000">
<meta name="viewport" content="width=800; height=1000; initial-scale=1.0">
<body>
<div style="position: fixed; background: lightblue; top: 0; left: 0; width:100px; height:100px; -moz-transform: translate(360px,0px);"/>
</body>

4
layout/reftests/reftest-sanity/test-pos-fixed.html

@ -1,7 +1,7 @@
<!DOCTYPE HTML>
<html reftest-viewport-w="200" reftest-viewport-h="100"
reftest-displayport-w="200" reftest-displayport-h="100"
<html reftest-displayport-w="200" reftest-displayport-h="100"
reftest-displayport-x="0" reftest-displayport-y="10">
<meta name="viewport" content="width=200; height=100; initial-scale=1.0">
<body>
<div style="position:fixed;top:0px;width:100%;height:10px;background-color:green;">&nbsp;</div>
</body>

11
layout/tools/reftest/README.txt

@ -512,12 +512,13 @@ are 800/zoom and 1000/zoom. For best results therefore, choose zoom factors
that do not require rounding when we calculate the number of appunits per
device pixel; i.e. the zoom factor should divide 60, so 60/zoom is an integer.
Setting Viewport Size: reftest-viewport-w/h="<int>"
===================================================
Setting Scrollport Size: reftest-scrollport-w/h="<int>"
=======================================================
If either of the "reftest-viewport-w" and "reftest-viewport-h" attributes on
the root element are non-zero, sets the CSS viewport to the given size in
CSS pixels. This does not affect the size of the snapshot that is taken.
If either of the "reftest-scrollport-w" and "reftest-scrollport-h" attributes on
the root element are non-zero, sets the scroll-position-clamping scroll-port
size to the given size in CSS pixels. This does not affect the size of the
snapshot that is taken.
Setting Async Scroll Mode: reftest-async-scroll attribute
=========================================================

10
layout/tools/reftest/reftest-content.js

@ -195,11 +195,11 @@ function setupViewport(contentRootElement) {
return;
}
var vw = attrOrDefault(contentRootElement, "reftest-viewport-w", 0);
var vh = attrOrDefault(contentRootElement, "reftest-viewport-h", 0);
if (vw !== 0 || vh !== 0) {
LogInfo("Setting viewport to <w="+ vw +", h="+ vh +">");
windowUtils().setCSSViewport(vw, vh);
var sw = attrOrDefault(contentRootElement, "reftest-scrollport-w", 0);
var sh = attrOrDefault(contentRootElement, "reftest-scrollport-h", 0);
if (sw !== 0 || sh !== 0) {
LogInfo("Setting scrollport to <w=" + sw + ", h=" + sh + ">");
windowUtils().setScrollPositionClampingScrollPortSize(sw, sh);
}
// XXX support resolution when needed

3
toolkit/components/gfx/GfxSanityTest.manifest

@ -0,0 +1,3 @@
component {f3a8ca4d-4c83-456b-aee2-6a2cbf11e9bd} SanityTest.js process=main
contract @mozilla.org/sanity-test;1 {f3a8ca4d-4c83-456b-aee2-6a2cbf11e9bd} process=main
category profile-after-change SanityTest @mozilla.org/sanity-test;1 process=main

290
toolkit/components/gfx/SanityTest.js

@ -0,0 +1,290 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { utils: Cu, interfaces: Ci, classes: Cc, results: Cr } = Components;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import('resource://gre/modules/Preferences.jsm');
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
const PAGE_WIDTH=72;
const PAGE_HEIGHT=136;
const DRIVER_PREF="sanity-test.driver-version";
const DEVICE_PREF="sanity-test.device-id";
const VERSION_PREF="sanity-test.version";
const DISABLE_VIDEO_PREF="media.hardware-video-decoding.failed";
const RUNNING_PREF="sanity-test.running";
const OS_SNAPSHOT_TIMEOUT_SEC=3;
// GRAPHICS_SANITY_TEST histogram enumeration values
const TEST_PASSED=0;
const TEST_FAILED_RENDER=1;
const TEST_FAILED_VIDEO=2;
const TEST_CRASHED=3;
// GRAPHICS_SANITY_TEST_OS_SNAPSHOT histogram enumeration values
const SNAPSHOT_OK=0;
const SNAPSHOT_INCORRECT=1;
const SNAPSHOT_ERROR=2;
const SNAPSHOT_TIMEOUT=3;
function testPixel(ctx, x, y, r, g, b, a, fuzz) {
var data = ctx.getImageData(x, y, 1, 1);
if (Math.abs(data.data[0] - r) <= fuzz &&
Math.abs(data.data[1] - g) <= fuzz &&
Math.abs(data.data[2] - b) <= fuzz &&
Math.abs(data.data[3] - a) <= fuzz) {
return true;
}
return false;
}
function reportResult(val) {
try {
let histogram = Services.telemetry.getHistogramById("GRAPHICS_SANITY_TEST");
histogram.add(val);
} catch (e) {}
Preferences.set(RUNNING_PREF, false);
Services.prefs.savePrefFile(null);
}
function reportSnapshotResult(val) {
let histogram = Services.telemetry.getHistogramById("GRAPHICS_SANITY_TEST_OS_SNAPSHOT");
histogram.add(val);
}
function takeWindowSnapshot(win, ctx) {
// TODO: drawWindow reads back from the gpu's backbuffer, which won't catch issues with presenting
// the front buffer via the window manager. Ideally we'd use an OS level API for reading back
// from the desktop itself to get a more accurate test.
var flags = ctx.DRAWWINDOW_DRAW_CARET | ctx.DRAWWINDOW_DRAW_VIEW | ctx.DRAWWINDOW_USE_WIDGET_LAYERS;
ctx.drawWindow(win.ownerGlobal, 0, 0, PAGE_WIDTH, PAGE_HEIGHT, "rgb(255,255,255)", flags);
}
function takeWidgetSnapshot(win, canvas, ctx) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawWidgetAsOnScreen(win.ownerGlobal);
}
function testWidgetSnapshot(win, canvas, ctx) {
try {
takeWidgetSnapshot(win, canvas, ctx);
if (verifyVideoRendering(ctx)) {
reportSnapshotResult(SNAPSHOT_OK);
} else {
reportSnapshotResult(SNAPSHOT_INCORRECT);
}
} catch (e) {
reportSnapshotResult(SNAPSHOT_ERROR);
}
}
function setTimeout(aMs, aCallback) {
var timer = Components.classes["@mozilla.org/timer;1"]
.createInstance(Components.interfaces.nsITimer);
timer.initWithCallback(aCallback, aMs, Ci.nsITimer.TYPE_ONE_SHOT);
}
// Verify that all the 4 coloured squares of the video
// render as expected (with a tolerance of 64 to allow for
// yuv->rgb differences between platforms).
//
// The video is 64x64, and is split into quadrants of
// different colours. The top left of the video is 8,72
// and we test a pixel 10,10 into each quadrant to avoid
// blending differences at the edges.
//
// We allow massive amounts of fuzz for the colours since
// it can depend hugely on the yuv -> rgb conversion, and
// we don't want to fail unnecessarily.
function verifyVideoRendering(ctx) {
return testPixel(ctx, 18, 82, 255, 255, 255, 255, 64) &&
testPixel(ctx, 50, 82, 0, 255, 0, 255, 64) &&
testPixel(ctx, 18, 114, 0, 0, 255, 255, 64) &&
testPixel(ctx, 50, 114, 255, 0, 0, 255, 64);
}
function testCompositor(win, ctx) {
takeWindowSnapshot(win, ctx);
if (!verifyVideoRendering(ctx)) {
reportResult(TEST_FAILED_VIDEO);
Preferences.set(DISABLE_VIDEO_PREF, true);
return false;
}
reportResult(TEST_PASSED);
return true;
}
let listener = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]),
win: null,
utils: null,
canvas: null,
// State flow:
// onload -> WM_PAINT -> MozAfterPaint -> ready
// WM_PAINT -> onload -> MozAfterPaint -> ready
//
// We always wait for the low-level paint message because this is what tells
// us whether or not the OS has actually started drawing.
windowLoaded: false, // onload event has fired.
windowReady: false, // widget has received an OS-level paint request.
scheduleTest: function(win) {
this.win = win;
this.win.onload = this.onWindowLoaded.bind(this);
this.utils = this.win.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
let observerService = Cc["@mozilla.org/observer-service;1"].
getService(Components.interfaces.nsIObserverService);
observerService.addObserver(this, "widget-first-paint", false);
},
onWindowLoaded: function() {
this.canvas = this.win.document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
this.canvas.setAttribute("width", PAGE_WIDTH);
this.canvas.setAttribute("height", PAGE_HEIGHT);
this.ctx = this.canvas.getContext("2d");
// Perform the compositor backbuffer test, which currently we use for
// actually deciding whether to enable hardware media decoding.
if (!testCompositor(this.win, this.ctx)) {
this.endTest();
return;
}
// Wait to perform the OS snapshot test. Since this waits for a series of
// events to occur, we set a timeout in case nothing happens.
setTimeout(OS_SNAPSHOT_TIMEOUT_SEC * 1000, (() => {
if (this.win) {
reportSnapshotResult(SNAPSHOT_TIMEOUT);
this.endTest();
}
}));
this.windowLoaded = true;
if (this.windowReady) {
this.waitForPaintsFlushed();
}
},
// Watch for the first OS-level paint message to the window.
observe: function(aSubject, aTopic, aData) {
if (aSubject != this.win || aTopic != "widget-first-paint") {
return;
}
this.windowReady = true;
if (this.windowLoaded) {
this.waitForPaintsFlushed();
}
},
// Wait for all layout-induced paints to flush.
waitForPaintsFlushed: function() {
// If the test ended prematurely due to a timeout, just ignore the event.
if (!this.win) {
return;
}
if (this.utils.isMozAfterPaintPending) {
let paintListener = (() => {
if (this.utils && this.utils.isMozAfterPaintPending) {
return;
}
this.win.removeEventListener("MozAfterPaint", paintListener);
if (this.utils) {
// Painting is finished, we will fail the above
// isMozAfterPaintPending test now.
this.waitForPaintsFlushed();
}
});
this.win.addEventListener("MozAfterPaint", paintListener);
return;
}
testWidgetSnapshot(this.win, this.canvas, this.ctx);
this.endTest();
},
endTest: function() {
if (!this.win) {
return;
}
this.win.ownerGlobal.close();
this.win = null;
this.utils = null;
this.canvas = null;