зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1091229 - Make nsBulletFrame block onload when it loads images. r=tn
--HG-- extra : rebase_source : e6b4ed67cab9d0d674a6a5f194c14c7362723440
This commit is contained in:
Родитель
2d5dbdb879
Коммит
552b8dfc85
|
@ -12,6 +12,7 @@
|
|||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/gfx/PathHelpers.h"
|
||||
#include "mozilla/MathAlgorithms.h"
|
||||
#include "mozilla/Move.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsFontMetrics.h"
|
||||
#include "nsGkAtoms.h"
|
||||
|
@ -51,20 +52,14 @@ NS_QUERYFRAME_TAIL_INHERITING(nsFrame)
|
|||
|
||||
nsBulletFrame::~nsBulletFrame()
|
||||
{
|
||||
NS_ASSERTION(!mBlockingOnload, "Still blocking onload in destructor?");
|
||||
}
|
||||
|
||||
void
|
||||
nsBulletFrame::DestroyFrom(nsIFrame* aDestructRoot)
|
||||
{
|
||||
// Stop image loading first
|
||||
if (mImageRequest) {
|
||||
// Deregister our image request from the refresh driver
|
||||
nsLayoutUtils::DeregisterImageRequest(PresContext(),
|
||||
mImageRequest,
|
||||
&mRequestRegistered);
|
||||
mImageRequest->CancelAndForgetObserver(NS_ERROR_FAILURE);
|
||||
mImageRequest = nullptr;
|
||||
}
|
||||
// Stop image loading first.
|
||||
DeregisterAndCancelImageRequest();
|
||||
|
||||
if (mListener) {
|
||||
mListener->SetFrame(nullptr);
|
||||
|
@ -132,35 +127,21 @@ nsBulletFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
|
|||
}
|
||||
|
||||
if (needNewRequest) {
|
||||
nsRefPtr<imgRequestProxy> oldRequest = mImageRequest;
|
||||
newRequest->Clone(mListener, getter_AddRefs(mImageRequest));
|
||||
nsRefPtr<imgRequestProxy> newRequestClone;
|
||||
newRequest->Clone(mListener, getter_AddRefs(newRequestClone));
|
||||
|
||||
// Deregister the old request. We wait until after Clone is done in case
|
||||
// the old request and the new request are the same underlying image
|
||||
// accessed via different URLs.
|
||||
if (oldRequest) {
|
||||
nsLayoutUtils::DeregisterImageRequest(PresContext(), oldRequest,
|
||||
&mRequestRegistered);
|
||||
oldRequest->CancelAndForgetObserver(NS_ERROR_FAILURE);
|
||||
oldRequest = nullptr;
|
||||
}
|
||||
DeregisterAndCancelImageRequest();
|
||||
|
||||
// Register the new request.
|
||||
if (mImageRequest) {
|
||||
nsLayoutUtils::RegisterImageRequestIfAnimated(PresContext(),
|
||||
mImageRequest,
|
||||
&mRequestRegistered);
|
||||
}
|
||||
mImageRequest = Move(newRequestClone);
|
||||
RegisterImageRequest(/* aKnownToBeAnimated = */ false);
|
||||
}
|
||||
} else {
|
||||
// No image request on the new style context
|
||||
if (mImageRequest) {
|
||||
nsLayoutUtils::DeregisterImageRequest(PresContext(), mImageRequest,
|
||||
&mRequestRegistered);
|
||||
|
||||
mImageRequest->CancelAndForgetObserver(NS_ERROR_FAILURE);
|
||||
mImageRequest = nullptr;
|
||||
}
|
||||
// No image request on the new style context.
|
||||
DeregisterAndCancelImageRequest();
|
||||
}
|
||||
|
||||
#ifdef ACCESSIBILITY
|
||||
|
@ -692,14 +673,67 @@ nsBulletFrame::Notify(imgIRequest *aRequest, int32_t aType, const nsIntRect* aDa
|
|||
// Register the image request with the refresh driver now that we know it's
|
||||
// animated.
|
||||
if (aRequest == mImageRequest) {
|
||||
nsLayoutUtils::RegisterImageRequest(PresContext(), mImageRequest,
|
||||
&mRequestRegistered);
|
||||
RegisterImageRequest(/* aKnownToBeAnimated = */ true);
|
||||
}
|
||||
}
|
||||
|
||||
if (aType == imgINotificationObserver::LOAD_COMPLETE) {
|
||||
// Unconditionally start decoding for now.
|
||||
// XXX(seth): We eventually want to decide whether to do this based on
|
||||
// visibility. We should get that for free from bug 1091236.
|
||||
if (aRequest == mImageRequest) {
|
||||
mImageRequest->RequestDecode();
|
||||
}
|
||||
InvalidateFrame();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBulletFrame::BlockOnload(imgIRequest* aRequest)
|
||||
{
|
||||
if (aRequest != mImageRequest) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_ASSERTION(!mBlockingOnload, "Double BlockOnload for an nsBulletFrame?");
|
||||
|
||||
nsIDocument* doc = GetOurCurrentDoc();
|
||||
if (doc) {
|
||||
mBlockingOnload = true;
|
||||
doc->BlockOnload();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBulletFrame::UnblockOnload(imgIRequest* aRequest)
|
||||
{
|
||||
if (aRequest != mImageRequest) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_ASSERTION(!mBlockingOnload, "Double UnblockOnload for an nsBulletFrame?");
|
||||
|
||||
nsIDocument* doc = GetOurCurrentDoc();
|
||||
if (doc) {
|
||||
doc->UnblockOnload(false);
|
||||
}
|
||||
mBlockingOnload = false;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIDocument*
|
||||
nsBulletFrame::GetOurCurrentDoc() const
|
||||
{
|
||||
nsIContent* parentContent = GetParent()->GetContent();
|
||||
return parentContent ? parentContent->GetComposedDoc()
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
nsresult nsBulletFrame::OnStartContainer(imgIRequest *aRequest,
|
||||
imgIContainer *aImage)
|
||||
{
|
||||
|
@ -873,7 +907,57 @@ nsBulletFrame::GetSpokenText(nsAString& aText)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsBulletFrame::RegisterImageRequest(bool aKnownToBeAnimated)
|
||||
{
|
||||
if (mImageRequest) {
|
||||
// mRequestRegistered is a bitfield; unpack it temporarily so we can take
|
||||
// the address.
|
||||
bool isRequestRegistered = mRequestRegistered;
|
||||
|
||||
if (aKnownToBeAnimated) {
|
||||
nsLayoutUtils::RegisterImageRequest(PresContext(), mImageRequest,
|
||||
&isRequestRegistered);
|
||||
} else {
|
||||
nsLayoutUtils::RegisterImageRequestIfAnimated(PresContext(),
|
||||
mImageRequest,
|
||||
&isRequestRegistered);
|
||||
}
|
||||
|
||||
isRequestRegistered = mRequestRegistered;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nsBulletFrame::DeregisterAndCancelImageRequest()
|
||||
{
|
||||
if (mImageRequest) {
|
||||
// mRequestRegistered is a bitfield; unpack it temporarily so we can take
|
||||
// the address.
|
||||
bool isRequestRegistered = mRequestRegistered;
|
||||
|
||||
// Deregister our image request from the refresh driver.
|
||||
nsLayoutUtils::DeregisterImageRequest(PresContext(),
|
||||
mImageRequest,
|
||||
&isRequestRegistered);
|
||||
|
||||
isRequestRegistered = mRequestRegistered;
|
||||
|
||||
// Unblock onload if we blocked it.
|
||||
if (mBlockingOnload) {
|
||||
nsIDocument* doc = GetOurCurrentDoc();
|
||||
if (doc) {
|
||||
doc->UnblockOnload(false);
|
||||
}
|
||||
mBlockingOnload = false;
|
||||
}
|
||||
|
||||
// Cancel the image request and forget about it.
|
||||
mImageRequest->CancelAndForgetObserver(NS_ERROR_FAILURE);
|
||||
mImageRequest = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -894,7 +978,26 @@ nsBulletListener::~nsBulletListener()
|
|||
NS_IMETHODIMP
|
||||
nsBulletListener::Notify(imgIRequest *aRequest, int32_t aType, const nsIntRect* aData)
|
||||
{
|
||||
if (!mFrame)
|
||||
if (!mFrame) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return mFrame->Notify(aRequest, aType, aData);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBulletListener::BlockOnload(imgIRequest* aRequest)
|
||||
{
|
||||
if (!mFrame) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return mFrame->BlockOnload(aRequest);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsBulletListener::UnblockOnload(imgIRequest* aRequest)
|
||||
{
|
||||
if (!mFrame) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return mFrame->UnblockOnload(aRequest);
|
||||
}
|
||||
|
|
|
@ -12,19 +12,22 @@
|
|||
#include "nsFrame.h"
|
||||
|
||||
#include "imgINotificationObserver.h"
|
||||
#include "imgIOnloadBlocker.h"
|
||||
|
||||
class imgIContainer;
|
||||
class imgRequestProxy;
|
||||
|
||||
class nsBulletFrame;
|
||||
|
||||
class nsBulletListener MOZ_FINAL : public imgINotificationObserver
|
||||
class nsBulletListener MOZ_FINAL : public imgINotificationObserver,
|
||||
public imgIOnloadBlocker
|
||||
{
|
||||
public:
|
||||
nsBulletListener();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_IMGINOTIFICATIONOBSERVER
|
||||
NS_DECL_IMGIONLOADBLOCKER
|
||||
|
||||
void SetFrame(nsBulletFrame *frame) { mFrame = frame; }
|
||||
|
||||
|
@ -50,11 +53,14 @@ public:
|
|||
: nsFrame(aContext)
|
||||
, mPadding(GetWritingMode())
|
||||
, mIntrinsicSize(GetWritingMode())
|
||||
{
|
||||
}
|
||||
, mRequestRegistered(false)
|
||||
, mBlockingOnload(false)
|
||||
{ }
|
||||
virtual ~nsBulletFrame();
|
||||
|
||||
NS_IMETHOD Notify(imgIRequest *aRequest, int32_t aType, const nsIntRect* aData);
|
||||
NS_IMETHOD Notify(imgIRequest* aRequest, int32_t aType, const nsIntRect* aData);
|
||||
NS_IMETHOD BlockOnload(imgIRequest* aRequest);
|
||||
NS_IMETHOD UnblockOnload(imgIRequest* aRequest);
|
||||
|
||||
// nsIFrame
|
||||
virtual void DestroyFrom(nsIFrame* aDestructRoot) MOZ_OVERRIDE;
|
||||
|
@ -111,6 +117,7 @@ protected:
|
|||
float aFontSizeInflation);
|
||||
|
||||
void GetLoadGroup(nsPresContext *aPresContext, nsILoadGroup **aLoadGroup);
|
||||
nsIDocument* GetOurCurrentDoc() const;
|
||||
|
||||
mozilla::LogicalMargin mPadding;
|
||||
nsRefPtr<imgRequestProxy> mImageRequest;
|
||||
|
@ -120,10 +127,15 @@ protected:
|
|||
int32_t mOrdinal;
|
||||
|
||||
private:
|
||||
void RegisterImageRequest(bool aKnownToBeAnimated);
|
||||
void DeregisterAndCancelImageRequest();
|
||||
|
||||
// This is a boolean flag indicating whether or not the current image request
|
||||
// has been registered with the refresh driver.
|
||||
bool mRequestRegistered;
|
||||
bool mRequestRegistered : 1;
|
||||
|
||||
// Whether we're currently blocking onload.
|
||||
bool mBlockingOnload : 1;
|
||||
};
|
||||
|
||||
#endif /* nsBulletFrame_h___ */
|
||||
|
|
|
@ -127,7 +127,7 @@ skip-if(B2G) == img-fragment-2a.html img-fragment-2-ref.html # bug 773482
|
|||
skip-if(B2G) == img-fragment-2b.html img-fragment-2-ref.html # bug 773482
|
||||
skip-if(B2G) == img-fragment-2c.html img-fragment-2-ref.html # bug 773482
|
||||
|
||||
skip-if(B2G) == list-simple-1.html list-simple-1-ref.html # bug 773482
|
||||
fuzzy-if(B2G,68,4) == list-simple-1.html list-simple-1-ref.html
|
||||
|
||||
== svg-image-simple-1.svg lime100x100.svg
|
||||
== svg-image-simple-2.svg lime100x100.svg
|
||||
|
|
Загрузка…
Ссылка в новой задаче