Bug 1285942 Part 1: Make RecordedEvent::PlayEvent return a bool and null check DrawTarget creation. draft
authorBob Owen <bobowencode@gmail.com>
Mon, 18 Jul 2016 12:13:04 +0100
changeset 388956 64f7c97a051e63e9ec32deb83262f7c20f4a6808
parent 388900 0fbdcd21fad76a00328e67875c6f40dc219235f4
child 388957 5d58b6e98428fafa68cb5d976d103dbc78f66f00
push id23276
push userbobowencode@gmail.com
push dateMon, 18 Jul 2016 11:13:40 +0000
bugs1285942
milestone50.0a1
Bug 1285942 Part 1: Make RecordedEvent::PlayEvent return a bool and null check DrawTarget creation. MozReview-Commit-ID: 8tm7rjFEbw0
gfx/2d/RecordedEvent.cpp
gfx/2d/RecordedEvent.h
layout/printing/PrintTranslator.cpp
layout/printing/ipc/RemotePrintJobParent.cpp
--- a/gfx/2d/RecordedEvent.cpp
+++ b/gfx/2d/RecordedEvent.cpp
@@ -385,26 +385,34 @@ RecordedDrawingEvent::RecordToStream(ost
 }
 
 ReferencePtr
 RecordedDrawingEvent::GetObjectRef() const
 {
   return mDT;
 }
 
-void
+bool
 RecordedDrawTargetCreation::PlayEvent(Translator *aTranslator) const
 {
   RefPtr<DrawTarget> newDT =
     aTranslator->CreateDrawTarget(mRefPtr, mSize, mFormat);
 
-  if (newDT && mHasExistingData) {
+  // If we couldn't create a DrawTarget this will probably cause us to crash
+  // with nullptr later in the playback, so return false to abort.
+  if (!newDT) {
+    return false;
+  }
+
+  if (mHasExistingData) {
     Rect dataRect(0, 0, mExistingData->GetSize().width, mExistingData->GetSize().height);
     newDT->DrawSurface(mExistingData, dataRect, dataRect);
   }
+
+  return true;
 }
 
 void
 RecordedDrawTargetCreation::RecordToStream(ostream &aStream) const
 {
   WriteElement(aStream, mRefPtr);
   WriteElement(aStream, mBackendType);
   WriteElement(aStream, mSize);
@@ -450,20 +458,21 @@ RecordedDrawTargetCreation::RecordedDraw
 
 void
 RecordedDrawTargetCreation::OutputSimpleEventInfo(stringstream &aStringStream) const
 {
   aStringStream << "[" << mRefPtr << "] DrawTarget Creation (Type: " << NameFromBackend(mBackendType) << ", Size: " << mSize.width << "x" << mSize.height << ")";
 }
 
 
-void
+bool
 RecordedDrawTargetDestruction::PlayEvent(Translator *aTranslator) const
 {
   aTranslator->RemoveDrawTarget(mRefPtr);
+  return true;
 }
 
 void
 RecordedDrawTargetDestruction::RecordToStream(ostream &aStream) const
 {
   WriteElement(aStream, mRefPtr);
 }
 
@@ -474,22 +483,30 @@ RecordedDrawTargetDestruction::RecordedD
 }
 
 void
 RecordedDrawTargetDestruction::OutputSimpleEventInfo(stringstream &aStringStream) const
 {
   aStringStream << "[" << mRefPtr << "] DrawTarget Destruction";
 }
 
-void
+bool
 RecordedCreateSimilarDrawTarget::PlayEvent(Translator *aTranslator) const
 {
   RefPtr<DrawTarget> newDT =
     aTranslator->GetReferenceDrawTarget()->CreateSimilarDrawTarget(mSize, mFormat);
+
+  // If we couldn't create a DrawTarget this will probably cause us to crash
+  // with nullptr later in the playback, so return false to abort.
+  if (!newDT) {
+    return false;
+  }
+
   aTranslator->AddDrawTarget(mRefPtr, newDT);
+  return true;
 }
 
 void
 RecordedCreateSimilarDrawTarget::RecordToStream(ostream &aStream) const
 {
   WriteElement(aStream, mRefPtr);
   WriteElement(aStream, mSize);
   WriteElement(aStream, mFormat);
@@ -570,20 +587,21 @@ struct GenericPattern
     char mSurfPat[sizeof(SurfacePattern)];
   };
 
   PatternStorage *mStorage;
   Pattern *mPattern;
   Translator *mTranslator;
 };
 
