image/VectorImage.h
author Alex Gaynor <agaynor@mozilla.com>
Mon, 27 Nov 2017 14:37:34 -0600
changeset 403385 bcc0a91dd43feae18d4bf04d7db3d146035aa416
parent 396187 4e2cf0afd644cc0f2dfb0f6def3f1c1d25a19d27
child 421522 7597bbcc9d66111326aa69048ad5847bdc7497f2
permissions -rw-r--r--
Bug 1407693 - Part 2 - when a child process crashes, write extra annotation data to a pre-opened file descriptor instead of creating a new file; r=gsvelto,rbarker This removes the need for the content process to have permissions to create new files on macOS, allowing more aggressive sandboxing. MozReview-Commit-ID: 8agL5jwxDSL

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef mozilla_image_VectorImage_h
#define mozilla_image_VectorImage_h

#include "Image.h"
#include "nsIStreamListener.h"
#include "mozilla/MemoryReporting.h"

class nsIRequest;
class gfxDrawable;

namespace mozilla {
namespace image {

struct SVGDrawingParameters;
class  SVGDocumentWrapper;
class  SVGRootRenderingObserver;
class  SVGLoadEventListener;
class  SVGParseCompleteListener;

class VectorImage final : public ImageResource,
                          public nsIStreamListener
{
public:
  NS_DECL_ISUPPORTS
  NS_DECL_NSIREQUESTOBSERVER
  NS_DECL_NSISTREAMLISTENER
  NS_DECL_IMGICONTAINER

  // (no public constructor - use ImageFactory)

  // Methods inherited from Image
  nsresult GetNativeSizes(nsTArray<gfx::IntSize>& aNativeSizes) const override;
  size_t GetNativeSizesLength() const override;
  virtual size_t SizeOfSourceWithComputedFallback(SizeOfState& aState)
    const override;
  virtual void CollectSizeOfSurfaces(nsTArray<SurfaceMemoryCounter>& aCounters,
                                     MallocSizeOf aMallocSizeOf) const override;

  virtual nsresult OnImageDataAvailable(nsIRequest* aRequest,
                                        nsISupports* aContext,
                                        nsIInputStream* aInStr,
                                        uint64_t aSourceOffset,
                                        uint32_t aCount) override;
  virtual nsresult OnImageDataComplete(nsIRequest* aRequest,
                                       nsISupports* aContext,
                                       nsresult aResult,
                                       bool aLastPart) override;

  virtual void OnSurfaceDiscarded(const SurfaceKey& aSurfaceKey) override;

  /**
   * Callback for SVGRootRenderingObserver.
   *
   * This just sets a dirty flag that we check in VectorImage::RequestRefresh,
   * which is called under the ticks of the refresh driver of any observing
   * documents that we may have. Only then (after all animations in this image
   * have been updated) do we send out "frame changed" notifications,
   */
  void InvalidateObserversOnNextRefreshDriverTick();

  // Callback for SVGParseCompleteListener.
  void OnSVGDocumentParsed();

  // Callbacks for SVGLoadEventListener.
  void OnSVGDocumentLoaded();
  void OnSVGDocumentError();

  virtual void ReportUseCounters() override;

protected:
  explicit VectorImage(ImageURL* aURI = nullptr);
  virtual ~VectorImage();

  virtual nsresult StartAnimation() override;
  virtual nsresult StopAnimation() override;
  virtual bool     ShouldAnimate() override;

private:
  Tuple<ImgDrawResult, IntSize, RefPtr<SourceSurface>>
    GetFrameInternal(const IntSize& aSize,
                     const Maybe<SVGImageContext>& aSVGContext,
                     uint32_t aWhichFrame,
                     uint32_t aFlags) override;

  IntSize GetImageContainerSize(layers::LayerManager* aManager,
                                const IntSize& aSize,
                                uint32_t aFlags) override;

  /// Attempt to find a matching cached surface in the SurfaceCache.
  already_AddRefed<SourceSurface>
    LookupCachedSurface(const IntSize& aSize,
                        const Maybe<SVGImageContext>& aSVGContext,
                        uint32_t aFlags);

  bool MaybeRestrictSVGContext(Maybe<SVGImageContext>& aNewSVGContext,
                               const Maybe<SVGImageContext>& aSVGContext,
                               uint32_t aFlags);

  /// Create a gfxDrawable which callbacks into the SVG document.
  already_AddRefed<gfxDrawable>
    CreateSVGDrawable(const SVGDrawingParameters& aParams);

  /// Rasterize the SVG into a surface. aWillCache will be set to whether or
  /// not the new surface was put into the cache.
  already_AddRefed<SourceSurface>
    CreateSurface(const SVGDrawingParameters& aParams,
                  gfxDrawable* aSVGDrawable,
                  bool& aWillCache);

  /// Send a frame complete notification if appropriate. Must be called only
  /// after all drawing has been completed.
  void SendFrameComplete(bool aDidCache, uint32_t aFlags);

  void Show(gfxDrawable* aDrawable, const SVGDrawingParameters& aParams);

  nsresult Init(const char* aMimeType, uint32_t aFlags);

  /**
   * In catastrophic circumstances like a GPU driver crash, we may lose our
   * surfaces even if they're locked. RecoverFromLossOfSurfaces discards all
   * existing surfaces, allowing us to recover.
   */
  void RecoverFromLossOfSurfaces();

  void CancelAllListeners();
  void SendInvalidationNotifications();

  RefPtr<SVGDocumentWrapper>       mSVGDocumentWrapper;
  RefPtr<SVGRootRenderingObserver> mRenderingObserver;
  RefPtr<SVGLoadEventListener>     mLoadEventListener;
  RefPtr<SVGParseCompleteListener> mParseCompleteListener;

  /// Count of locks on this image (roughly correlated to visible instances).
  uint32_t mLockCount;

  // Stored result from the Necko load of the image, which we save in
  // OnImageDataComplete if the underlying SVG document isn't loaded. If we save
  // this, we actually notify this progress (and clear this value) in
  // OnSVGDocumentLoaded or OnSVGDocumentError.
  Maybe<Progress> mLoadProgress;

  bool           mIsInitialized;          // Have we been initialized?
  bool           mDiscardable;            // Are we discardable?
  bool           mIsFullyLoaded;          // Has the SVG document finished
                                          // loading?
  bool           mIsDrawing;              // Are we currently drawing?
  bool           mHaveAnimations;         // Is our SVG content SMIL-animated?
                                          // (Only set after mIsFullyLoaded.)
  bool           mHasPendingInvalidation; // Invalidate observers next refresh
                                          // driver tick.

  friend class ImageFactory;
};

inline NS_IMETHODIMP VectorImage::GetAnimationMode(uint16_t* aAnimationMode) {
  return GetAnimationModeInternal(aAnimationMode);
}

inline NS_IMETHODIMP VectorImage::SetAnimationMode(uint16_t aAnimationMode) {
  return SetAnimationModeInternal(aAnimationMode);
}

} // namespace image
} // namespace mozilla

#endif // mozilla_image_VectorImage_h