mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-30 12:27:29 +09:00
import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo
This commit is contained in:
commit
dcd9973243
150858 changed files with 23884658 additions and 0 deletions
234
image/ProgressTracker.h
Normal file
234
image/ProgressTracker.h
Normal file
|
|
@ -0,0 +1,234 @@
|
|||
/* -*- 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_ProgressTracker_h
|
||||
#define mozilla_image_ProgressTracker_h
|
||||
|
||||
#include "CopyOnWrite.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/WeakPtr.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsTObserverArray.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsRect.h"
|
||||
#include "IProgressObserver.h"
|
||||
|
||||
class nsIRunnable;
|
||||
|
||||
namespace mozilla {
|
||||
namespace image {
|
||||
|
||||
class AsyncNotifyRunnable;
|
||||
class AsyncNotifyCurrentStateRunnable;
|
||||
class Image;
|
||||
|
||||
/**
|
||||
* Image progress bitflags.
|
||||
*
|
||||
* See CheckProgressConsistency() for the invariants we enforce about the
|
||||
* ordering dependencies betweeen these flags.
|
||||
*/
|
||||
enum {
|
||||
FLAG_SIZE_AVAILABLE = 1u << 0, // STATUS_SIZE_AVAILABLE
|
||||
FLAG_DECODE_COMPLETE = 1u << 1, // STATUS_DECODE_COMPLETE
|
||||
FLAG_FRAME_COMPLETE = 1u << 2, // STATUS_FRAME_COMPLETE
|
||||
FLAG_LOAD_COMPLETE = 1u << 3, // STATUS_LOAD_COMPLETE
|
||||
FLAG_ONLOAD_BLOCKED = 1u << 4,
|
||||
FLAG_ONLOAD_UNBLOCKED = 1u << 5,
|
||||
FLAG_IS_ANIMATED = 1u << 6, // STATUS_IS_ANIMATED
|
||||
FLAG_HAS_TRANSPARENCY = 1u << 7, // STATUS_HAS_TRANSPARENCY
|
||||
FLAG_LAST_PART_COMPLETE = 1u << 8,
|
||||
FLAG_HAS_ERROR = 1u << 9 // STATUS_ERROR
|
||||
};
|
||||
|
||||
typedef uint32_t Progress;
|
||||
|
||||
const uint32_t NoProgress = 0;
|
||||
|
||||
inline Progress LoadCompleteProgress(bool aLastPart,
|
||||
bool aError,
|
||||
nsresult aStatus)
|
||||
{
|
||||
Progress progress = FLAG_LOAD_COMPLETE;
|
||||
if (aLastPart) {
|
||||
progress |= FLAG_LAST_PART_COMPLETE;
|
||||
}
|
||||
if (NS_FAILED(aStatus) || aError) {
|
||||
progress |= FLAG_HAS_ERROR;
|
||||
}
|
||||
return progress;
|
||||
}
|
||||
|
||||
/**
|
||||
* ProgressTracker stores its observers in an ObserverTable, which is a hash
|
||||
* table mapping raw pointers to WeakPtr's to the same objects. This sounds like
|
||||
* unnecessary duplication of information, but it's necessary for stable hash
|
||||
* values since WeakPtr's lose the knowledge of which object they used to point
|
||||
* to when that object is destroyed.
|
||||
*
|
||||
* ObserverTable subclasses nsDataHashtable to add reference counting support
|
||||
* and a copy constructor, both of which are needed for use with CopyOnWrite<T>.
|
||||
*/
|
||||
class ObserverTable
|
||||
: public nsDataHashtable<nsPtrHashKey<IProgressObserver>,
|
||||
WeakPtr<IProgressObserver>>
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_REFCOUNTING(ObserverTable);
|
||||
|
||||
ObserverTable() = default;
|
||||
|
||||
ObserverTable(const ObserverTable& aOther)
|
||||
{
|
||||
NS_WARNING("Forced to copy ObserverTable due to nested notifications");
|
||||
for (auto iter = aOther.ConstIter(); !iter.Done(); iter.Next()) {
|
||||
this->Put(iter.Key(), iter.Data());
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
~ObserverTable() { }
|
||||
};
|
||||
|
||||
/**
|
||||
* ProgressTracker is a class that records an Image's progress through the
|
||||
* loading and decoding process, and makes it possible to send notifications to
|
||||
* IProgressObservers, both synchronously and asynchronously.
|
||||
*
|
||||
* When a new observer needs to be notified of the current progress of an image,
|
||||
* call the Notify() method on this class with the relevant observer as its
|
||||
* argument, and the notifications will be replayed to the observer
|
||||
* asynchronously.
|
||||
*/
|
||||
class ProgressTracker : public mozilla::SupportsWeakPtr<ProgressTracker>
|
||||
{
|
||||
virtual ~ProgressTracker() { }
|
||||
|
||||
public:
|
||||
MOZ_DECLARE_WEAKREFERENCE_TYPENAME(ProgressTracker)
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ProgressTracker)
|
||||
|
||||
ProgressTracker()
|
||||
: mImageMutex("ProgressTracker::mImage")
|
||||
, mImage(nullptr)
|
||||
, mObservers(new ObserverTable)
|
||||
, mProgress(NoProgress)
|
||||
{ }
|
||||
|
||||
bool HasImage() const { MutexAutoLock lock(mImageMutex); return mImage; }
|
||||
already_AddRefed<Image> GetImage() const
|
||||
{
|
||||
MutexAutoLock lock(mImageMutex);
|
||||
RefPtr<Image> image = mImage;
|
||||
return image.forget();
|
||||
}
|
||||
|
||||
// Get the current image status (as in imgIRequest).
|
||||
uint32_t GetImageStatus() const;
|
||||
|
||||
// Get the current Progress.
|
||||
Progress GetProgress() const { return mProgress; }
|
||||
|
||||
// Schedule an asynchronous "replaying" of all the notifications that would
|
||||
// have to happen to put us in the current state.
|
||||
// We will also take note of any notifications that happen between the time
|
||||
// Notify() is called and when we call SyncNotify on |aObserver|, and replay
|
||||
// them as well.
|
||||
// Should be called on the main thread only, since observers and GetURI are
|
||||
// not threadsafe.
|
||||
void Notify(IProgressObserver* aObserver);
|
||||
|
||||
// Schedule an asynchronous "replaying" of all the notifications that would
|
||||
// have to happen to put us in the state we are in right now.
|
||||
// Unlike Notify(), does *not* take into account future notifications.
|
||||
// This is only useful if you do not have an imgRequest, e.g., if you are a
|
||||
// static request returned from imgIRequest::GetStaticRequest().
|
||||
// Should be called on the main thread only, since observers and GetURI are
|
||||
// not threadsafe.
|
||||
void NotifyCurrentState(IProgressObserver* aObserver);
|
||||
|
||||
// "Replay" all of the notifications that would have to happen to put us in
|
||||
// the state we're currently in.
|
||||
// Only use this if you're already servicing an asynchronous call (e.g.
|
||||
// OnStartRequest).
|
||||
// Should be called on the main thread only, since observers and GetURI are
|
||||
// not threadsafe.
|
||||
void SyncNotify(IProgressObserver* aObserver);
|
||||
|
||||
// Get this ProgressTracker ready for a new request. This resets all the
|
||||
// state that doesn't persist between requests.
|
||||
void ResetForNewRequest();
|
||||
|
||||
// Stateless notifications. These are dispatched and immediately forgotten
|
||||
// about. All of these notifications are main thread only.
|
||||
void OnDiscard();
|
||||
void OnUnlockedDraw();
|
||||
void OnImageAvailable();
|
||||
|
||||
// Compute the difference between this our progress and aProgress. This allows
|
||||
// callers to predict whether SyncNotifyProgress will send any notifications.
|
||||
Progress Difference(Progress aProgress) const
|
||||
{
|
||||
return ~mProgress & aProgress;
|
||||
}
|
||||
|
||||
// Update our state to incorporate the changes in aProgress and synchronously
|
||||
// notify our observers.
|
||||
//
|
||||
// Because this may result in recursive notifications, no decoding locks may
|
||||
// be held. Called on the main thread only.
|
||||
void SyncNotifyProgress(Progress aProgress,
|
||||
const nsIntRect& aInvalidRect = nsIntRect());
|
||||
|
||||
// We manage a set of observers that are using an image and thus concerned
|
||||
// with its loading progress. Weak pointers.
|
||||
void AddObserver(IProgressObserver* aObserver);
|
||||
bool RemoveObserver(IProgressObserver* aObserver);
|
||||
uint32_t ObserverCount() const;
|
||||
|
||||
// Resets our weak reference to our image. Image subclasses should call this
|
||||
// in their destructor.
|
||||
void ResetImage();
|
||||
|
||||
private:
|
||||
friend class AsyncNotifyRunnable;
|
||||
friend class AsyncNotifyCurrentStateRunnable;
|
||||
friend class ImageFactory;
|
||||
|
||||
ProgressTracker(const ProgressTracker& aOther) = delete;
|
||||
|
||||
// Sets our weak reference to our image. Only ImageFactory should call this.
|
||||
void SetImage(Image* aImage);
|
||||
|
||||
// Send some notifications that would be necessary to make |aObserver| believe
|
||||
// the request is finished downloading and decoding. We only send
|
||||
// FLAG_LOAD_COMPLETE and FLAG_ONLOAD_UNBLOCKED, and only if necessary.
|
||||
void EmulateRequestFinished(IProgressObserver* aObserver);
|
||||
|
||||
// Main thread only because it deals with the observer service.
|
||||
void FireFailureNotification();
|
||||
|
||||
// The runnable, if any, that we've scheduled to deliver async notifications.
|
||||
nsCOMPtr<nsIRunnable> mRunnable;
|
||||
|
||||
// mImage is a weak ref; it should be set to null when the image goes out of
|
||||
// scope. mImageMutex protects mImage.
|
||||
mutable Mutex mImageMutex;
|
||||
Image* mImage;
|
||||
|
||||
// Hashtable of observers attached to the image. Each observer represents a
|
||||
// consumer using the image. Main thread only.
|
||||
CopyOnWrite<ObserverTable> mObservers;
|
||||
|
||||
Progress mProgress;
|
||||
};
|
||||
|
||||
} // namespace image
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_image_ProgressTracker_h
|
||||
Loading…
Add table
Add a link
Reference in a new issue