-void
+bool
 RecordedFillRect::PlayEvent(Translator *aTranslator) const
 {
   aTranslator->LookupDrawTarget(mDT)->FillRect(mRect, *GenericPattern(mPattern, aTranslator), mOptions);
+  return true;
 }
 
 void
 RecordedFillRect::RecordToStream(ostream &aStream) const
 {
   RecordedDrawingEvent::RecordToStream(aStream);
   WriteElement(aStream, mRect);
   WriteElement(aStream, mOptions);
@@ -600,20 +618,21 @@ RecordedFillRect::RecordedFillRect(istre
 
 void
 RecordedFillRect::OutputSimpleEventInfo(stringstream &aStringStream) const
 {
   aStringStream << "[" << mDT << "] FillRect (" << mRect.x << ", " << mRect.y << " - " << mRect.width << " x " << mRect.height << ") ";
   OutputSimplePatternInfo(mPattern, aStringStream);
 }
 
-void
+bool
 RecordedStrokeRect::PlayEvent(Translator *aTranslator) const
 {
   aTranslator->LookupDrawTarget(mDT)->StrokeRect(mRect, *GenericPattern(mPattern, aTranslator), mStrokeOptions, mOptions);
+  return true;
 }
 
 void
 RecordedStrokeRect::RecordToStream(ostream &aStream) const
 {
   RecordedDrawingEvent::RecordToStream(aStream);
   WriteElement(aStream, mRect);
   WriteElement(aStream, mOptions);
@@ -633,20 +652,21 @@ RecordedStrokeRect::RecordedStrokeRect(i
 void
 RecordedStrokeRect::OutputSimpleEventInfo(stringstream &aStringStream) const
 {
   aStringStream << "[" << mDT << "] StrokeRect (" << mRect.x << ", " << mRect.y << " - " << mRect.width << " x " << mRect.height
                 << ") LineWidth: " << mStrokeOptions.mLineWidth << "px ";
   OutputSimplePatternInfo(mPattern, aStringStream);
 }
 
-void
+bool
 RecordedStrokeLine::PlayEvent(Translator *aTranslator) const
 {
   aTranslator->LookupDrawTarget(mDT)->StrokeLine(mBegin, mEnd, *GenericPattern(mPattern, aTranslator), mStrokeOptions, mOptions);
+  return true;
 }
 
 void
 RecordedStrokeLine::RecordToStream(ostream &aStream) const
 {
   RecordedDrawingEvent::RecordToStream(aStream);
   WriteElement(aStream, mBegin);
   WriteElement(aStream, mEnd);
@@ -668,20 +688,21 @@ RecordedStrokeLine::RecordedStrokeLine(i
 void
 RecordedStrokeLine::OutputSimpleEventInfo(stringstream &aStringStream) const
 {
   aStringStream << "[" << mDT << "] StrokeLine (" << mBegin.x << ", " << mBegin.y << " - " << mEnd.x << ", " << mEnd.y
                 << ") LineWidth: " << mStrokeOptions.mLineWidth << "px ";
   OutputSimplePatternInfo(mPattern, aStringStream);
 }
 
-void
+bool
 RecordedFill::PlayEvent(Translator *aTranslator) const
 {
   aTranslator->LookupDrawTarget(mDT)->Fill(aTranslator->LookupPath(mPath), *GenericPattern(mPattern, aTranslator), mOptions);
+  return true;
 }
 
 RecordedFill::RecordedFill(istream &aStream)
   : RecordedDrawingEvent(FILL, aStream)
 {
   ReadElement(aStream, mPath);
   ReadElement(aStream, mOptions);
   ReadPatternData(aStream, mPattern);
@@ -703,23 +724,24 @@ RecordedFill::OutputSimpleEventInfo(stri
   OutputSimplePatternInfo(mPattern, aStringStream);
 }
 
 RecordedFillGlyphs::~RecordedFillGlyphs()
 {
   delete [] mGlyphs;
 }
 
-void
+bool
 RecordedFillGlyphs::PlayEvent(Translator *aTranslator) const
 {
   GlyphBuffer buffer;
   buffer.mGlyphs = mGlyphs;
   buffer.mNumGlyphs = mNumGlyphs;
   aTranslator->LookupDrawTarget(mDT)->FillGlyphs(aTranslator->LookupScaledFont(mScaledFont), buffer, *GenericPattern(mPattern, aTranslator), mOptions);
+  return true;
 }
 
 RecordedFillGlyphs::RecordedFillGlyphs(istream &aStream)
   : RecordedDrawingEvent(FILLGLYPHS, aStream)
 {
   ReadElement(aStream, mScaledFont);
   ReadElement(aStream, mOptions);
   ReadPatternData(aStream, mPattern);
@@ -741,20 +763,21 @@ RecordedFillGlyphs::RecordToStream(ostre
 
 void
 RecordedFillGlyphs::OutputSimpleEventInfo(stringstream &aStringStream) const
 {
   aStringStream << "[" << mDT << "] FillGlyphs (" << mScaledFont << ") ";
   OutputSimplePatternInfo(mPattern, aStringStream);
 }
 
-void
+bool
 RecordedMask::PlayEvent(Translator *aTranslator) const
 {
   aTranslator->LookupDrawTarget(mDT)->Mask(*GenericPattern(mSource, aTranslator), *GenericPattern(mMask, aTranslator), mOptions);
+  return true;
 }
 
 RecordedMask::RecordedMask(istream &aStream)
   : RecordedDrawingEvent(MASK, aStream)
 {
   ReadElement(aStream, mOptions);
   ReadPatternData(aStream, mSource);
   ReadPatternData(aStream, mMask);
@@ -773,20 +796,21 @@ void
 RecordedMask::OutputSimpleEventInfo(stringstream &aStringStream) const
 {
   aStringStream << "[" << mDT << "] Mask (Source: ";
   OutputSimplePatternInfo(mSource, aStringStream);
   aStringStream << " Mask: ";
   OutputSimplePatternInfo(mMask, aStringStream);
 }
 
-void
+bool
 RecordedStroke::PlayEvent(Translator *aTranslator) const
 {
   aTranslator->LookupDrawTarget(mDT)->Stroke(aTranslator->LookupPath(mPath), *GenericPattern(mPattern, aTranslator), mStrokeOptions, mOptions);
+  return true;
 }
 
 void
 RecordedStroke::RecordToStream(ostream &aStream) const
 {
   RecordedDrawingEvent::RecordToStream(aStream);
   WriteElement(aStream, mPath);
   WriteElement(aStream, mOptions);
@@ -805,20 +829,21 @@ RecordedStroke::RecordedStroke(istream &
 
 void
 RecordedStroke::OutputSimpleEventInfo(stringstream &aStringStream) const
 {
   aStringStream << "[" << mDT << "] Stroke ("<< mPath << ") LineWidth: " << mStrokeOptions.mLineWidth << "px ";
   OutputSimplePatternInfo(mPattern, aStringStream);
 }
 
-void
+bool
 RecordedClearRect::PlayEvent(Translator *aTranslator) const
 {
   aTranslator->LookupDrawTarget(mDT)->ClearRect(mRect);
+  return true;
 }
 
 void
 RecordedClearRect::RecordToStream(ostream &aStream) const
 {
   RecordedDrawingEvent::RecordToStream(aStream);
   WriteElement(aStream, mRect);
 }
@@ -830,21 +855,22 @@ RecordedClearRect::RecordedClearRect(ist
 }
 
 void
 RecordedClearRect::OutputSimpleEventInfo(stringstream &aStringStream) const
 {
   aStringStream << "[" << mDT<< "] ClearRect (" << mRect.x << ", " << mRect.y << " - " << mRect.width << " x " << mRect.height << ") ";
 }
 
-void
+bool
 RecordedCopySurface::PlayEvent(Translator *aTranslator) const
 {
 	aTranslator->LookupDrawTarget(mDT)->CopySurface(aTranslator->LookupSourceSurface(mSourceSurface),
                                                   mSourceRect, mDest);
+  return true;
 }
 
 void
 RecordedCopySurface::RecordToStream(ostream &aStream) const
 {
   RecordedDrawingEvent::RecordToStream(aStream);
   WriteElement(aStream, mSourceSurface);
   WriteElement(aStream, mSourceRect);
@@ -860,20 +886,21 @@ RecordedCopySurface::RecordedCopySurface
 }
 
 void
 RecordedCopySurface::OutputSimpleEventInfo(stringstream &aStringStream) const
 {
   aStringStream << "[" << mDT<< "] CopySurface (" << mSourceSurface << ")";
 }
 
-void
+bool
 RecordedPushClip::PlayEvent(Translator *aTranslator) const
 {
   aTranslator->LookupDrawTarget(mDT)->PushClip(aTranslator->LookupPath(mPath));
+  return true;
 }
 
 void
 RecordedPushClip::RecordToStream(ostream &aStream) const
 {
   RecordedDrawingEvent::RecordToStream(aStream);
   WriteElement(aStream, mPath);
 }
@@ -885,20 +912,21 @@ RecordedPushClip::RecordedPushClip(istre
 }
 
 void
 RecordedPushClip::OutputSimpleEventInfo(stringstream &aStringStream) const
 {
   aStringStream << "[" << mDT << "] PushClip (" << mPath << ") ";
 }
 
-void
+bool
 RecordedPushClipRect::PlayEvent(Translator *aTranslator) const
 {
   aTranslator->LookupDrawTarget(mDT)->PushClipRect(mRect);
+  return true;
 }
 
 void
 RecordedPushClipRect::RecordToStream(ostream &aStream) const
 {
   RecordedDrawingEvent::RecordToStream(aStream);
   WriteElement(aStream, mRect);
 }
@@ -910,20 +938,21 @@ RecordedPushClipRect::RecordedPushClipRe
 }
 
 void
 RecordedPushClipRect::OutputSimpleEventInfo(stringstream &aStringStream) const
 {
   aStringStream << "[" << mDT << "] PushClipRect (" << mRect.x << ", " << mRect.y << " - " << mRect.width << " x " << mRect.height << ") ";
 }
 
-void
+bool
 RecordedPopClip::PlayEvent(Translator *aTranslator) const
 {
   aTranslator->LookupDrawTarget(mDT)->PopClip();
+  return true;
 }
 
 void
 RecordedPopClip::RecordToStream(ostream &aStream) const
 {
   RecordedDrawingEvent::RecordToStream(aStream);
 }
 
@@ -933,23 +962,24 @@ RecordedPopClip::RecordedPopClip(istream
 }
 
 void
 RecordedPopClip::OutputSimpleEventInfo(stringstream &aStringStream) const
 {
   aStringStream << "[" << mDT << "] PopClip";
 }
 
-void
+bool
 RecordedPushLayer::PlayEvent(Translator *aTranslator) const
 {
   SourceSurface* mask = mMask ? aTranslator->LookupSourceSurface(mMask)
                               : nullptr;
   aTranslator->LookupDrawTarget(mDT)->
     PushLayer(mOpaque, mOpacity, mask, mMaskTransform, mBounds, mCopyBackground);
+  return true;
 }
 
 void
 RecordedPushLayer::RecordToStream(ostream &aStream) const
 {
   RecordedDrawingEvent::RecordToStream(aStream);
   WriteElement(aStream, mOpaque);
   WriteElement(aStream, mOpacity);
@@ -972,20 +1002,21 @@ RecordedPushLayer::RecordedPushLayer(ist
 
 void
 RecordedPushLayer::OutputSimpleEventInfo(stringstream &aStringStream) const
 {
   aStringStream << "[" << mDT << "] PushPLayer (Opaque=" << mOpaque <<
     ", Opacity=" << mOpacity << ", Mask Ref=" << mMask << ") ";
 }
 
-void
+bool
 RecordedPopLayer::PlayEvent(Translator *aTranslator) const
 {
   aTranslator->LookupDrawTarget(mDT)->PopLayer();
+  return true;
 }
 
 void
 RecordedPopLayer::RecordToStream(ostream &aStream) const
 {
   RecordedDrawingEvent::RecordToStream(aStream);
 }
 
@@ -995,20 +1026,21 @@ RecordedPopLayer::RecordedPopLayer(istre
 }
 
 void
 RecordedPopLayer::OutputSimpleEventInfo(stringstream &aStringStream) const
 {
   aStringStream << "[" << mDT << "] PopLayer";
 }
 
-void
+bool
 RecordedSetTransform::PlayEvent(Translator *aTranslator) const
 {
   aTranslator->LookupDrawTarget(mDT)->SetTransform(mTransform);
+  return true;
 }
 
 void
 RecordedSetTransform::RecordToStream(ostream &aStream) const
 {
   RecordedDrawingEvent::RecordToStream(aStream);
   WriteElement(aStream, mTransform);
 }
@@ -1021,22 +1053,23 @@ RecordedSetTransform::RecordedSetTransfo
 
 void
 RecordedSetTransform::OutputSimpleEventInfo(stringstream &aStringStream) const
 {
   aStringStream << "[" << mDT << "] SetTransform [ " << mTransform._11 << " " << mTransform._12 << " ; " <<
     mTransform._21 << " " << mTransform._22 << " ; " << mTransform._31 << " " << mTransform._32 << " ]";
 }
 
-void
+bool
 RecordedDrawSurface::PlayEvent(Translator *aTranslator) const
 {
   aTranslator->LookupDrawTarget(mDT)->
     DrawSurface(aTranslator->LookupSourceSurface(mRefSource), mDest, mSource,
                 mDSOptions, mOptions);
+  return true;
 }
 
 void
 RecordedDrawSurface::RecordToStream(ostream &aStream) const
 {
   RecordedDrawingEvent::RecordToStream(aStream);
   WriteElement(aStream, mRefSource);
   WriteElement(aStream, mDest);
@@ -1056,22 +1089,23 @@ RecordedDrawSurface::RecordedDrawSurface
 }
 
 void
 RecordedDrawSurface::OutputSimpleEventInfo(stringstream &aStringStream) const
 {
   aStringStream << "[" << mDT << "] DrawSurface (" << mRefSource << ")";
 }
 
-void
+bool
 RecordedDrawFilter::PlayEvent(Translator *aTranslator) const
 {
   aTranslator->LookupDrawTarget(mDT)->
     DrawFilter(aTranslator->LookupFilterNode(mNode), mSourceRect,
                 mDestPoint, mOptions);
+  return true;
 }
 
 void
 RecordedDrawFilter::RecordToStream(ostream &aStream) const
 {
   RecordedDrawingEvent::RecordToStream(aStream);
   WriteElement(aStream, mNode);
   WriteElement(aStream, mSourceRect);
@@ -1089,22 +1123,23 @@ RecordedDrawFilter::RecordedDrawFilter(i
 }
 
 void
 RecordedDrawFilter::OutputSimpleEventInfo(stringstream &aStringStream) const
 {
   aStringStream << "[" << mDT << "] DrawFilter (" << mNode << ")";
 }
 
-void
+bool
 RecordedDrawSurfaceWithShadow::PlayEvent(Translator *aTranslator) const
 {
   aTranslator->LookupDrawTarget(mDT)->
     DrawSurfaceWithShadow(aTranslator->LookupSourceSurface(mRefSource),
                           mDest, mColor, mOffset, mSigma, mOp);
+  return true;
 }
 
 void
 RecordedDrawSurfaceWithShadow::RecordToStream(ostream &aStream) const
 {
   RecordedDrawingEvent::RecordToStream(aStream);
   WriteElement(aStream, mRefSource);
   WriteElement(aStream, mDest);
@@ -1136,17 +1171,17 @@ RecordedPathCreation::RecordedPathCreati
   : RecordedEvent(PATHCREATION), mRefPtr(aPath), mFillRule(aPath->mFillRule), mPathOps(aPath->mPathOps)
 {
 }
 
 RecordedPathCreation::~RecordedPathCreation()
 {
 }
 
-void
+bool
 RecordedPathCreation::PlayEvent(Translator *aTranslator) const
 {
   RefPtr<PathBuilder> builder = 
     aTranslator->GetReferenceDrawTarget()->CreatePathBuilder(mFillRule);
 
   for (size_t i = 0; i < mPathOps.size(); i++) {
     const PathOp &op = mPathOps[i];
     switch (op.mType) {
@@ -1165,16 +1200,17 @@ RecordedPathCreation::PlayEvent(Translat
     case PathOp::OP_CLOSE:
       builder->Close();
       break;
     }
   }
 
   RefPtr<Path> path = builder->Finish();
   aTranslator->AddPath(mRefPtr, path);
+  return true;
 }
 
 void
 RecordedPathCreation::RecordToStream(ostream &aStream) const
 {
   WriteElement(aStream, mRefPtr);
   WriteElement(aStream, uint64_t(mPathOps.size()));
   WriteElement(aStream, mFillRule);
@@ -1221,20 +1257,21 @@ RecordedPathCreation::RecordedPathCreati
 
 }
 
 void
 RecordedPathCreation::OutputSimpleEventInfo(stringstream &aStringStream) const
 {
   aStringStream << "[" << mRefPtr << "] Path created (OpCount: " << mPathOps.size() << ")";
 }
-void
+bool
 RecordedPathDestruction::PlayEvent(Translator *aTranslator) const
 {
   aTranslator->RemovePath(mRefPtr);
+  return true;
 }
 
 void
 RecordedPathDestruction::RecordToStream(ostream &aStream) const
 {
   WriteElement(aStream, mRefPtr);
 }
 
@@ -1252,22 +1289,23 @@ RecordedPathDestruction::OutputSimpleEve
 
 RecordedSourceSurfaceCreation::~RecordedSourceSurfaceCreation()
 {
   if (mDataOwned) {
     delete [] mData;
   }
 }
 
-void
+bool
 RecordedSourceSurfaceCreation::PlayEvent(Translator *aTranslator) const
 {
   RefPtr<SourceSurface> src = aTranslator->GetReferenceDrawTarget()->
     CreateSourceSurfaceFromData(mData, mSize, mSize.width * BytesPerPixel(mFormat), mFormat);
   aTranslator->AddSourceSurface(mRefPtr, src);
+  return true;
 }
 
 void
 RecordedSourceSurfaceCreation::RecordToStream(ostream &aStream) const
 {
   WriteElement(aStream, mRefPtr);
   WriteElement(aStream, mSize);
   WriteElement(aStream, mFormat);
@@ -1287,20 +1325,21 @@ RecordedSourceSurfaceCreation::RecordedS
 }
 
 void
 RecordedSourceSurfaceCreation::OutputSimpleEventInfo(stringstream &aStringStream) const
 {
   aStringStream << "[" << mRefPtr << "] SourceSurface created (Size: " << mSize.width << "x" << mSize.height << ")";
 }
 
-void
+bool
 RecordedSourceSurfaceDestruction::PlayEvent(Translator *aTranslator) const
 {
   aTranslator->RemoveSourceSurface(mRefPtr);
+  return true;
 }
 
 void
 RecordedSourceSurfaceDestruction::RecordToStream(ostream &aStream) const
 {
   WriteElement(aStream, mRefPtr);
 }
 
@@ -1315,22 +1354,23 @@ RecordedSourceSurfaceDestruction::Output
 {
   aStringStream << "[" << mRefPtr << "] SourceSurface Destroyed";
 }
 
 RecordedFilterNodeCreation::~RecordedFilterNodeCreation()
 {
 }
 
-void
+bool
 RecordedFilterNodeCreation::PlayEvent(Translator *aTranslator) const
 {
   RefPtr<FilterNode> node = aTranslator->GetReferenceDrawTarget()->
     CreateFilter(mType);
   aTranslator->AddFilterNode(mRefPtr, node);
+  return true;
 }
 
 void
 RecordedFilterNodeCreation::RecordToStream(ostream &aStream) const
 {
   WriteElement(aStream, mRefPtr);
   WriteElement(aStream, mType);
 }
@@ -1343,20 +1383,21 @@ RecordedFilterNodeCreation::RecordedFilt
 }
 
 void
 RecordedFilterNodeCreation::OutputSimpleEventInfo(stringstream &aStringStream) const
 {
   aStringStream << "[" << mRefPtr << "] FilterNode created (Type: " << int(mType) << ")";
 }
 
-void
+bool
 RecordedFilterNodeDestruction::PlayEvent(Translator *aTranslator) const
 {
   aTranslator->RemoveFilterNode(mRefPtr);
+  return true;
 }
 
 void
 RecordedFilterNodeDestruction::RecordToStream(ostream &aStream) const
 {
   WriteElement(aStream, mRefPtr);
 }
 
@@ -1374,22 +1415,23 @@ RecordedFilterNodeDestruction::OutputSim
 
 RecordedGradientStopsCreation::~RecordedGradientStopsCreation()
 {
   if (mDataOwned) {
     delete [] mStops;
   }
 }
 
-void
+bool
 RecordedGradientStopsCreation::PlayEvent(Translator *aTranslator) const
 {
   RefPtr<GradientStops> src = aTranslator->GetReferenceDrawTarget()->
     CreateGradientStops(mStops, mNumStops, mExtendMode);
   aTranslator->AddGradientStops(mRefPtr, src);
+  return true;
 }
 
 void
 RecordedGradientStopsCreation::RecordToStream(ostream &aStream) const
 {
   WriteElement(aStream, mRefPtr);
   WriteElement(aStream, mExtendMode);
   WriteElement(aStream, mNumStops);
@@ -1408,20 +1450,21 @@ RecordedGradientStopsCreation::RecordedG
 }
 
 void
 RecordedGradientStopsCreation::OutputSimpleEventInfo(stringstream &aStringStream) const
 {
   aStringStream << "[" << mRefPtr << "] GradientStops created (Stops: " << mNumStops << ")";
 }
 
-void
+bool
 RecordedGradientStopsDestruction::PlayEvent(Translator *aTranslator) const
 {
   aTranslator->RemoveGradientStops(mRefPtr);
+  return true;
 }
 
 void
 RecordedGradientStopsDestruction::RecordToStream(ostream &aStream) const
 {
   WriteElement(aStream, mRefPtr);
 }
 
@@ -1432,21 +1475,22 @@ RecordedGradientStopsDestruction::Record
 }
 
 void
 RecordedGradientStopsDestruction::OutputSimpleEventInfo(stringstream &aStringStream) const
 {
   aStringStream << "[" << mRefPtr << "] GradientStops Destroyed";
 }
 
-void
+bool
 RecordedSnapshot::PlayEvent(Translator *aTranslator) const
 {
   RefPtr<SourceSurface> src = aTranslator->LookupDrawTarget(mDT)->Snapshot();
   aTranslator->AddSourceSurface(mRefPtr, src);
+  return true;
 }
 
 void
 RecordedSnapshot::RecordToStream(ostream &aStream) const
 {
   WriteElement(aStream, mRefPtr);
   WriteElement(aStream, mDT);
 }
@@ -1464,23 +1508,24 @@ RecordedSnapshot::OutputSimpleEventInfo(
   aStringStream << "[" << mRefPtr << "] Snapshot Created (DT: " << mDT << ")";
 }
 
 RecordedFontData::~RecordedFontData()
 {
   delete[] mData;
 }
 
-void
+bool
 RecordedFontData::PlayEvent(Translator *aTranslator) const
 {
   RefPtr<NativeFontResource> fontResource =
     Factory::CreateNativeFontResource(mData, mFontDetails.size,
                                       aTranslator->GetDesiredFontType());
   aTranslator->AddNativeFontResource(mFontDetails.fontDataKey, fontResource);
+  return true;
 }
 
 void
 RecordedFontData::RecordToStream(std::ostream &aStream) const
 {
   MOZ_ASSERT(mGetFontFileDataSucceeded);
 
   WriteElement(aStream, mFontDetails.fontDataKey);
@@ -1527,33 +1572,34 @@ RecordedFontData::RecordedFontData(istre
   mData = new uint8_t[mFontDetails.size];
   aStream.read((char*)mData, mFontDetails.size);
 }
 
 RecordedFontDescriptor::~RecordedFontDescriptor()
 {
 }
 
-void
+bool
 RecordedFontDescriptor::PlayEvent(Translator *aTranslator) const
 {
   MOZ_ASSERT(mType == FontType::GDI);
 
   NativeFont nativeFont;
   nativeFont.mType = (NativeFontType)mType;
   nativeFont.mFont = (void*)&mData[0];
 
   RefPtr<ScaledFont> font =
     Factory::CreateScaledFontForNativeFont(nativeFont, mFontSize);
 
 #ifdef USE_CAIRO_SCALED_FONT
   static_cast<ScaledFontBase*>(font.get())->PopulateCairoScaledFont();
 #endif
 
   aTranslator->AddScaledFont(mRefPtr, font);
+  return true;
 }
 
 void
 RecordedFontDescriptor::RecordToStream(std::ostream &aStream) const
 {
   MOZ_ASSERT(mHasDesc);
   WriteElement(aStream, mType);
   WriteElement(aStream, mFontSize);
@@ -1583,22 +1629,23 @@ RecordedFontDescriptor::RecordedFontDesc
   ReadElement(aStream, mRefPtr);
 
   size_t size;
   ReadElement(aStream, size);
   mData.resize(size);
   aStream.read((char*)&mData[0], size);
 }
 
-void
+bool
 RecordedScaledFontCreation::PlayEvent(Translator *aTranslator) const
 {
   NativeFontResource *fontResource = aTranslator->LookupNativeFontResource(mFontDataKey);
   RefPtr<ScaledFont> scaledFont = fontResource->CreateScaledFont(mIndex, mGlyphSize);
   aTranslator->AddScaledFont(mRefPtr, scaledFont);
+  return true;
 }
 
 void
 RecordedScaledFontCreation::RecordToStream(std::ostream &aStream) const
 {
   WriteElement(aStream, mRefPtr);
   WriteElement(aStream, mFontDataKey);
   WriteElement(aStream, mIndex);
@@ -1615,20 +1662,21 @@ RecordedScaledFontCreation::RecordedScal
   : RecordedEvent(SCALEDFONTCREATION)
 {
   ReadElement(aStream, mRefPtr);
   ReadElement(aStream, mFontDataKey);
   ReadElement(aStream, mIndex);
   ReadElement(aStream, mGlyphSize);
 }
 
-void
+bool
 RecordedScaledFontDestruction::PlayEvent(Translator *aTranslator) const
 {
   aTranslator->RemoveScaledFont(mRefPtr);
+  return true;
 }
 
 void
 RecordedScaledFontDestruction::RecordToStream(ostream &aStream) const
 {
   WriteElement(aStream, mRefPtr);
 }
 
@@ -1639,23 +1687,24 @@ RecordedScaledFontDestruction::RecordedS
 }
 
 void
 RecordedScaledFontDestruction::OutputSimpleEventInfo(stringstream &aStringStream) const
 {
   aStringStream << "[" << mRefPtr << "] ScaledFont Destroyed";
 }
 
-void
+bool
 RecordedMaskSurface::PlayEvent(Translator *aTranslator) const
 {
   aTranslator->LookupDrawTarget(mDT)->
     MaskSurface(*GenericPattern(mPattern, aTranslator),
                 aTranslator->LookupSourceSurface(mRefMask),
                 mOffset, mOptions);
+  return true;
 }
 
 void
 RecordedMaskSurface::RecordToStream(ostream &aStream) const
 {
   RecordedDrawingEvent::RecordToStream(aStream);
   RecordPatternData(aStream, mPattern);
   WriteElement(aStream, mRefMask);
@@ -1681,17 +1730,17 @@ RecordedMaskSurface::OutputSimpleEventIn
 
 template<typename T>
 void
 ReplaySetAttribute(FilterNode *aNode, uint32_t aIndex, T aValue)
 {
   aNode->SetAttribute(aIndex, aValue);
 }
 
-void
+bool
 RecordedFilterNodeSetAttribute::PlayEvent(Translator *aTranslator) const
 {
 #define REPLAY_SET_ATTRIBUTE(type, argtype) \
   case ARGTYPE_##argtype: \
   ReplaySetAttribute(aTranslator->LookupFilterNode(mNode), mIndex, *(type*)&mPayload.front()); \
   break
 
   switch (mArgType) {
@@ -1710,16 +1759,18 @@ RecordedFilterNodeSetAttribute::PlayEven
     REPLAY_SET_ATTRIBUTE(Color, COLOR);
   case ARGTYPE_FLOAT_ARRAY:
     aTranslator->LookupFilterNode(mNode)->SetAttribute(
       mIndex,
       reinterpret_cast<const Float*>(&mPayload.front()),
       mPayload.size() / sizeof(Float));
     break;
   }
+
+  return true;
 }
 
 void
 RecordedFilterNodeSetAttribute::RecordToStream(ostream &aStream) const
 {
   RecordedEvent::RecordToStream(aStream);
   WriteElement(aStream, mNode);
   WriteElement(aStream, mIndex);
@@ -1741,26 +1792,28 @@ RecordedFilterNodeSetAttribute::Recorded
 }
 
 void
 RecordedFilterNodeSetAttribute::OutputSimpleEventInfo(stringstream &aStringStream) const
 {
   aStringStream << "[" << mNode << "] SetAttribute (" << mIndex << ")";
 }
 
-void
+bool
 RecordedFilterNodeSetInput::PlayEvent(Translator *aTranslator) const
 {
   if (mInputFilter) {
     aTranslator->LookupFilterNode(mNode)->SetInput(
       mIndex, aTranslator->LookupFilterNode(mInputFilter));
   } else {
     aTranslator->LookupFilterNode(mNode)->SetInput(
       mIndex, aTranslator->LookupSourceSurface(mInputSurface));
   }
+
+  return true;
 }
 
 void
 RecordedFilterNodeSetInput::RecordToStream(ostream &aStream) const
 {
   RecordedEvent::RecordToStream(aStream);
   WriteElement(aStream, mNode);
   WriteElement(aStream, mIndex);
--- a/gfx/2d/RecordedEvent.h
+++ b/gfx/2d/RecordedEvent.h
@@ -197,17 +197,25 @@ public:
     POPLAYER,
   };
   static const uint32_t kTotalEventTypes = RecordedEvent::FILTERNODESETINPUT + 1;
 
   virtual ~RecordedEvent() {}
 
   static std::string GetEventName(EventType aType);
 
-  virtual void PlayEvent(Translator *aTranslator) const {}
+  /**
+   * Play back this event using the translator. Note that derived classes should
+   * only return false when there is a fatal error, as it will probably mean the
+   * translation will abort.
+   * @param aTranslator Translator to be used for retrieving other referenced
+   *                    objects and making playback decisions.
+   * @return true unless a fatal problem has occurred and playback should abort.
+   */
+  virtual bool PlayEvent(Translator *aTranslator) const { return true; }
 
   virtual void RecordToStream(std::ostream &aStream) const {}
 
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const { }
 
   void RecordPatternData(std::ostream &aStream, const PatternStorage &aPatternStorage) const;
   void ReadPatternData(std::istream &aStream, PatternStorage &aPatternStorage) const;
   void StorePattern(PatternStorage &aDestination, const Pattern &aSource) const;
@@ -257,17 +265,17 @@ protected:
 class RecordedDrawTargetCreation : public RecordedEvent {
 public:
   RecordedDrawTargetCreation(ReferencePtr aRefPtr, BackendType aType, const IntSize &aSize, SurfaceFormat aFormat,
                              bool aHasExistingData = false, SourceSurface *aExistingData = nullptr)
     : RecordedEvent(DRAWTARGETCREATION), mRefPtr(aRefPtr), mBackendType(aType), mSize(aSize), mFormat(aFormat)
     , mHasExistingData(aHasExistingData), mExistingData(aExistingData)
   {}
 
-  virtual void PlayEvent(Translator *aTranslator) const;
+  virtual bool PlayEvent(Translator *aTranslator) const;
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
 
   virtual std::string GetName() const { return "DrawTarget Creation"; }
   virtual ReferencePtr GetObjectRef() const { return mRefPtr; }
 
   ReferencePtr mRefPtr;
@@ -284,17 +292,17 @@ private:
 };
 
 class RecordedDrawTargetDestruction : public RecordedEvent {
 public:
   MOZ_IMPLICIT RecordedDrawTargetDestruction(ReferencePtr aRefPtr)
     : RecordedEvent(DRAWTARGETDESTRUCTION), mRefPtr(aRefPtr)
   {}
 
-  virtual void PlayEvent(Translator *aTranslator) const;
+  virtual bool PlayEvent(Translator *aTranslator) const;
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
 
   virtual std::string GetName() const { return "DrawTarget Destruction"; }
   virtual ReferencePtr GetObjectRef() const { return mRefPtr; }
 
   ReferencePtr mRefPtr;
@@ -311,17 +319,17 @@ class RecordedCreateSimilarDrawTarget : 
 public:
   RecordedCreateSimilarDrawTarget(ReferencePtr aRefPtr, const IntSize &aSize,
                                   SurfaceFormat aFormat)
     : RecordedEvent(CREATESIMILARDRAWTARGET)
     , mRefPtr(aRefPtr) , mSize(aSize), mFormat(aFormat)
   {
   }
 
-  virtual void PlayEvent(Translator *aTranslator) const;
+  virtual bool PlayEvent(Translator *aTranslator) const;
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
 
   virtual std::string GetName() const { return "CreateSimilarDrawTarget"; }
   virtual ReferencePtr GetObjectRef() const { return mRefPtr; }
 
   ReferencePtr mRefPtr;
@@ -337,17 +345,17 @@ private:
 class RecordedFillRect : public RecordedDrawingEvent {
 public:
   RecordedFillRect(DrawTarget *aDT, const Rect &aRect, const Pattern &aPattern, const DrawOptions &aOptions)
     : RecordedDrawingEvent(FILLRECT, aDT), mRect(aRect), mOptions(aOptions)
   {
     StorePattern(mPattern, aPattern);
   }
 
-  virtual void PlayEvent(Translator *aTranslator) const;
+  virtual bool PlayEvent(Translator *aTranslator) const;
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
 
   virtual std::string GetName() const { return "FillRect"; }
 private:
   friend class RecordedEvent;
 
@@ -363,17 +371,17 @@ public:
   RecordedStrokeRect(DrawTarget *aDT, const Rect &aRect, const Pattern &aPattern,
                      const StrokeOptions &aStrokeOptions, const DrawOptions &aOptions)
     : RecordedDrawingEvent(STROKERECT, aDT), mRect(aRect),
       mStrokeOptions(aStrokeOptions), mOptions(aOptions)
   {
     StorePattern(mPattern, aPattern);
   }
 
-  virtual void PlayEvent(Translator *aTranslator) const;
+  virtual bool PlayEvent(Translator *aTranslator) const;
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
 
   virtual std::string GetName() const { return "StrokeRect"; }
 private:
   friend class RecordedEvent;
 
@@ -391,17 +399,17 @@ public:
                      const Pattern &aPattern, const StrokeOptions &aStrokeOptions,
                      const DrawOptions &aOptions)
     : RecordedDrawingEvent(STROKELINE, aDT), mBegin(aBegin), mEnd(aEnd),
       mStrokeOptions(aStrokeOptions), mOptions(aOptions)
   {
     StorePattern(mPattern, aPattern);
   }
 
-  virtual void PlayEvent(Translator *aTranslator) const;
+  virtual bool PlayEvent(Translator *aTranslator) const;
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
 
   virtual std::string GetName() const { return "StrokeLine"; }
 private:
   friend class RecordedEvent;
 
@@ -417,17 +425,17 @@ private:
 class RecordedFill : public RecordedDrawingEvent {
 public:
   RecordedFill(DrawTarget *aDT, ReferencePtr aPath, const Pattern &aPattern, const DrawOptions &aOptions)
     : RecordedDrawingEvent(FILL, aDT), mPath(aPath), mOptions(aOptions)
   {
     StorePattern(mPattern, aPattern);
   }
 
-  virtual void PlayEvent(Translator *aTranslator) const;
+  virtual bool PlayEvent(Translator *aTranslator) const;
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
 
   virtual std::string GetName() const { return "Fill"; }
 private:
   friend class RecordedEvent;
 
@@ -446,17 +454,17 @@ public:
   {
     StorePattern(mPattern, aPattern);
     mNumGlyphs = aNumGlyphs;
     mGlyphs = new Glyph[aNumGlyphs];
     memcpy(mGlyphs, aGlyphs, sizeof(Glyph) * aNumGlyphs);
   }
   virtual ~RecordedFillGlyphs();
 
-  virtual void PlayEvent(Translator *aTranslator) const;
+  virtual bool PlayEvent(Translator *aTranslator) const;
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
 
   virtual std::string GetName() const { return "FillGlyphs"; }
 private:
   friend class RecordedEvent;
 
@@ -473,17 +481,17 @@ class RecordedMask : public RecordedDraw
 public:
   RecordedMask(DrawTarget *aDT, const Pattern &aSource, const Pattern &aMask, const DrawOptions &aOptions)
     : RecordedDrawingEvent(MASK, aDT), mOptions(aOptions)
   {
     StorePattern(mSource, aSource);
     StorePattern(mMask, aMask);
   }
 
-  virtual void PlayEvent(Translator *aTranslator) const;
+  virtual bool PlayEvent(Translator *aTranslator) const;
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
 
   virtual std::string GetName() const { return "Mask"; }
 private:
   friend class RecordedEvent;
 
@@ -499,17 +507,17 @@ public:
   RecordedStroke(DrawTarget *aDT, ReferencePtr aPath, const Pattern &aPattern,
                      const StrokeOptions &aStrokeOptions, const DrawOptions &aOptions)
     : RecordedDrawingEvent(STROKE, aDT), mPath(aPath),
       mStrokeOptions(aStrokeOptions), mOptions(aOptions)
   {
     StorePattern(mPattern, aPattern);
   }
 
-  virtual void PlayEvent(Translator *aTranslator) const;
+  virtual bool PlayEvent(Translator *aTranslator) const;
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
 
   virtual std::string GetName() const { return "Stroke"; }
 private:
   friend class RecordedEvent;
 
@@ -523,17 +531,17 @@ private:
 
 class RecordedClearRect : public RecordedDrawingEvent {
 public:
   RecordedClearRect(DrawTarget *aDT, const Rect &aRect)
     : RecordedDrawingEvent(CLEARRECT, aDT), mRect(aRect)
   {
   }
 
-  virtual void PlayEvent(Translator *aTranslator) const;
+  virtual bool PlayEvent(Translator *aTranslator) const;
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
 
   virtual std::string GetName() const { return "ClearRect"; }
 private:
   friend class RecordedEvent;
 
@@ -546,17 +554,17 @@ class RecordedCopySurface : public Recor
 public:
   RecordedCopySurface(DrawTarget *aDT, ReferencePtr aSourceSurface,
                       const IntRect &aSourceRect, const IntPoint &aDest)
     : RecordedDrawingEvent(COPYSURFACE, aDT), mSourceSurface(aSourceSurface),
 	  mSourceRect(aSourceRect), mDest(aDest)
   {
   }
 
-  virtual void PlayEvent(Translator *aTranslator) const;
+  virtual bool PlayEvent(Translator *aTranslator) const;
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
 
   virtual std::string GetName() const { return "CopySurface"; }
 private:
   friend class RecordedEvent;
 
@@ -569,17 +577,17 @@ private:
 
 class RecordedPushClip : public RecordedDrawingEvent {
 public:
   RecordedPushClip(DrawTarget *aDT, ReferencePtr aPath)
     : RecordedDrawingEvent(PUSHCLIP, aDT), mPath(aPath)
   {
   }
 
-  virtual void PlayEvent(Translator *aTranslator) const;
+  virtual bool PlayEvent(Translator *aTranslator) const;
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
 
   virtual std::string GetName() const { return "PushClip"; }
 private:
   friend class RecordedEvent;
 
@@ -590,17 +598,17 @@ private:
 
 class RecordedPushClipRect : public RecordedDrawingEvent {
 public:
   RecordedPushClipRect(DrawTarget *aDT, const Rect &aRect)
     : RecordedDrawingEvent(PUSHCLIPRECT, aDT), mRect(aRect)
   {
   }
 
-  virtual void PlayEvent(Translator *aTranslator) const;
+  virtual bool PlayEvent(Translator *aTranslator) const;
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
 
   virtual std::string GetName() const { return "PushClipRect"; }
 private:
   friend class RecordedEvent;
 
@@ -610,17 +618,17 @@ private:
 };
 
 class RecordedPopClip : public RecordedDrawingEvent {
 public:
   MOZ_IMPLICIT RecordedPopClip(DrawTarget *aDT)
     : RecordedDrawingEvent(POPCLIP, aDT)
   {}
 
-  virtual void PlayEvent(Translator *aTranslator) const;
+  virtual bool PlayEvent(Translator *aTranslator) const;
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
 
   virtual std::string GetName() const { return "PopClip"; }
 private:
   friend class RecordedEvent;
 
@@ -633,17 +641,17 @@ public:
                     SourceSurface* aMask, const Matrix& aMaskTransform,
                     const IntRect& aBounds, bool aCopyBackground)
     : RecordedDrawingEvent(PUSHLAYER, aDT), mOpaque(aOpaque)
     , mOpacity(aOpacity), mMask(aMask), mMaskTransform(aMaskTransform)
     , mBounds(aBounds), mCopyBackground(aCopyBackground)
   {
   }
 
-  virtual void PlayEvent(Translator *aTranslator) const;
+  virtual bool PlayEvent(Translator *aTranslator) const;
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
 
   virtual std::string GetName() const { return "PushLayer"; }
 private:
   friend class RecordedEvent;
 
@@ -659,17 +667,17 @@ private:
 
 class RecordedPopLayer : public RecordedDrawingEvent {
 public:
   MOZ_IMPLICIT RecordedPopLayer(DrawTarget* aDT)
     : RecordedDrawingEvent(POPLAYER, aDT)
   {
   }
 
-  virtual void PlayEvent(Translator *aTranslator) const;
+  virtual bool PlayEvent(Translator *aTranslator) const;
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
 
   virtual std::string GetName() const { return "PopLayer"; }
 private:
   friend class RecordedEvent;
 
@@ -678,17 +686,17 @@ private:
 
 class RecordedSetTransform : public RecordedDrawingEvent {
 public:
   RecordedSetTransform(DrawTarget *aDT, const Matrix &aTransform)
     : RecordedDrawingEvent(SETTRANSFORM, aDT), mTransform(aTransform)
   {
   }
 
-  virtual void PlayEvent(Translator *aTranslator) const;
+  virtual bool PlayEvent(Translator *aTranslator) const;
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
   
   virtual std::string GetName() const { return "SetTransform"; }
 private:
   friend class RecordedEvent;
 
@@ -702,17 +710,17 @@ public:
   RecordedDrawSurface(DrawTarget *aDT, ReferencePtr aRefSource, const Rect &aDest,
                       const Rect &aSource, const DrawSurfaceOptions &aDSOptions,
                       const DrawOptions &aOptions)
     : RecordedDrawingEvent(DRAWSURFACE, aDT), mRefSource(aRefSource), mDest(aDest)
     , mSource(aSource), mDSOptions(aDSOptions), mOptions(aOptions)
   {
   }
 
-  virtual void PlayEvent(Translator *aTranslator) const;
+  virtual bool PlayEvent(Translator *aTranslator) const;
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
   
   virtual std::string GetName() const { return "DrawSurface"; }
 private:
   friend class RecordedEvent;
 
@@ -730,17 +738,17 @@ public:
   RecordedDrawSurfaceWithShadow(DrawTarget *aDT, ReferencePtr aRefSource, const Point &aDest,
                                 const Color &aColor, const Point &aOffset,
                                 Float aSigma, CompositionOp aOp)
     : RecordedDrawingEvent(DRAWSURFACEWITHSHADOW, aDT), mRefSource(aRefSource), mDest(aDest)
     , mColor(aColor), mOffset(aOffset), mSigma(aSigma), mOp(aOp)
   {
   }
 
-  virtual void PlayEvent(Translator *aTranslator) const;
+  virtual bool PlayEvent(Translator *aTranslator) const;
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
   
   virtual std::string GetName() const { return "DrawSurfaceWithShadow"; }
 private:
   friend class RecordedEvent;
 
@@ -760,17 +768,17 @@ public:
                      const Rect &aSourceRect,
                      const Point &aDestPoint,
                      const DrawOptions &aOptions)
     : RecordedDrawingEvent(DRAWFILTER, aDT), mNode(aNode), mSourceRect(aSourceRect)
     , mDestPoint(aDestPoint), mOptions(aOptions)
   {
   }
 
-  virtual void PlayEvent(Translator *aTranslator) const;
+  virtual bool PlayEvent(Translator *aTranslator) const;
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
 
   virtual std::string GetName() const { return "DrawFilter"; }
 private:
   friend class RecordedEvent;
 
@@ -782,17 +790,17 @@ private:
   DrawOptions mOptions;
 };
 
 class RecordedPathCreation : public RecordedEvent {
 public:
   MOZ_IMPLICIT RecordedPathCreation(PathRecording *aPath);
   ~RecordedPathCreation();
   
-  virtual void PlayEvent(Translator *aTranslator) const;
+  virtual bool PlayEvent(Translator *aTranslator) const;
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
   
   virtual std::string GetName() const { return "Path Creation"; }
   virtual ReferencePtr GetObjectRef() const { return mRefPtr; }
 private:
   friend class RecordedEvent;
@@ -806,17 +814,17 @@ private:
 
 class RecordedPathDestruction : public RecordedEvent {
 public:
   MOZ_IMPLICIT RecordedPathDestruction(PathRecording *aPath)
     : RecordedEvent(PATHDESTRUCTION), mRefPtr(aPath)
   {
   }
   
-  virtual void PlayEvent(Translator *aTranslator) const;
+  virtual bool PlayEvent(Translator *aTranslator) const;
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
   
   virtual std::string GetName() const { return "Path Destruction"; }
   virtual ReferencePtr GetObjectRef() const { return mRefPtr; }
 private:
   friend class RecordedEvent;
@@ -832,17 +840,17 @@ public:
                                 const IntSize &aSize, SurfaceFormat aFormat)
     : RecordedEvent(SOURCESURFACECREATION), mRefPtr(aRefPtr), mData(aData)
     , mStride(aStride), mSize(aSize), mFormat(aFormat), mDataOwned(false)
   {
   }
 
   ~RecordedSourceSurfaceCreation();
 
-  virtual void PlayEvent(Translator *aTranslator) const;
+  virtual bool PlayEvent(Translator *aTranslator) const;
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
   
   virtual std::string GetName() const { return "SourceSurface Creation"; }
   virtual ReferencePtr GetObjectRef() const { return mRefPtr; }
 private:
   friend class RecordedEvent;
@@ -859,17 +867,17 @@ private:
 
 class RecordedSourceSurfaceDestruction : public RecordedEvent {
 public:
   MOZ_IMPLICIT RecordedSourceSurfaceDestruction(ReferencePtr aRefPtr)
     : RecordedEvent(SOURCESURFACEDESTRUCTION), mRefPtr(aRefPtr)
   {
   }
 
-  virtual void PlayEvent(Translator *aTranslator) const;
+  virtual bool PlayEvent(Translator *aTranslator) const;
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
   
   virtual std::string GetName() const { return "SourceSurface Destruction"; }
   virtual ReferencePtr GetObjectRef() const { return mRefPtr; }
 private:
   friend class RecordedEvent;
@@ -883,17 +891,17 @@ class RecordedFilterNodeCreation : publi
 public:
   RecordedFilterNodeCreation(ReferencePtr aRefPtr, FilterType aType)
     : RecordedEvent(FILTERNODECREATION), mRefPtr(aRefPtr), mType(aType)
   {
   }
 
   ~RecordedFilterNodeCreation();
 
-  virtual void PlayEvent(Translator *aTranslator) const;
+  virtual bool PlayEvent(Translator *aTranslator) const;
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
 
   virtual std::string GetName() const { return "FilterNode Creation"; }
   virtual ReferencePtr GetObjectRef() const { return mRefPtr; }
 private:
   friend class RecordedEvent;
@@ -906,17 +914,17 @@ private:
 
 class RecordedFilterNodeDestruction : public RecordedEvent {
 public:
   MOZ_IMPLICIT RecordedFilterNodeDestruction(ReferencePtr aRefPtr)
     : RecordedEvent(FILTERNODEDESTRUCTION), mRefPtr(aRefPtr)
   {
   }
 
-  virtual void PlayEvent(Translator *aTranslator) const;
+  virtual bool PlayEvent(Translator *aTranslator) const;
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
 
   virtual std::string GetName() const { return "FilterNode Destruction"; }
   virtual ReferencePtr GetObjectRef() const { return mRefPtr; }
 private:
   friend class RecordedEvent;
@@ -932,17 +940,17 @@ public:
                                 uint32_t aNumStops, ExtendMode aExtendMode)
     : RecordedEvent(GRADIENTSTOPSCREATION), mRefPtr(aRefPtr), mStops(aStops)
     , mNumStops(aNumStops), mExtendMode(aExtendMode), mDataOwned(false)
   {
   }
 
   ~RecordedGradientStopsCreation();
 
-  virtual void PlayEvent(Translator *aTranslator) const;
+  virtual bool PlayEvent(Translator *aTranslator) const;
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
   
   virtual std::string GetName() const { return "GradientStops Creation"; }
   virtual ReferencePtr GetObjectRef() const { return mRefPtr; }
 private:
   friend class RecordedEvent;
@@ -958,17 +966,17 @@ private:
 
 class RecordedGradientStopsDestruction : public RecordedEvent {
 public:
   MOZ_IMPLICIT RecordedGradientStopsDestruction(ReferencePtr aRefPtr)
     : RecordedEvent(GRADIENTSTOPSDESTRUCTION), mRefPtr(aRefPtr)
   {
   }
 
-  virtual void PlayEvent(Translator *aTranslator) const;
+  virtual bool PlayEvent(Translator *aTranslator) const;
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
   
   virtual std::string GetName() const { return "GradientStops Destruction"; }
   virtual ReferencePtr GetObjectRef() const { return mRefPtr; }
 private:
   friend class RecordedEvent;
@@ -980,17 +988,17 @@ private:
 
 class RecordedSnapshot : public RecordedEvent {
 public:
   RecordedSnapshot(ReferencePtr aRefPtr, DrawTarget *aDT)
     : RecordedEvent(SNAPSHOT), mRefPtr(aRefPtr), mDT(aDT)
   {
   }
 
-  virtual void PlayEvent(Translator *aTranslator) const;
+  virtual bool PlayEvent(Translator *aTranslator) const;
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
   
   virtual std::string GetName() const { return "Snapshot"; }
   virtual ReferencePtr GetObjectRef() const { return mRefPtr; }
 private:
   friend class RecordedEvent;
@@ -1014,17 +1022,17 @@ public:
   explicit RecordedFontData(ScaledFont *aScaledFont)
     : RecordedEvent(FONTDATA), mData(nullptr)
   {
     mGetFontFileDataSucceeded = aScaledFont->GetFontFileData(&FontDataProc, this);
   }
 
   ~RecordedFontData();
 
-  virtual void PlayEvent(Translator *aTranslator) const;
+  virtual bool PlayEvent(Translator *aTranslator) const;
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
 
   virtual std::string GetName() const { return "Font Data"; }
   virtual ReferencePtr GetObjectRef() const { return nullptr; };
 
   void SetFontData(const uint8_t *aData, uint32_t aSize, uint32_t aIndex,
@@ -1060,17 +1068,17 @@ public:
   {
     mHasDesc = aScaledFont->GetFontDescriptor(FontDescCb, this);
   }
 
   ~RecordedFontDescriptor();
 
   bool IsValid() const { return mHasDesc; }
 
-  virtual void PlayEvent(Translator *aTranslator) const;
+  virtual bool PlayEvent(Translator *aTranslator) const;
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
 
   virtual std::string GetName() const { return "Font Desc"; }
   virtual ReferencePtr GetObjectRef() const { return mRefPtr; }
 
 private:
@@ -1094,17 +1102,17 @@ public:
   RecordedScaledFontCreation(ReferencePtr aRefPtr,
                              RecordedFontDetails aFontDetails)
     : RecordedEvent(SCALEDFONTCREATION), mRefPtr(aRefPtr)
     , mFontDataKey(aFontDetails.fontDataKey)
     , mGlyphSize(aFontDetails.glyphSize) , mIndex(aFontDetails.index)
   {
   }
 
-  virtual void PlayEvent(Translator *aTranslator) const;
+  virtual bool PlayEvent(Translator *aTranslator) const;
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
   
   virtual std::string GetName() const { return "ScaledFont Creation"; }
   virtual ReferencePtr GetObjectRef() const { return mRefPtr; }
 
 private:
@@ -1120,17 +1128,17 @@ private:
 
 class RecordedScaledFontDestruction : public RecordedEvent {
 public:
   MOZ_IMPLICIT RecordedScaledFontDestruction(ReferencePtr aRefPtr)
     : RecordedEvent(SCALEDFONTDESTRUCTION), mRefPtr(aRefPtr)
   {
   }
 
-  virtual void PlayEvent(Translator *aTranslator) const;
+  virtual bool PlayEvent(Translator *aTranslator) const;
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
   
   virtual std::string GetName() const { return "ScaledFont Destruction"; }
   virtual ReferencePtr GetObjectRef() const { return mRefPtr; }
 private:
   friend class RecordedEvent;
@@ -1145,17 +1153,17 @@ public:
   RecordedMaskSurface(DrawTarget *aDT, const Pattern &aPattern, ReferencePtr aRefMask,
                       const Point &aOffset, const DrawOptions &aOptions)
     : RecordedDrawingEvent(MASKSURFACE, aDT), mRefMask(aRefMask), mOffset(aOffset)
     , mOptions(aOptions)
   {
     StorePattern(mPattern, aPattern);
   }
 
-  virtual void PlayEvent(Translator *aTranslator) const;
+  virtual bool PlayEvent(Translator *aTranslator) const;
 
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
   
   virtual std::string GetName() const { return "MaskSurface"; }
 private:
   friend class RecordedEvent;
 
@@ -1197,17 +1205,17 @@ public:
 
   RecordedFilterNodeSetAttribute(FilterNode *aNode, uint32_t aIndex, const Float *aFloat, uint32_t aSize)
     : RecordedEvent(FILTERNODESETATTRIBUTE), mNode(aNode), mIndex(aIndex), mArgType(ARGTYPE_FLOAT_ARRAY)
   {
     mPayload.resize(sizeof(Float) * aSize);
     memcpy(&mPayload.front(), aFloat, sizeof(Float) * aSize);
   }
 
-  virtual void PlayEvent(Translator *aTranslator) const;
+  virtual bool PlayEvent(Translator *aTranslator) const;
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
 
   virtual std::string GetName() const { return "SetAttribute"; }
 
   virtual ReferencePtr GetObjectRef() const { return mNode; }
 
 private:
@@ -1232,17 +1240,17 @@ public:
   }
 
   RecordedFilterNodeSetInput(FilterNode *aNode, uint32_t aIndex, SourceSurface *aInputSurface)
     : RecordedEvent(FILTERNODESETINPUT), mNode(aNode), mIndex(aIndex)
     , mInputFilter(nullptr), mInputSurface(aInputSurface)
   {
   }
 
-  virtual void PlayEvent(Translator *aTranslator) const;
+  virtual bool PlayEvent(Translator *aTranslator) const;
   virtual void RecordToStream(std::ostream &aStream) const;
   virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const;
 
   virtual std::string GetName() const { return "SetInput"; }
 
   virtual ReferencePtr GetObjectRef() const { return mNode; }
 
 private:
--- a/layout/printing/PrintTranslator.cpp
+++ b/layout/printing/PrintTranslator.cpp
@@ -52,17 +52,20 @@ PrintTranslator::TranslateRecording(std:
       RecordedEvent::LoadEventFromStream(aRecording,
       static_cast<RecordedEvent::EventType>(eventType)));
 
     // Make sure that the whole event was read from the stream successfully.
     if (!aRecording.good() || !recordedEvent) {
       return false;
     }
 
-    recordedEvent->PlayEvent(this);
+    if (!recordedEvent->PlayEvent(this)) {
+      return false;
+    }
+
     ReadElement(aRecording, eventType);
   }
 
   return true;
 }
 
 already_AddRefed<DrawTarget>
 PrintTranslator::CreateDrawTarget(ReferencePtr aRefPtr,
@@ -94,9 +97,9 @@ PrintTranslator::GetDesiredFontType()
     case BackendType::COREGRAPHICS_ACCELERATED:
       return FontType::COREGRAPHICS;
     default:
       return FontType::CAIRO;
   }
 }
 
 } // namespace layout
-} // namespace mozilla
\ No newline at end of file
+} // namespace mozilla
--- a/layout/printing/ipc/RemotePrintJobParent.cpp
+++ b/layout/printing/ipc/RemotePrintJobParent.cpp
@@ -107,17 +107,19 @@ RemotePrintJobParent::PrintPage(const Sh
 
   nsresult rv = mPrintDeviceContext->BeginPage();
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   std::istringstream recording(std::string(aStoredPage.get<char>(),
                                            aStoredPage.Size<char>()));
-  mPrintTranslator->TranslateRecording(recording);
+  if (!mPrintTranslator->TranslateRecording(recording)) {
+    return NS_ERROR_FAILURE;
+  }
 
   rv = mPrintDeviceContext->EndPage();
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   return NS_OK;
 }