зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to tracemonkey.
This commit is contained in:
Коммит
61a58b84de
|
@ -157,6 +157,7 @@ enum EventNameType {
|
|||
EventNameType_XUL = 0x0002,
|
||||
EventNameType_SVGGraphic = 0x0004, // svg graphic elements
|
||||
EventNameType_SVGSVG = 0x0008, // the svg element
|
||||
EventNameType_SMIL = 0x0016, // smil elements
|
||||
|
||||
EventNameType_HTMLXUL = 0x0003,
|
||||
EventNameType_All = 0xFFFF
|
||||
|
|
|
@ -575,6 +575,14 @@ nsContentUtils::InitializeEventTable() {
|
|||
// This is a bit hackish, but SVG's event names are weird.
|
||||
{ nsGkAtoms::onzoom, NS_SVG_ZOOM, EventNameType_SVGSVG, NS_EVENT_NULL },
|
||||
#endif // MOZ_SVG
|
||||
#ifdef MOZ_SMIL
|
||||
{ nsGkAtoms::onbegin, NS_SMIL_BEGIN, EventNameType_SMIL, NS_EVENT_NULL },
|
||||
{ nsGkAtoms::onbeginEvent, NS_SMIL_BEGIN, EventNameType_None, NS_SMIL_TIME_EVENT },
|
||||
{ nsGkAtoms::onend, NS_SMIL_END, EventNameType_SMIL, NS_EVENT_NULL },
|
||||
{ nsGkAtoms::onendEvent, NS_SMIL_END, EventNameType_None, NS_SMIL_TIME_EVENT },
|
||||
{ nsGkAtoms::onrepeat, NS_SMIL_REPEAT, EventNameType_SMIL, NS_EVENT_NULL },
|
||||
{ nsGkAtoms::onrepeatEvent, NS_SMIL_REPEAT, EventNameType_None, NS_SMIL_TIME_EVENT },
|
||||
#endif // MOZ_SMIL
|
||||
#ifdef MOZ_MEDIA
|
||||
{ nsGkAtoms::onloadstart, NS_LOADSTART, EventNameType_HTML, NS_EVENT_NULL },
|
||||
{ nsGkAtoms::onprogress, NS_PROGRESS, EventNameType_HTML, NS_EVENT_NULL },
|
||||
|
|
|
@ -1309,6 +1309,12 @@ GK_ATOM(keyPoints, "keyPoints")
|
|||
GK_ATOM(keySplines, "keySplines")
|
||||
GK_ATOM(keyTimes, "keyTimes")
|
||||
GK_ATOM(mozAnimateMotionDummyAttr, "_mozAnimateMotionDummyAttr")
|
||||
GK_ATOM(onbegin, "onbegin")
|
||||
GK_ATOM(onbeginEvent, "onbeginEvent")
|
||||
GK_ATOM(onend, "onend")
|
||||
GK_ATOM(onendEvent, "onendEvent")
|
||||
GK_ATOM(onrepeat, "onrepeat")
|
||||
GK_ATOM(onrepeatEvent, "onrepeatEvent")
|
||||
GK_ATOM(repeatCount, "repeatCount")
|
||||
GK_ATOM(repeatDur, "repeatDur")
|
||||
GK_ATOM(restart, "restart")
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Christian Biesinger <cbiesinger@web.de>
|
||||
* Bobby Holley <bobbyholley@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
|
@ -103,14 +104,14 @@ nsImageLoadingContent::nsImageLoadingContent()
|
|||
: mObserverList(nsnull),
|
||||
mImageBlockingStatus(nsIContentPolicy::ACCEPT),
|
||||
mLoadingEnabled(PR_TRUE),
|
||||
mStartingLoad(PR_FALSE),
|
||||
mIsImageStateForced(PR_FALSE),
|
||||
mLoading(PR_FALSE),
|
||||
// mBroken starts out true, since an image without a URI is broken....
|
||||
mBroken(PR_TRUE),
|
||||
mUserDisabled(PR_FALSE),
|
||||
mSuppressed(PR_FALSE),
|
||||
mBlockingOnload(PR_FALSE)
|
||||
mBlockingOnload(PR_FALSE),
|
||||
mStateChangerDepth(0)
|
||||
{
|
||||
if (!nsContentUtils::GetImgLoader()) {
|
||||
mLoadingEnabled = PR_FALSE;
|
||||
|
@ -120,18 +121,9 @@ nsImageLoadingContent::nsImageLoadingContent()
|
|||
void
|
||||
nsImageLoadingContent::DestroyImageLoadingContent()
|
||||
{
|
||||
// If we're blocking onload for any reason, now's a good time to stop
|
||||
SetBlockingOnload(PR_FALSE);
|
||||
|
||||
// Cancel our requests so they won't hold stale refs to us
|
||||
if (mCurrentRequest) {
|
||||
mCurrentRequest->CancelAndForgetObserver(NS_ERROR_FAILURE);
|
||||
mCurrentRequest = nsnull;
|
||||
}
|
||||
if (mPendingRequest) {
|
||||
mPendingRequest->CancelAndForgetObserver(NS_ERROR_FAILURE);
|
||||
mPendingRequest = nsnull;
|
||||
}
|
||||
ClearCurrentRequest(NS_BINDING_ABORTED);
|
||||
ClearPendingRequest(NS_BINDING_ABORTED);
|
||||
}
|
||||
|
||||
nsImageLoadingContent::~nsImageLoadingContent()
|
||||
|
@ -261,6 +253,9 @@ nsImageLoadingContent::OnStopContainer(imgIRequest* aRequest,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// Warning - This isn't actually fired when decode is complete. Rather, it's
|
||||
// fired when load is complete. See bug 505385, and in the mean time use
|
||||
// OnStopContainer.
|
||||
NS_IMETHODIMP
|
||||
nsImageLoadingContent::OnStopDecode(imgIRequest* aRequest,
|
||||
nsresult aStatus,
|
||||
|
@ -273,21 +268,20 @@ nsImageLoadingContent::OnStopDecode(imgIRequest* aRequest,
|
|||
"Unknown request");
|
||||
LOOP_OVER_OBSERVERS(OnStopDecode(aRequest, aStatus, aStatusArg));
|
||||
|
||||
// XXXbholley - When we fix bug 505385, everything here should go in
|
||||
// OnStopRequest.
|
||||
|
||||
// Our state may change. Watch it.
|
||||
AutoStateChanger changer(this, PR_TRUE);
|
||||
|
||||
// If the pending request is loaded, switch to it.
|
||||
if (aRequest == mPendingRequest) {
|
||||
|
||||
// If we were blocking for the soon-to-be-obsolete request, stop doing so
|
||||
SetBlockingOnload(PR_FALSE);
|
||||
|
||||
// The new image is decoded - switch to it
|
||||
// XXXbholley - This is technically not true pre bug 505385, but I don't
|
||||
// think it's a big enough issue to worry about handling in the mean time
|
||||
mCurrentRequest->Cancel(NS_ERROR_IMAGE_SRC_CHANGED);
|
||||
mPendingRequest.swap(mCurrentRequest);
|
||||
PrepareCurrentRequest() = mPendingRequest;
|
||||
mPendingRequest = nsnull;
|
||||
}
|
||||
NS_ABORT_IF_FALSE(aRequest == mCurrentRequest,
|
||||
"One way or another, we should be current by now");
|
||||
|
||||
// XXXbholley - When we fix bug 505385, this should go in OnStopRequest.
|
||||
//
|
||||
// We just loaded all the data we're going to get. If we haven't done an
|
||||
// initial paint, we want to make sure the image starts decoding for 2
|
||||
// reasons:
|
||||
|
@ -324,26 +318,16 @@ nsImageLoadingContent::OnStopDecode(imgIRequest* aRequest,
|
|||
|
||||
// If we're requesting a decode, do it
|
||||
if (doRequestDecode)
|
||||
aRequest->RequestDecode();
|
||||
mCurrentRequest->RequestDecode();
|
||||
}
|
||||
|
||||
// XXXldb What's the difference between when OnStopDecode and OnStopRequest
|
||||
// fire? Should we do this work there instead? Should they just be the
|
||||
// same?
|
||||
|
||||
// Fire the appropriate DOM event.
|
||||
if (NS_SUCCEEDED(aStatus)) {
|
||||
FireEvent(NS_LITERAL_STRING("load"));
|
||||
} else {
|
||||
FireEvent(NS_LITERAL_STRING("error"));
|
||||
}
|
||||
|
||||
// Have to check for state changes here (for example, the new load could
|
||||
// have resulted in a broken image). Note that we don't want to do this
|
||||
// async, unlike the event, because while this is waiting to happen our
|
||||
// state could change yet again, and then we'll get confused about our
|
||||
// state.
|
||||
UpdateImageState(PR_TRUE);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -513,39 +497,36 @@ NS_IMETHODIMP
|
|||
nsImageLoadingContent::LoadImageWithChannel(nsIChannel* aChannel,
|
||||
nsIStreamListener** aListener)
|
||||
{
|
||||
NS_PRECONDITION(aListener, "null out param");
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aChannel);
|
||||
|
||||
if (!nsContentUtils::GetImgLoader()) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
// XXX what should we do with content policies here, if anything?
|
||||
// Shouldn't that be done before the start of the load?
|
||||
// XXX what about shouldProcess?
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = GetOurDocument();
|
||||
if (!doc) {
|
||||
// Don't bother
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Null out our mCurrentURI, in case we have no image requests right now.
|
||||
mCurrentURI = nsnull;
|
||||
|
||||
CancelImageRequests(NS_ERROR_IMAGE_SRC_CHANGED, PR_FALSE,
|
||||
nsIContentPolicy::ACCEPT);
|
||||
// XXX what should we do with content policies here, if anything?
|
||||
// Shouldn't that be done before the start of the load?
|
||||
// XXX what about shouldProcess?
|
||||
|
||||
nsCOMPtr<imgIRequest> & req = mCurrentRequest ? mPendingRequest : mCurrentRequest;
|
||||
// Our state might change. Watch it.
|
||||
AutoStateChanger changer(this, PR_TRUE);
|
||||
|
||||
// Do the load.
|
||||
nsresult rv = nsContentUtils::GetImgLoader()->
|
||||
LoadImageWithChannel(aChannel, this, doc, aListener, getter_AddRefs(req));
|
||||
|
||||
// Make sure our state is up to date
|
||||
UpdateImageState(PR_TRUE);
|
||||
|
||||
return rv;
|
||||
LoadImageWithChannel(aChannel, this, doc, aListener,
|
||||
getter_AddRefs(PrepareNextRequest()));
|
||||
if (NS_FAILED(rv)) {
|
||||
// If we don't have a current URI, we might as well store this URI so people
|
||||
// know what we tried (and failed) to load.
|
||||
if (!mCurrentRequest)
|
||||
aChannel->GetURI(getter_AddRefs(mCurrentURI));
|
||||
FireEvent(NS_LITERAL_STRING("error"));
|
||||
return rv;
|
||||
}
|
||||
return NS_OK;;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsImageLoadingContent::ForceReload()
|
||||
|
@ -628,11 +609,10 @@ nsImageLoadingContent::LoadImage(nsIURI* aNewURI,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
nsresult rv; // XXXbz Should failures in this method fire onerror?
|
||||
|
||||
// Skip the URI equality check if our current image was blocked. If
|
||||
// that happened, we really do want to try loading again.
|
||||
// URI equality check.
|
||||
//
|
||||
// We skip the equality check if our current image was blocked, since in that
|
||||
// case we really do want to try loading again.
|
||||
if (!aForce && NS_CP_ACCEPTED(mImageBlockingStatus)) {
|
||||
nsCOMPtr<nsIURI> currentURI;
|
||||
GetCurrentURI(getter_AddRefs(currentURI));
|
||||
|
@ -645,71 +625,46 @@ nsImageLoadingContent::LoadImage(nsIURI* aNewURI,
|
|||
}
|
||||
}
|
||||
|
||||
// From this point on, our state could change before return, so make
|
||||
// sure to notify if it does.
|
||||
// From this point on, our image state could change. Watch it.
|
||||
AutoStateChanger changer(this, aNotify);
|
||||
|
||||
// Use the principal of aDocument to avoid having to QI |this| an extra time.
|
||||
// It should be the same as the principal of this node in any case.
|
||||
// Sanity check.
|
||||
//
|
||||
// We use the principal of aDocument to avoid having to QI |this| an extra
|
||||
// time. It should always be the same as the principal of this node.
|
||||
#ifdef DEBUG
|
||||
nsCOMPtr<nsIContent> thisContent = do_QueryInterface(this);
|
||||
NS_ASSERTION(thisContent &&
|
||||
thisContent->NodePrincipal() == aDocument->NodePrincipal(),
|
||||
"Principal mismatch?");
|
||||
NS_ABORT_IF_FALSE(thisContent &&
|
||||
thisContent->NodePrincipal() == aDocument->NodePrincipal(),
|
||||
"Principal mismatch?");
|
||||
#endif
|
||||
|
||||
// If we'll be loading a new image, we want to cancel our existing
|
||||
// requests; the question is what reason to pass in. If everything
|
||||
// is going smoothly, that reason should be
|
||||
// NS_ERROR_IMAGE_SRC_CHANGED so that our frame (if any) will know
|
||||
// not to show the broken image icon. If the load is blocked by the
|
||||
// content policy or security manager, we will want to cancel with
|
||||
// the error code from those.
|
||||
|
||||
PRInt16 newImageStatus;
|
||||
PRBool loadImage = nsContentUtils::CanLoadImage(aNewURI, this, aDocument,
|
||||
aDocument->NodePrincipal(),
|
||||
&newImageStatus);
|
||||
NS_ASSERTION(loadImage || !NS_CP_ACCEPTED(newImageStatus),
|
||||
"CanLoadImage lied");
|
||||
|
||||
nsresult cancelResult = loadImage ? NS_ERROR_IMAGE_SRC_CHANGED
|
||||
: NS_ERROR_IMAGE_BLOCKED;
|
||||
|
||||
CancelImageRequests(cancelResult, PR_FALSE, newImageStatus);
|
||||
|
||||
// Remember the URL of this request, in case someone asks us for it later.
|
||||
// But this only matters if we are affecting the current request. Need to do
|
||||
// this after CancelImageRequests, since that affects the value of
|
||||
// mCurrentRequest.
|
||||
if (!mCurrentRequest) {
|
||||
mCurrentURI = aNewURI;
|
||||
}
|
||||
|
||||
if (!loadImage) {
|
||||
// Don't actually load anything! This was blocked by CanLoadImage.
|
||||
// Are we blocked?
|
||||
PRInt16 cpDecision = nsIContentPolicy::REJECT_REQUEST;
|
||||
nsContentUtils::CanLoadImage(aNewURI, this, aDocument,
|
||||
aDocument->NodePrincipal(), &cpDecision);
|
||||
if (!NS_CP_ACCEPTED(cpDecision)) {
|
||||
FireEvent(NS_LITERAL_STRING("error"));
|
||||
SetBlockedRequest(aNewURI, cpDecision);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<imgIRequest> & req = mCurrentRequest ? mPendingRequest : mCurrentRequest;
|
||||
|
||||
// Not blocked. Do the load.
|
||||
nsresult rv;
|
||||
rv = nsContentUtils::LoadImage(aNewURI, aDocument,
|
||||
aDocument->NodePrincipal(),
|
||||
aDocument->GetDocumentURI(),
|
||||
this, aLoadFlags,
|
||||
getter_AddRefs(req));
|
||||
getter_AddRefs(PrepareNextRequest()));
|
||||
if (NS_FAILED(rv)) {
|
||||
// If we don't have a current URI, we might as well store this URI so people
|
||||
// know what we tried (and failed) to load.
|
||||
if (!mCurrentRequest)
|
||||
mCurrentURI = aNewURI;
|
||||
FireEvent(NS_LITERAL_STRING("error"));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// If we now have a current request, we don't need to store the URI, since
|
||||
// we can get it off the request. Release it.
|
||||
if (mCurrentRequest) {
|
||||
mCurrentURI = nsnull;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -734,12 +689,13 @@ nsImageLoadingContent::ImageState() const
|
|||
void
|
||||
nsImageLoadingContent::UpdateImageState(PRBool aNotify)
|
||||
{
|
||||
if (mStartingLoad) {
|
||||
// Ignore this call; we'll update our state when the state changer is
|
||||
// destroyed. Need this to work around the fact that some libpr0n stuff is
|
||||
// actually sync and hence we can get OnStopDecode called while we're still
|
||||
// under LoadImage, and OnStopDecode doesn't know anything about
|
||||
// aNotify
|
||||
if (mStateChangerDepth > 0) {
|
||||
// Ignore this call; we'll update our state when the outermost state
|
||||
// changer is destroyed. Need this to work around the fact that some libpr0n
|
||||
// stuff is actually sync and hence we can get OnStopDecode called while
|
||||
// we're still under LoadImage, and OnStopDecode doesn't know anything about
|
||||
// aNotify.
|
||||
// XXX - This machinery should be removed after bug 521604.
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -788,78 +744,28 @@ nsImageLoadingContent::UpdateImageState(PRBool aNotify)
|
|||
void
|
||||
nsImageLoadingContent::CancelImageRequests(PRBool aNotify)
|
||||
{
|
||||
// Make sure to null out mCurrentURI here, so we no longer look like an image
|
||||
AutoStateChanger changer(this, aNotify);
|
||||
mCurrentURI = nsnull;
|
||||
CancelImageRequests(NS_BINDING_ABORTED, PR_TRUE, nsIContentPolicy::ACCEPT);
|
||||
}
|
||||
|
||||
void
|
||||
nsImageLoadingContent::CancelImageRequests(nsresult aReason,
|
||||
PRBool aEvenIfSizeAvailable,
|
||||
PRInt16 aNewImageStatus)
|
||||
{
|
||||
// Cancel the pending request, if any
|
||||
if (mPendingRequest) {
|
||||
mPendingRequest->Cancel(aReason);
|
||||
mPendingRequest = nsnull;
|
||||
}
|
||||
|
||||
// Cancel the current request if it has not progressed enough to
|
||||
// have a size yet
|
||||
if (mCurrentRequest) {
|
||||
PRUint32 loadStatus = imgIRequest::STATUS_ERROR;
|
||||
mCurrentRequest->GetImageStatus(&loadStatus);
|
||||
|
||||
NS_ASSERTION(NS_CP_ACCEPTED(mImageBlockingStatus),
|
||||
"Have current request but blocked image?");
|
||||
|
||||
if (aEvenIfSizeAvailable ||
|
||||
!(loadStatus & imgIRequest::STATUS_SIZE_AVAILABLE)) {
|
||||
// The new image is going to become the current request. Make sure to
|
||||
// set mImageBlockingStatus _before_ we cancel the request... if we set
|
||||
// it after, things that are watching the mCurrentRequest will get wrong
|
||||
// data.
|
||||
|
||||
// If we were blocking onload for this image, stop doing so
|
||||
SetBlockingOnload(PR_FALSE);
|
||||
|
||||
// Get rid of it
|
||||
mImageBlockingStatus = aNewImageStatus;
|
||||
mCurrentRequest->Cancel(aReason);
|
||||
mCurrentRequest = nsnull;
|
||||
}
|
||||
} else {
|
||||
// No current request so the new image status will become the
|
||||
// status of the current request
|
||||
mImageBlockingStatus = aNewImageStatus;
|
||||
}
|
||||
|
||||
// Note that the only way we could have avoided setting the image blocking
|
||||
// status above is if we have a current request and have kept it as the
|
||||
// current request. In that case, we want to leave our old status, since the
|
||||
// status corresponds to the current request. Even if we plan to do a
|
||||
// pending request load, having an mCurrentRequest means that our current
|
||||
// status is not a REJECT_* status, and doing the load shouldn't change that.
|
||||
// XXXbz there is an issue here if different ACCEPT statuses are used, but...
|
||||
ClearPendingRequest(NS_BINDING_ABORTED);
|
||||
ClearCurrentRequest(NS_BINDING_ABORTED);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsImageLoadingContent::UseAsPrimaryRequest(imgIRequest* aRequest,
|
||||
PRBool aNotify)
|
||||
{
|
||||
// Use an AutoStateChanger so that the clone call won't
|
||||
// automatically notify from inside OnStopDecode.
|
||||
// Also, make sure to use the CancelImageRequests which doesn't
|
||||
// notify, so that the changer is handling the notifications.
|
||||
NS_PRECONDITION(aRequest, "Must have a request here!");
|
||||
// Our state will change. Watch it.
|
||||
AutoStateChanger changer(this, aNotify);
|
||||
mCurrentURI = nsnull;
|
||||
CancelImageRequests(NS_BINDING_ABORTED, PR_TRUE, nsIContentPolicy::ACCEPT);
|
||||
|
||||
NS_ASSERTION(!mCurrentRequest, "We should not have a current request now");
|
||||
// Get rid if our existing images
|
||||
ClearPendingRequest(NS_BINDING_ABORTED);
|
||||
ClearCurrentRequest(NS_BINDING_ABORTED);
|
||||
|
||||
return aRequest->Clone(this, getter_AddRefs(mCurrentRequest));
|
||||
// Clone the request we were given.
|
||||
nsCOMPtr<imgIRequest> newRequest;
|
||||
nsresult rv = aRequest->Clone(this, getter_AddRefs(PrepareNextRequest()));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIDocument*
|
||||
|
@ -911,6 +817,112 @@ nsImageLoadingContent::FireEvent(const nsAString& aEventType)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<imgIRequest>&
|
||||
nsImageLoadingContent::PrepareNextRequest()
|
||||
{
|
||||
// If we don't have a usable current request, get rid of any half-baked
|
||||
// request that might be sitting there and make this one current.
|
||||
if (!HaveSize(mCurrentRequest))
|
||||
return PrepareCurrentRequest();
|
||||
|
||||
// Otherwise, make it pending.
|
||||
return PreparePendingRequest();
|
||||
}
|
||||
|
||||
void
|
||||
nsImageLoadingContent::SetBlockedRequest(nsIURI* aURI, PRInt16 aContentDecision)
|
||||
{
|
||||
// Sanity
|
||||
NS_ABORT_IF_FALSE(!NS_CP_ACCEPTED(aContentDecision), "Blocked but not?");
|
||||
|
||||
// We do some slightly illogical stuff here to maintain consistency with
|
||||
// old behavior that people probably depend on. Even in the case where the
|
||||
// new image is blocked, the old one should really be canceled with the
|
||||
// reason "image source changed". However, apparently there's some abuse
|
||||
// over in nsImageFrame where the displaying of the "broken" icon for the
|
||||
// next image depends on the cancel reason of the previous image. ugh.
|
||||
ClearPendingRequest(NS_ERROR_IMAGE_BLOCKED);
|
||||
|
||||
// For the blocked case, we only want to cancel the existing current request
|
||||
// if size is not available. bz says the web depends on this behavior.
|
||||
if (!HaveSize(mCurrentRequest)) {
|
||||
|
||||
mImageBlockingStatus = aContentDecision;
|
||||
ClearCurrentRequest(NS_ERROR_IMAGE_BLOCKED);
|
||||
|
||||
// We still want to remember what URI we were despite not having an actual
|
||||
// request.
|
||||
mCurrentURI = aURI;
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<imgIRequest>&
|
||||
nsImageLoadingContent::PrepareCurrentRequest()
|
||||
{
|
||||
// Blocked images go through SetBlockedRequest, which is a separate path. For
|
||||
// everything else, we're unblocked.
|
||||
mImageBlockingStatus = nsIContentPolicy::ACCEPT;
|
||||
|
||||
// Get rid of anything that was there previously.
|
||||
ClearCurrentRequest(NS_ERROR_IMAGE_SRC_CHANGED);
|
||||
|
||||
// Return a reference.
|
||||
return mCurrentRequest;
|
||||
}
|
||||
|
||||
nsCOMPtr<imgIRequest>&
|
||||
nsImageLoadingContent::PreparePendingRequest()
|
||||
{
|
||||
// Get rid of anything that was there previously.
|
||||
ClearPendingRequest(NS_ERROR_IMAGE_SRC_CHANGED);
|
||||
|
||||
// Return a reference.
|
||||
return mPendingRequest;
|
||||
}
|
||||
|
||||
void
|
||||
nsImageLoadingContent::ClearCurrentRequest(nsresult aReason)
|
||||
{
|
||||
if (!mCurrentRequest) {
|
||||
// Even if we didn't have a current request, we might have been keeping
|
||||
// a URI as a placeholder for a failed load. Clear that now.
|
||||
mCurrentURI = nsnull;
|
||||
return;
|
||||
}
|
||||
NS_ABORT_IF_FALSE(!mCurrentURI,
|
||||
"Shouldn't have both mCurrentRequest and mCurrentURI!");
|
||||
|
||||
// Clean up the request.
|
||||
mCurrentRequest->CancelAndForgetObserver(aReason);
|
||||
mCurrentRequest = nsnull;
|
||||
|
||||
// We only block onload during the decoding of "current" images. This one is
|
||||
// going away, so we should unblock unconditionally here.
|
||||
SetBlockingOnload(PR_FALSE);
|
||||
}
|
||||
|
||||
void
|
||||
nsImageLoadingContent::ClearPendingRequest(nsresult aReason)
|
||||
{
|
||||
if (!mPendingRequest)
|
||||
return;
|
||||
mPendingRequest->CancelAndForgetObserver(aReason);
|
||||
mPendingRequest = nsnull;
|
||||
}
|
||||
|
||||
bool
|
||||
nsImageLoadingContent::HaveSize(imgIRequest *aImage)
|
||||
{
|
||||
// Handle the null case
|
||||
if (!aImage)
|
||||
return false;
|
||||
|
||||
// Query the image
|
||||
PRUint32 status;
|
||||
nsresult rv = aImage->GetImageStatus(&status);
|
||||
return (NS_SUCCEEDED(rv) && (status & imgIRequest::STATUS_SIZE_AVAILABLE));
|
||||
}
|
||||
|
||||
void
|
||||
nsImageLoadingContent::SetBlockingOnload(PRBool aBlocking)
|
||||
{
|
||||
|
@ -940,7 +952,7 @@ nsImageLoadingContent::CreateStaticImageClone(nsImageLoadingContent* aDest) cons
|
|||
aDest->mForcedImageState = mForcedImageState;
|
||||
aDest->mImageBlockingStatus = mImageBlockingStatus;
|
||||
aDest->mLoadingEnabled = mLoadingEnabled;
|
||||
aDest->mStartingLoad = mStartingLoad;
|
||||
aDest->mStateChangerDepth = mStateChangerDepth;
|
||||
aDest->mIsImageStateForced = mIsImageStateForced;
|
||||
aDest->mLoading = mLoading;
|
||||
aDest->mBroken = mBroken;
|
||||
|
|
|
@ -189,13 +189,11 @@ private:
|
|||
mImageContent(aImageContent),
|
||||
mNotify(aNotify)
|
||||
{
|
||||
NS_ASSERTION(!mImageContent->mStartingLoad,
|
||||
"Nested AutoStateChangers somehow?");
|
||||
mImageContent->mStartingLoad = PR_TRUE;
|
||||
mImageContent->mStateChangerDepth++;
|
||||
}
|
||||
~AutoStateChanger()
|
||||
{
|
||||
mImageContent->mStartingLoad = PR_FALSE;
|
||||
mImageContent->mStateChangerDepth--;
|
||||
mImageContent->UpdateImageState(mNotify);
|
||||
}
|
||||
|
||||
|
@ -248,9 +246,50 @@ private:
|
|||
protected:
|
||||
void CreateStaticImageClone(nsImageLoadingContent* aDest) const;
|
||||
|
||||
/**
|
||||
* Prepare and returns a reference to the "next request". If there's already
|
||||
* a _usable_ current request (one with SIZE_AVAILABLE), this request is
|
||||
* "pending" until it becomes usable. Otherwise, this becomes the current
|
||||
* request.
|
||||
*/
|
||||
nsCOMPtr<imgIRequest>& PrepareNextRequest();
|
||||
|
||||
/**
|
||||
* Called when we would normally call PrepareNextRequest(), but the request was
|
||||
* blocked.
|
||||
*/
|
||||
void SetBlockedRequest(nsIURI* aURI, PRInt16 aContentDecision);
|
||||
|
||||
/**
|
||||
* Returns a COMPtr reference to the current/pending image requests, cleaning
|
||||
* up and canceling anything that was there before. Note that if you just want
|
||||
* to get rid of one of the requests, you should call
|
||||
* Clear*Request(NS_BINDING_ABORTED) instead, since it passes a more appropriate
|
||||
* aReason than Prepare*Request() does (NS_ERROR_IMAGE_SRC_CHANGED).
|
||||
*/
|
||||
nsCOMPtr<imgIRequest>& PrepareCurrentRequest();
|
||||
nsCOMPtr<imgIRequest>& PreparePendingRequest();
|
||||
|
||||
/**
|
||||
* Cancels and nulls-out the "current" and "pending" requests if they exist.
|
||||
*/
|
||||
void ClearCurrentRequest(nsresult aReason);
|
||||
void ClearPendingRequest(nsresult aReason);
|
||||
|
||||
/**
|
||||
* Static helper method to tell us if we have the size of a request. The
|
||||
* image may be null.
|
||||
*/
|
||||
static bool HaveSize(imgIRequest *aImage);
|
||||
|
||||
/* MEMBERS */
|
||||
nsCOMPtr<imgIRequest> mCurrentRequest;
|
||||
nsCOMPtr<imgIRequest> mPendingRequest;
|
||||
|
||||
// If the image was blocked or if there was an error loading, it's nice to
|
||||
// still keep track of what the URI was despite not having an imgIRequest.
|
||||
// We only maintain this in those situations (in the common case, this is
|
||||
// always null).
|
||||
nsCOMPtr<nsIURI> mCurrentURI;
|
||||
|
||||
private:
|
||||
|
@ -272,7 +311,6 @@ private:
|
|||
|
||||
PRInt16 mImageBlockingStatus;
|
||||
PRPackedBool mLoadingEnabled : 1;
|
||||
PRPackedBool mStartingLoad : 1;
|
||||
|
||||
/**
|
||||
* When true, we return mForcedImageState from ImageState().
|
||||
|
@ -292,6 +330,9 @@ private:
|
|||
* Whether we're currently blocking document load.
|
||||
*/
|
||||
PRPackedBool mBlockingOnload : 1;
|
||||
|
||||
/* The number of nested AutoStateChangers currently tracking our state. */
|
||||
PRUint8 mStateChangerDepth;
|
||||
};
|
||||
|
||||
#endif // nsImageLoadingContent_h__
|
||||
|
|
|
@ -103,6 +103,10 @@ NS_NewDOMSVGEvent(nsIDOMEvent** aResult, nsPresContext* aPresContext, class nsEv
|
|||
nsresult
|
||||
NS_NewDOMSVGZoomEvent(nsIDOMEvent** aResult, nsPresContext* aPresContext, class nsGUIEvent* aEvent);
|
||||
#endif // MOZ_SVG
|
||||
#ifdef MOZ_SMIL
|
||||
nsresult
|
||||
NS_NewDOMTimeEvent(nsIDOMEvent** aResult, nsPresContext* aPresContext, class nsEvent* aEvent);
|
||||
#endif // MOZ_SMIL
|
||||
nsresult
|
||||
NS_NewDOMXULCommandEvent(nsIDOMEvent** aResult, nsPresContext* aPresContext, class nsInputEvent* aEvent);
|
||||
nsresult
|
||||
|
|
|
@ -81,6 +81,9 @@ static const char* const sEventNames[] = {
|
|||
"SVGLoad", "SVGUnload", "SVGAbort", "SVGError", "SVGResize", "SVGScroll",
|
||||
"SVGZoom",
|
||||
#endif // MOZ_SVG
|
||||
#ifdef MOZ_SMIL
|
||||
"beginEvent", "endEvent", "repeatEvent",
|
||||
#endif // MOZ_SMIL
|
||||
#ifdef MOZ_MEDIA
|
||||
"loadstart", "progress", "suspend", "emptied", "stalled", "play", "pause",
|
||||
"loadedmetadata", "loadeddata", "waiting", "playing", "canplay",
|
||||
|
@ -773,6 +776,15 @@ NS_METHOD nsDOMEvent::DuplicatePrivateData()
|
|||
break;
|
||||
}
|
||||
#endif // MOZ_SVG
|
||||
#ifdef MOZ_SMIL
|
||||
case NS_SMIL_TIME_EVENT:
|
||||
{
|
||||
newEvent = new nsUIEvent(PR_FALSE, msg, 0);
|
||||
NS_ENSURE_TRUE(newEvent, NS_ERROR_OUT_OF_MEMORY);
|
||||
newEvent->eventStructType = NS_SMIL_TIME_EVENT;
|
||||
break;
|
||||
}
|
||||
#endif // MOZ_SMIL
|
||||
case NS_SIMPLE_GESTURE_EVENT:
|
||||
{
|
||||
nsSimpleGestureEvent* oldSimpleGestureEvent = static_cast<nsSimpleGestureEvent*>(mEvent);
|
||||
|
@ -1225,6 +1237,14 @@ const char* nsDOMEvent::GetEventName(PRUint32 aEventType)
|
|||
case NS_SVG_ZOOM:
|
||||
return sEventNames[eDOMEvents_SVGZoom];
|
||||
#endif // MOZ_SVG
|
||||
#ifdef MOZ_SMIL
|
||||
case NS_SMIL_BEGIN:
|
||||
return sEventNames[eDOMEvents_beginEvent];
|
||||
case NS_SMIL_END:
|
||||
return sEventNames[eDOMEvents_endEvent];
|
||||
case NS_SMIL_REPEAT:
|
||||
return sEventNames[eDOMEvents_repeatEvent];
|
||||
#endif // MOZ_SMIL
|
||||
#ifdef MOZ_MEDIA
|
||||
case NS_LOADSTART:
|
||||
return sEventNames[eDOMEvents_loadstart];
|
||||
|
|
|
@ -142,6 +142,11 @@ public:
|
|||
eDOMEvents_SVGScroll,
|
||||
eDOMEvents_SVGZoom,
|
||||
#endif // MOZ_SVG
|
||||
#ifdef MOZ_SMIL
|
||||
eDOMEvents_beginEvent,
|
||||
eDOMEvents_endEvent,
|
||||
eDOMEvents_repeatEvent,
|
||||
#endif // MOZ_SMIL
|
||||
#ifdef MOZ_MEDIA
|
||||
eDOMEvents_loadstart,
|
||||
eDOMEvents_progress,
|
||||
|
|
|
@ -742,6 +742,10 @@ nsEventDispatcher::CreateEvent(nsPresContext* aPresContext,
|
|||
return NS_NewDOMSVGZoomEvent(aDOMEvent, aPresContext,
|
||||
static_cast<nsGUIEvent*>(aEvent));
|
||||
#endif // MOZ_SVG
|
||||
#ifdef MOZ_SMIL
|
||||
case NS_SMIL_TIME_EVENT:
|
||||
return NS_NewDOMTimeEvent(aDOMEvent, aPresContext, aEvent);
|
||||
#endif // MOZ_SMIL
|
||||
|
||||
case NS_COMMAND_EVENT:
|
||||
return NS_NewDOMCommandEvent(aDOMEvent, aPresContext,
|
||||
|
@ -797,6 +801,11 @@ nsEventDispatcher::CreateEvent(nsPresContext* aPresContext,
|
|||
aEventType.LowerCaseEqualsLiteral("svgzoomevents"))
|
||||
return NS_NewDOMSVGZoomEvent(aDOMEvent, aPresContext, nsnull);
|
||||
#endif // MOZ_SVG
|
||||
#ifdef MOZ_SMIL
|
||||
if (aEventType.LowerCaseEqualsLiteral("timeevent") ||
|
||||
aEventType.LowerCaseEqualsLiteral("timeevents"))
|
||||
return NS_NewDOMTimeEvent(aDOMEvent, aPresContext, nsnull);
|
||||
#endif // MOZ_SMIL
|
||||
if (aEventType.LowerCaseEqualsLiteral("xulcommandevent") ||
|
||||
aEventType.LowerCaseEqualsLiteral("xulcommandevents"))
|
||||
return NS_NewDOMXULCommandEvent(aDOMEvent, aPresContext, nsnull);
|
||||
|
|
|
@ -983,6 +983,14 @@ nsEventListenerManager::CompileEventHandlerInternal(nsIScriptContext *aContext,
|
|||
else if (aName == nsGkAtoms::onSVGZoom)
|
||||
attrName = nsGkAtoms::onzoom;
|
||||
#endif // MOZ_SVG
|
||||
#ifdef MOZ_SMIL
|
||||
else if (aName == nsGkAtoms::onbeginEvent)
|
||||
attrName = nsGkAtoms::onbegin;
|
||||
else if (aName == nsGkAtoms::onrepeatEvent)
|
||||
attrName = nsGkAtoms::onrepeat;
|
||||
else if (aName == nsGkAtoms::onendEvent)
|
||||
attrName = nsGkAtoms::onend;
|
||||
#endif // MOZ_SMIL
|
||||
|
||||
content->GetAttr(kNameSpaceID_None, attrName, handlerBody);
|
||||
|
||||
|
|
|
@ -54,6 +54,7 @@ EXPORTS = nsSMILKeySpline.h
|
|||
|
||||
ifdef MOZ_SMIL
|
||||
CPPSRCS += \
|
||||
nsDOMTimeEvent.cpp \
|
||||
nsSMILAnimationController.cpp \
|
||||
nsSMILAnimationFunction.cpp \
|
||||
nsSMILCompositor.cpp \
|
||||
|
@ -105,6 +106,7 @@ EXPORTS += \
|
|||
INCLUDES += \
|
||||
-I$(srcdir)/../base/src \
|
||||
-I$(srcdir)/../../layout/style \
|
||||
-I$(srcdir)/../events/src \
|
||||
$(NULL)
|
||||
endif # MOZ_SMIL
|
||||
|
||||
|
|
|
@ -0,0 +1,130 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Mozilla SMIL Module.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Brian Birtles <birtles@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsDOMTimeEvent.h"
|
||||
#include "nsGUIEvent.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
#include "nsIDOMAbstractView.h"
|
||||
|
||||
nsDOMTimeEvent::nsDOMTimeEvent(nsPresContext* aPresContext, nsEvent* aEvent)
|
||||
: nsDOMEvent(aPresContext, aEvent ? aEvent : new nsUIEvent(PR_FALSE, 0, 0)),
|
||||
mDetail(0)
|
||||
{
|
||||
if (aEvent) {
|
||||
mEventIsInternal = PR_FALSE;
|
||||
} else {
|
||||
mEventIsInternal = PR_TRUE;
|
||||
mEvent->eventStructType = NS_SMIL_TIME_EVENT;
|
||||
}
|
||||
|
||||
if (mEvent->eventStructType == NS_SMIL_TIME_EVENT) {
|
||||
nsUIEvent* event = static_cast<nsUIEvent*>(mEvent);
|
||||
mDetail = event->detail;
|
||||
}
|
||||
|
||||
mEvent->flags |= NS_EVENT_FLAG_CANT_BUBBLE |
|
||||
NS_EVENT_FLAG_CANT_CANCEL;
|
||||
|
||||
if (mPresContext) {
|
||||
nsCOMPtr<nsISupports> container = mPresContext->GetContainer();
|
||||
if (container) {
|
||||
nsCOMPtr<nsIDOMWindowInternal> window = do_GetInterface(container);
|
||||
if (window) {
|
||||
mView = do_QueryInterface(window);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMTimeEvent)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDOMTimeEvent, nsDOMEvent)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mView)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsDOMTimeEvent, nsDOMEvent)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mView)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(nsDOMTimeEvent, nsDOMEvent)
|
||||
NS_IMPL_RELEASE_INHERITED(nsDOMTimeEvent, nsDOMEvent)
|
||||
|
||||
DOMCI_DATA(TimeEvent, nsDOMTimeEvent)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsDOMTimeEvent)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMTimeEvent)
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(TimeEvent)
|
||||
NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMTimeEvent::GetView(nsIDOMAbstractView** aView)
|
||||
{
|
||||
*aView = mView;
|
||||
NS_IF_ADDREF(*aView);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMTimeEvent::GetDetail(PRInt32* aDetail)
|
||||
{
|
||||
*aDetail = mDetail;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMTimeEvent::InitTimeEvent(const nsAString& aTypeArg,
|
||||
nsIDOMAbstractView* aViewArg,
|
||||
PRInt32 aDetailArg)
|
||||
{
|
||||
nsresult rv = nsDOMEvent::InitEvent(aTypeArg, PR_FALSE /*doesn't bubble*/,
|
||||
PR_FALSE /*can't cancel*/);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mDetail = aDetailArg;
|
||||
mView = aViewArg;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult NS_NewDOMTimeEvent(nsIDOMEvent** aInstancePtrResult,
|
||||
nsPresContext* aPresContext,
|
||||
nsEvent* aEvent)
|
||||
{
|
||||
nsDOMTimeEvent* it = new nsDOMTimeEvent(aPresContext, aEvent);
|
||||
return CallQueryInterface(it, aInstancePtrResult);
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Mozilla SMIL Module.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Brian Birtles <birtles@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef NS_DOMTIMEEVENT_H_
|
||||
#define NS_DOMTIMEEVENT_H_
|
||||
|
||||
#include "nsIDOMTimeEvent.h"
|
||||
#include "nsDOMEvent.h"
|
||||
|
||||
class nsDOMTimeEvent : public nsDOMEvent,
|
||||
public nsIDOMTimeEvent
|
||||
{
|
||||
public:
|
||||
nsDOMTimeEvent(nsPresContext* aPresContext, nsEvent* aEvent);
|
||||
|
||||
// nsISupports interface:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsDOMTimeEvent, nsDOMEvent)
|
||||
|
||||
// nsIDOMTimeEvent interface:
|
||||
NS_DECL_NSIDOMTIMEEVENT
|
||||
|
||||
// Forward to base class
|
||||
NS_FORWARD_TO_NSDOMEVENT
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIDOMAbstractView> mView;
|
||||
PRInt32 mDetail;
|
||||
};
|
||||
|
||||
#endif // NS_DOMTIMEEVENT_H_
|
|
@ -43,15 +43,19 @@
|
|||
#include "nsSMILParserUtils.h"
|
||||
#include "nsSMILTimeContainer.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsGUIEvent.h"
|
||||
#include "nsEventDispatcher.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsMathUtils.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "prdtoa.h"
|
||||
#include "plstr.h"
|
||||
#include "prtime.h"
|
||||
#include "nsString.h"
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Helper classes -- InstanceTimeComparator
|
||||
// Helper class: InstanceTimeComparator
|
||||
|
||||
// Upon inserting an instance time into one of our instance time lists we assign
|
||||
// it a serial number. This allows us to sort the instance times in such a way
|
||||
|
@ -90,6 +94,43 @@ nsSMILTimedElement::InstanceTimeComparator::LessThan(
|
|||
return cmp == 0 ? aElem1->Serial() < aElem2->Serial() : cmp < 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Helper class: AsyncTimeEventRunner
|
||||
|
||||
namespace
|
||||
{
|
||||
class AsyncTimeEventRunner : public nsRunnable
|
||||
{
|
||||
protected:
|
||||
nsRefPtr<nsIContent> mTarget;
|
||||
PRUint32 mMsg;
|
||||
PRInt32 mDetail;
|
||||
|
||||
public:
|
||||
AsyncTimeEventRunner(nsIContent* aTarget, PRUint32 aMsg, PRInt32 aDetail)
|
||||
: mTarget(aTarget), mMsg(aMsg), mDetail(aDetail)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
nsUIEvent event(PR_TRUE, mMsg, mDetail);
|
||||
event.eventStructType = NS_SMIL_TIME_EVENT;
|
||||
|
||||
nsPresContext* context = nsnull;
|
||||
nsIDocument* doc = mTarget->GetCurrentDoc();
|
||||
if (doc) {
|
||||
nsCOMPtr<nsIPresShell> shell = doc->GetShell();
|
||||
if (shell) {
|
||||
context = shell->GetPresContext();
|
||||
}
|
||||
}
|
||||
|
||||
return nsEventDispatcher::Dispatch(mTarget, context, &event);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Templated helper functions
|
||||
|
||||
|
@ -150,6 +191,7 @@ nsSMILTimedElement::nsSMILTimedElement()
|
|||
mInstanceSerialIndex(0),
|
||||
mClient(nsnull),
|
||||
mCurrentInterval(nsnull),
|
||||
mCurrentRepeatIteration(0),
|
||||
mPrevRegisteredMilestone(sMaxMilestone),
|
||||
mElementState(STATE_STARTUP),
|
||||
mSeekState(SEEK_NOT_SEEKING)
|
||||
|
@ -506,20 +548,21 @@ nsSMILTimedElement::DoSampleAt(nsSMILTime aContainerTime, PRBool aEndOnly)
|
|||
if (mCurrentInterval->Begin()->Time() <= sampleTime) {
|
||||
mElementState = STATE_ACTIVE;
|
||||
mCurrentInterval->FixBegin();
|
||||
if (HasPlayed()) {
|
||||
Reset(); // Apply restart behaviour
|
||||
}
|
||||
if (mClient) {
|
||||
mClient->Activate(mCurrentInterval->Begin()->Time().GetMillis());
|
||||
}
|
||||
if (mSeekState == SEEK_NOT_SEEKING) {
|
||||
FireTimeEventAsync(NS_SMIL_BEGIN, 0);
|
||||
}
|
||||
if (HasPlayed()) {
|
||||
Reset(); // Apply restart behaviour
|
||||
// The call to Reset() may mean that the end point of our current
|
||||
// interval should be changed and so we should update the interval
|
||||
// now. However, calling UpdateCurrentInterval could result in the
|
||||
// interval getting deleted (perhaps through some web of syncbase
|
||||
// dependencies) therefore we make updating the interval the last
|
||||
// thing we do. There is no guarantee that mCurrentInterval.IsSet()
|
||||
// is true after this.
|
||||
// thing we do. There is no guarantee that mCurrentInterval is set
|
||||
// after this.
|
||||
UpdateCurrentInterval();
|
||||
}
|
||||
stateChanged = PR_TRUE;
|
||||
|
@ -541,6 +584,10 @@ nsSMILTimedElement::DoSampleAt(nsSMILTime aContainerTime, PRBool aEndOnly)
|
|||
mClient->Inactivate(mFillMode == FILL_FREEZE);
|
||||
}
|
||||
mCurrentInterval->FixEnd();
|
||||
if (mSeekState == SEEK_NOT_SEEKING) {
|
||||
FireTimeEventAsync(NS_SMIL_END, 0);
|
||||
}
|
||||
mCurrentRepeatIteration = 0;
|
||||
mOldIntervals.AppendElement(mCurrentInterval.forget());
|
||||
// We must update mOldIntervals before calling SampleFillValue
|
||||
SampleFillValue();
|
||||
|
@ -556,6 +603,19 @@ nsSMILTimedElement::DoSampleAt(nsSMILTime aContainerTime, PRBool aEndOnly)
|
|||
"Sample time should not precede current interval");
|
||||
nsSMILTime activeTime = aContainerTime - beginTime;
|
||||
SampleSimpleTime(activeTime);
|
||||
// We register our repeat times as milestones (except when we're
|
||||
// seeking) so we should get a sample at exactly the time we repeat.
|
||||
// (And even when we are seeking we want to update
|
||||
// mCurrentRepeatIteration so we do that first before testing the seek
|
||||
// state.)
|
||||
PRUint32 prevRepeatIteration = mCurrentRepeatIteration;
|
||||
if (ActiveTimeToSimpleTime(activeTime, mCurrentRepeatIteration)==0 &&
|
||||
mCurrentRepeatIteration != prevRepeatIteration &&
|
||||
mCurrentRepeatIteration &&
|
||||
mSeekState == SEEK_NOT_SEEKING) {
|
||||
FireTimeEventAsync(NS_SMIL_REPEAT,
|
||||
static_cast<PRInt32>(mCurrentRepeatIteration));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -607,6 +667,7 @@ nsSMILTimedElement::Rewind()
|
|||
// Set the STARTUP state first so that if we get any callbacks we won't waste
|
||||
// time recalculating the current interval
|
||||
mElementState = STATE_STARTUP;
|
||||
mCurrentRepeatIteration = 0;
|
||||
|
||||
// Clear the intervals and instance times except those instance times we can't
|
||||
// regenerate (DOM calls etc.)
|
||||
|
@ -1238,13 +1299,6 @@ nsSMILTimedElement::Reset()
|
|||
void
|
||||
nsSMILTimedElement::DoPostSeek()
|
||||
{
|
||||
// XXX When implementing TimeEvents we'll need to compare mElementState with
|
||||
// mSeekState and dispatch events as follows:
|
||||
// ACTIVE->INACTIVE: End event
|
||||
// INACTIVE->ACTIVE: Begin event
|
||||
// ACTIVE->ACTIVE: Nothing (even if they're different intervals)
|
||||
// INACTIVE->INACTIVE: Nothing (even if we've skipped intervals)
|
||||
|
||||
// Finish backwards seek
|
||||
if (mSeekState == SEEK_BACKWARD_FROM_INACTIVE ||
|
||||
mSeekState == SEEK_BACKWARD_FROM_ACTIVE) {
|
||||
|
@ -1266,6 +1320,34 @@ nsSMILTimedElement::DoPostSeek()
|
|||
UpdateCurrentInterval();
|
||||
}
|
||||
|
||||
// XXX
|
||||
// Note that SMIL gives the very cryptic description:
|
||||
// The associated time for the event is the document time before the seek.
|
||||
// This action does not resolve any times in the instance times list for end
|
||||
// times.
|
||||
//
|
||||
// The second sentence was added as a clarification in a SMIL 2.0 erratum.
|
||||
// Presumably the intention is that we fire the event as implemented below but
|
||||
// don't act on it. This makes sense at least for dependencies within the same
|
||||
// time container. So we'll probably need to set a flag here to ensure we
|
||||
// don't actually act on it when we implement event-based timing.
|
||||
switch (mSeekState)
|
||||
{
|
||||
case SEEK_FORWARD_FROM_ACTIVE:
|
||||
case SEEK_BACKWARD_FROM_ACTIVE:
|
||||
if (mElementState != STATE_ACTIVE) {
|
||||
FireTimeEventAsync(NS_SMIL_END, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case SEEK_FORWARD_FROM_INACTIVE:
|
||||
case SEEK_BACKWARD_FROM_INACTIVE:
|
||||
if (mElementState == STATE_ACTIVE) {
|
||||
FireTimeEventAsync(NS_SMIL_BEGIN, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
mSeekState = SEEK_NOT_SEEKING;
|
||||
}
|
||||
|
||||
|
@ -1861,10 +1943,6 @@ nsSMILTimedElement::GetNextMilestone(nsSMILMilestone& aNextMilestone) const
|
|||
{
|
||||
// Return the next key moment in our lifetime.
|
||||
//
|
||||
// XXX Once we implement TimeEvents and event based timing we might need to
|
||||
// include repeat times too, particularly if it's important to get them in
|
||||
// order.
|
||||
//
|
||||
// XXX It may be possible in future to optimise this so that we only register
|
||||
// for milestones if:
|
||||
// a) We have time dependents, or
|
||||
|
@ -1896,22 +1974,27 @@ nsSMILTimedElement::GetNextMilestone(nsSMILMilestone& aNextMilestone) const
|
|||
|
||||
case STATE_ACTIVE:
|
||||
{
|
||||
// XXX When we implement TimeEvents, we may need to consider what comes
|
||||
// next: the interval end or an interval repeat.
|
||||
// Work out what comes next: the interval end or the next repeat iteration
|
||||
nsSMILTimeValue nextRepeat;
|
||||
if (mSeekState == SEEK_NOT_SEEKING && mSimpleDur.IsResolved()) {
|
||||
nextRepeat.SetMillis(mCurrentInterval->Begin()->Time().GetMillis() +
|
||||
(mCurrentRepeatIteration + 1) * mSimpleDur.GetMillis());
|
||||
}
|
||||
nsSMILTimeValue nextMilestone =
|
||||
NS_MIN(mCurrentInterval->End()->Time(), nextRepeat);
|
||||
|
||||
// Check for an early end
|
||||
nsSMILInstanceTime* earlyEnd =
|
||||
CheckForEarlyEnd(mCurrentInterval->End()->Time());
|
||||
// Check for an early end before that time
|
||||
nsSMILInstanceTime* earlyEnd = CheckForEarlyEnd(nextMilestone);
|
||||
if (earlyEnd) {
|
||||
aNextMilestone.mIsEnd = PR_TRUE;
|
||||
aNextMilestone.mTime = earlyEnd->Time().GetMillis();
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
// Otherwise it's just the next interval end
|
||||
if (mCurrentInterval->End()->Time().IsResolved()) {
|
||||
aNextMilestone.mIsEnd = PR_TRUE;
|
||||
aNextMilestone.mTime = mCurrentInterval->End()->Time().GetMillis();
|
||||
// Apply the previously calculated milestone
|
||||
if (nextMilestone.IsResolved()) {
|
||||
aNextMilestone.mIsEnd = nextMilestone != nextRepeat;
|
||||
aNextMilestone.mTime = nextMilestone.GetMillis();
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
|
@ -1958,6 +2041,17 @@ nsSMILTimedElement::NotifyChangedInterval()
|
|||
mCurrentInterval->NotifyChanged(container);
|
||||
}
|
||||
|
||||
void
|
||||
nsSMILTimedElement::FireTimeEventAsync(PRUint32 aMsg, PRInt32 aDetail)
|
||||
{
|
||||
if (!mAnimationElement)
|
||||
return;
|
||||
|
||||
nsCOMPtr<nsIRunnable> event =
|
||||
new AsyncTimeEventRunner(&mAnimationElement->Content(), aMsg, aDetail);
|
||||
NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
const nsSMILInstanceTime*
|
||||
nsSMILTimedElement::GetEffectiveBeginInstance() const
|
||||
{
|
||||
|
|
|
@ -482,6 +482,7 @@ protected:
|
|||
|
||||
void NotifyNewInterval();
|
||||
void NotifyChangedInterval();
|
||||
void FireTimeEventAsync(PRUint32 aMsg, PRInt32 aDetail);
|
||||
const nsSMILInstanceTime* GetEffectiveBeginInstance() const;
|
||||
const nsSMILInterval* GetPreviousInterval() const;
|
||||
PRBool HasPlayed() const { return !mOldIntervals.IsEmpty(); }
|
||||
|
@ -539,6 +540,7 @@ protected:
|
|||
nsSMILAnimationFunction* mClient;
|
||||
nsAutoPtr<nsSMILInterval> mCurrentInterval;
|
||||
IntervalList mOldIntervals;
|
||||
PRUint32 mCurrentRepeatIteration;
|
||||
nsSMILMilestone mPrevRegisteredMilestone;
|
||||
static const nsSMILMilestone sMaxMilestone;
|
||||
static const PRUint8 sMaxNumIntervals;
|
||||
|
|
|
@ -82,6 +82,7 @@ _TEST_FILES = \
|
|||
test_smilSyncbaseTarget.xhtml \
|
||||
test_smilSyncTransform.xhtml \
|
||||
test_smilTextZoom.xhtml \
|
||||
test_smilTimeEvents.xhtml \
|
||||
test_smilTiming.xhtml \
|
||||
test_smilTimingZeroIntervals.xhtml \
|
||||
test_smilUpdatedInterval.xhtml \
|
||||
|
|
|
@ -0,0 +1,292 @@
|
|||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=572270
|
||||
-->
|
||||
<head>
|
||||
<title>Test TimeEvents dispatching</title>
|
||||
<script type="text/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=572270">Mozilla Bug
|
||||
572270</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
<svg id="svg" xmlns="http://www.w3.org/2000/svg" width="100px" height="100px">
|
||||
<g font-size="10px">
|
||||
<circle cx="0" cy="0" r="15" fill="blue" id="circle"
|
||||
onbegin="parentHandler(evt)" onrepeat="parentHandler(evt)"
|
||||
onend="parentHandler(evt)">
|
||||
<animate attributeName="cy" from="0" to="100" dur="60s" begin="2s"
|
||||
id="anim" repeatCount="2"
|
||||
onbegin="handleOnBegin(evt)" onrepeat="handleOnRepeat(evt)"
|
||||
onend="handleOnEnd(evt)"/>
|
||||
</circle>
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
<![CDATA[
|
||||
/** Test SMIL TimeEvents dispatching **/
|
||||
|
||||
/* Global Variables */
|
||||
const gTimeoutDur = 5000; // Time until we give up waiting for events in ms
|
||||
var gSvg = document.getElementById("svg");
|
||||
var gAnim = document.getElementById('anim');
|
||||
var gCircle = document.getElementById('circle');
|
||||
var gExpectedEvents = new Array();
|
||||
var gTimeoutID;
|
||||
var gTestStages =
|
||||
[ testPlaybackBegin,
|
||||
testPlaybackRepeat,
|
||||
testPlaybackEnd,
|
||||
testForwardsSeekToMid,
|
||||
testForwardsSeekToNextInterval,
|
||||
testForwardsSeekPastEnd,
|
||||
testBackwardsSeekToMid,
|
||||
testBackwardsSeekToStart,
|
||||
testCreateEvent,
|
||||
testRegistration
|
||||
];
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function continueTest()
|
||||
{
|
||||
if (gTestStages.length == 0) {
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
gTestStages.shift()();
|
||||
}
|
||||
|
||||
function testPlaybackBegin()
|
||||
{
|
||||
// Test events are dispatched through normal playback
|
||||
gSvg.pauseAnimations();
|
||||
gSvg.setCurrentTime(1.99);
|
||||
gExpectedEvents.push("beginEvent", "beginEvent"); // Two registered handlers
|
||||
gTimeoutID = setTimeout(timeoutFail, gTimeoutDur);
|
||||
gSvg.unpauseAnimations();
|
||||
}
|
||||
|
||||
function testPlaybackRepeat()
|
||||
{
|
||||
gSvg.pauseAnimations();
|
||||
gSvg.setCurrentTime(61.99);
|
||||
gExpectedEvents.push(["repeatEvent", 1], ["repeatEvent", 1]);
|
||||
gTimeoutID = setTimeout(timeoutFail, gTimeoutDur);
|
||||
gSvg.unpauseAnimations();
|
||||
}
|
||||
|
||||
function testPlaybackEnd()
|
||||
{
|
||||
gSvg.pauseAnimations();
|
||||
gSvg.setCurrentTime(121.99);
|
||||
gExpectedEvents.push("endEvent", "endEvent");
|
||||
gTimeoutID = setTimeout(timeoutFail, gTimeoutDur);
|
||||
gSvg.unpauseAnimations();
|
||||
}
|
||||
|
||||
function testForwardsSeekToMid()
|
||||
{
|
||||
gSvg.pauseAnimations();
|
||||
// Set animation parameters to something that repeats a lot
|
||||
gSvg.setCurrentTime(0);
|
||||
gAnim.setAttribute('begin', '2s; 102s');
|
||||
gAnim.setAttribute('dur', '15s');
|
||||
gAnim.setAttribute('repeatCount', '6');
|
||||
gSvg.setCurrentTime(46.99);
|
||||
gExpectedEvents.push("beginEvent", "beginEvent",
|
||||
["repeatEvent", 3], ["repeatEvent", 3]);
|
||||
gTimeoutID = setTimeout(timeoutFail, gTimeoutDur);
|
||||
gSvg.unpauseAnimations();
|
||||
}
|
||||
|
||||
function testForwardsSeekToNextInterval()
|
||||
{
|
||||
// Skip to next interval -- we shouldn't get any additional begin or end
|
||||
// events in between
|
||||
gSvg.pauseAnimations();
|
||||
gSvg.setCurrentTime(131.99);
|
||||
gExpectedEvents.push(["repeatEvent", 2], ["repeatEvent", 2]);
|
||||
gTimeoutID = setTimeout(timeoutFail, gTimeoutDur);
|
||||
gSvg.unpauseAnimations();
|
||||
}
|
||||
|
||||
function testForwardsSeekPastEnd()
|
||||
{
|
||||
gSvg.pauseAnimations();
|
||||
gSvg.setCurrentTime(200);
|
||||
gExpectedEvents.push("endEvent", "endEvent");
|
||||
gTimeoutID = setTimeout(timeoutFail, gTimeoutDur);
|
||||
gSvg.unpauseAnimations();
|
||||
}
|
||||
|
||||
function testBackwardsSeekToMid()
|
||||
{
|
||||
gSvg.pauseAnimations();
|
||||
gSvg.setCurrentTime(31.99);
|
||||
gExpectedEvents.push("beginEvent", "beginEvent",
|
||||
["repeatEvent", 2], ["repeatEvent", 2]);
|
||||
gTimeoutID = setTimeout(timeoutFail, gTimeoutDur);
|
||||
gSvg.unpauseAnimations();
|
||||
}
|
||||
|
||||
function testBackwardsSeekToStart()
|
||||
{
|
||||
gSvg.pauseAnimations();
|
||||
gExpectedEvents.push("endEvent", "endEvent");
|
||||
gTimeoutID = setTimeout(timeoutFail, gTimeoutDur);
|
||||
gSvg.setCurrentTime(0);
|
||||
}
|
||||
|
||||
function testCreateEvent()
|
||||
{
|
||||
var evt;
|
||||
try {
|
||||
evt = document.createEvent("TimeEvents");
|
||||
} catch (e) {
|
||||
ok(false, "Failed to create TimeEvent via script: " + e);
|
||||
return;
|
||||
}
|
||||
evt.initTimeEvent("repeatEvent", null, 3);
|
||||
is(evt.type, "repeatEvent", "Unexpected type for user-generated event");
|
||||
is(evt.detail, 3, "Unexpected detail for user-generated event");
|
||||
is(evt.target, null, "Unexpected event target");
|
||||
is(evt.currentTarget, null, "Unexpected event current target");
|
||||
is(evt.eventPhase, evt.AT_TARGET);
|
||||
is(evt.bubbles, false, "Event should not bubble");
|
||||
is(evt.cancelable, false, "Event should not be cancelable");
|
||||
is(evt.view, null, "Event view should be null");
|
||||
|
||||
// Prior to dispatch we should be able to change the event type
|
||||
evt.initTimeEvent("beginEvent", document.defaultView, 0);
|
||||
is(evt.type, "beginEvent", "Failed to update event type before dispatch");
|
||||
is(evt.detail, 0, "Failed to update event detail before dispatch");
|
||||
is(evt.view, document.defaultView, "Event view should be set");
|
||||
|
||||
// But not directly as it's readonly
|
||||
try {
|
||||
evt.type = "endEvent";
|
||||
} catch(e) { }
|
||||
is(evt.type, "beginEvent", "Event type should be readonly");
|
||||
|
||||
// Likewise the detail field should be readonly
|
||||
try {
|
||||
evt.detail = "8";
|
||||
} catch(e) { }
|
||||
is(evt.detail, 0, "Event detail should be readonly");
|
||||
|
||||
// Dispatch
|
||||
gExpectedEvents.push("beginEvent", "beginEvent");
|
||||
gTimeoutID = setTimeout(timeoutFail, gTimeoutDur);
|
||||
gAnim.dispatchEvent(evt);
|
||||
}
|
||||
|
||||
function testRegistration()
|
||||
{
|
||||
gSvg.pauseAnimations();
|
||||
// Reset animation to something simple
|
||||
gSvg.setCurrentTime(0);
|
||||
gAnim.setAttribute('begin', '2s');
|
||||
gAnim.setAttribute('dur', '50s');
|
||||
|
||||
// Remove attribute handler
|
||||
gAnim.removeAttribute('onbegin');
|
||||
|
||||
// Add bogus handlers
|
||||
gAnim.setAttribute('onbeginElement', 'handleOnBegin(evt)');
|
||||
gAnim.addEventListener("begin", handleOnBegin, false);
|
||||
gAnim.addEventListener("onbegin", handleOnBegin, false);
|
||||
|
||||
// We should now have just one legitimate listener: the one registered to
|
||||
// handle 'beginElement'
|
||||
gSvg.setCurrentTime(1.99);
|
||||
gExpectedEvents.push("beginEvent");
|
||||
gTimeoutID = setTimeout(timeoutFail, gTimeoutDur);
|
||||
gSvg.unpauseAnimations();
|
||||
}
|
||||
|
||||
function handleOnBegin(evt)
|
||||
{
|
||||
is(evt.type, "beginEvent", "Expected begin event but got " + evt.type);
|
||||
checkExpectedEvent(evt);
|
||||
}
|
||||
|
||||
function handleOnRepeat(evt)
|
||||
{
|
||||
is(evt.type, "repeatEvent", "Expected repeat event but got " + evt.type);
|
||||
checkExpectedEvent(evt);
|
||||
}
|
||||
|
||||
function handleOnEnd(evt)
|
||||
{
|
||||
is(evt.type, "endEvent", "Expected end event but got " + evt.type);
|
||||
checkExpectedEvent(evt);
|
||||
}
|
||||
|
||||
function sanityCheckEvent(evt)
|
||||
{
|
||||
is(evt.target, gAnim, "Unexpected event target");
|
||||
is(evt.currentTarget, gAnim, "Unexpected event current target");
|
||||
is(evt.eventPhase, evt.AT_TARGET);
|
||||
is(evt.bubbles, false, "Event should not bubble");
|
||||
is(evt.cancelable, false, "Event should not be cancelable");
|
||||
// Currently we set event timestamps to 0 which DOM 2 allows. This isn't
|
||||
// correct since SMIL uses this field to avoid synchronisation slew but first
|
||||
// we need to fix bug 323039 and bug 77992 which involve storing timestamps as
|
||||
// 64-bit integers and deciding whether those timestamps should be related to
|
||||
// the epoch or system start.
|
||||
is(evt.timeStamp, 0, "Event timeStamp should be 0");
|
||||
ok(evt.view !== null, "Event view not set");
|
||||
}
|
||||
|
||||
function checkExpectedEvent(evt)
|
||||
{
|
||||
sanityCheckEvent(evt);
|
||||
ok(gExpectedEvents.length > 0, "Unexpected event: " + evt.type);
|
||||
if (gExpectedEvents.length == 0) return;
|
||||
|
||||
var expected = gExpectedEvents.shift();
|
||||
if (typeof expected == 'string') {
|
||||
is(evt.type, expected, "Unexpected event type");
|
||||
is(evt.detail, 0, "Unexpected event detail (repeat iteration)");
|
||||
} else {
|
||||
is(evt.type, expected[0], "Unexpected event type");
|
||||
is(evt.detail, expected[1], "Unexpected event detail (repeat iteration)");
|
||||
}
|
||||
if (gExpectedEvents.length == 0) {
|
||||
clearTimeout(gTimeoutID);
|
||||
continueTest();
|
||||
}
|
||||
}
|
||||
|
||||
function timeoutFail()
|
||||
{
|
||||
ok(false, "Timed out waiting for events: " + gExpectedEvents.join(', '));
|
||||
SimpleTest.finish(); // No point continuing
|
||||
}
|
||||
|
||||
function parentHandler(evt)
|
||||
{
|
||||
ok(false, "Handler on parent got called but event shouldn't bubble.");
|
||||
}
|
||||
|
||||
window.addEventListener("load", continueTest, false);
|
||||
|
||||
// Register event handlers *in addition* to the handlers already added via the
|
||||
// "onbegin", "onend", "onrepeat" attributes on the <animate> and <circle>
|
||||
// elements. This is to test that both types of registration work.
|
||||
gAnim.addEventListener("beginEvent", handleOnBegin, false);
|
||||
gAnim.addEventListener("repeatEvent", handleOnRepeat, false);
|
||||
gAnim.addEventListener("endEvent", handleOnEnd, false);
|
||||
gCircle.addEventListener("beginEvent", parentHandler, false);
|
||||
]]>
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -476,6 +476,12 @@ nsSVGAnimationElement::EndElementAt(float offset)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsSVGAnimationElement::IsEventName(nsIAtom* aName)
|
||||
{
|
||||
return nsContentUtils::IsEventAttributeName(aName, EventNameType_SMIL);
|
||||
}
|
||||
|
||||
void
|
||||
nsSVGAnimationElement::UpdateHrefTarget(nsIContent* aNodeForContext,
|
||||
const nsAString& aHrefStr)
|
||||
|
|
|
@ -98,6 +98,9 @@ public:
|
|||
virtual nsSMILTimeContainer* GetTimeContainer();
|
||||
|
||||
protected:
|
||||
// nsSVGElement overrides
|
||||
PRBool IsEventName(nsIAtom* aName);
|
||||
|
||||
void UpdateHrefTarget(nsIContent* aNodeForContext,
|
||||
const nsAString& aHrefStr);
|
||||
|
||||
|
|
|
@ -1364,6 +1364,14 @@ nsIAtom* nsSVGElement::GetEventNameForAttr(nsIAtom* aAttr)
|
|||
return nsGkAtoms::onSVGScroll;
|
||||
if (aAttr == nsGkAtoms::onzoom)
|
||||
return nsGkAtoms::onSVGZoom;
|
||||
#ifdef MOZ_SMIL
|
||||
if (aAttr == nsGkAtoms::onbegin)
|
||||
return nsGkAtoms::onbeginEvent;
|
||||
if (aAttr == nsGkAtoms::onrepeat)
|
||||
return nsGkAtoms::onrepeatEvent;
|
||||
if (aAttr == nsGkAtoms::onend)
|
||||
return nsGkAtoms::onendEvent;
|
||||
#endif // MOZ_SMIL
|
||||
|
||||
return aAttr;
|
||||
}
|
||||
|
|
|
@ -82,7 +82,8 @@ FORCE_STATIC_LIB = 1
|
|||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
LOCAL_INCLUDES = -I$(srcdir)/../../../base/src \
|
||||
-I$(srcdir)/../../content/src \
|
||||
$(NULL)
|
||||
-I$(srcdir)/../../content/src \
|
||||
-I$(srcdir)/../../../../layout/xul/base/src/tree/src \
|
||||
$(NULL)
|
||||
|
||||
DEFINES += -D_IMPL_NS_LAYOUT
|
||||
|
|
|
@ -65,6 +65,7 @@
|
|||
#include "nsINameSpaceManager.h"
|
||||
#include "nsIDOMClassInfo.h"
|
||||
#include "nsWhitespaceTokenizer.h"
|
||||
#include "nsTreeContentView.h"
|
||||
|
||||
// For security check
|
||||
#include "nsIDocument.h"
|
||||
|
@ -467,6 +468,9 @@ nsXULTreeBuilder::GetSelection(nsITreeSelection** aSelection)
|
|||
NS_IMETHODIMP
|
||||
nsXULTreeBuilder::SetSelection(nsITreeSelection* aSelection)
|
||||
{
|
||||
NS_ENSURE_TRUE(!aSelection ||
|
||||
nsTreeContentView::CanTrustTreeSelection(aSelection),
|
||||
NS_ERROR_DOM_SECURITY_ERR);
|
||||
mSelection = aSelection;
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -377,6 +377,7 @@
|
|||
#include "nsIDOMSVGSetElement.h"
|
||||
#include "nsIDOMSVGAnimationElement.h"
|
||||
#include "nsIDOMElementTimeControl.h"
|
||||
#include "nsIDOMTimeEvent.h"
|
||||
#endif // MOZ_SMIL
|
||||
#include "nsIDOMSVGAnimTransformList.h"
|
||||
#include "nsIDOMSVGCircleElement.h"
|
||||
|
@ -1003,6 +1004,8 @@ static nsDOMClassInfoData sClassInfoData[] = {
|
|||
ELEMENT_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CLASSINFO_DATA(SVGSetElement, nsElementSH,
|
||||
ELEMENT_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CLASSINFO_DATA(TimeEvent, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
#endif // MOZ_SMIL
|
||||
NS_DEFINE_CLASSINFO_DATA(SVGCircleElement, nsElementSH,
|
||||
ELEMENT_SCRIPTABLE_FLAGS)
|
||||
|
@ -3040,6 +3043,10 @@ nsDOMClassInfo::Init()
|
|||
DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(TimeEvent, nsIDOMTimeEvent)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMTimeEvent)
|
||||
DOM_CLASSINFO_EVENT_MAP_ENTRIES
|
||||
DOM_CLASSINFO_MAP_END
|
||||
#endif // MOZ_SMIL
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(SVGCircleElement, nsIDOMSVGCircleElement)
|
||||
|
|
|
@ -240,6 +240,7 @@ DOMCI_CLASS(SVGAnimateTransformElement)
|
|||
DOMCI_CLASS(SVGAnimateMotionElement)
|
||||
DOMCI_CLASS(SVGMpathElement)
|
||||
DOMCI_CLASS(SVGSetElement)
|
||||
DOMCI_CLASS(TimeEvent)
|
||||
#endif // MOZ_SMIL
|
||||
DOMCI_CLASS(SVGCircleElement)
|
||||
DOMCI_CLASS(SVGClipPathElement)
|
||||
|
|
|
@ -48,6 +48,7 @@ XPIDL_MODULE = dom_smil
|
|||
|
||||
XPIDLSRCS = \
|
||||
nsIDOMElementTimeControl.idl \
|
||||
nsIDOMTimeEvent.idl \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is the Mozilla SMIL Module.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Brian Birtles <birtles@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsIDOMEvent.idl"
|
||||
|
||||
/**
|
||||
* The SMIL TimeEvent interface.
|
||||
*
|
||||
* For more information please refer to:
|
||||
* http://www.w3.org/TR/SMIL/smil-timing.html#Events-TimeEvent
|
||||
* http://www.w3.org/TR/SVG/animate.html#InterfaceTimeEvent
|
||||
*/
|
||||
|
||||
[scriptable, uuid(0d309c26-ddbb-44cb-9af1-3008972349e3)]
|
||||
interface nsIDOMTimeEvent : nsIDOMEvent
|
||||
{
|
||||
readonly attribute long detail;
|
||||
readonly attribute nsIDOMAbstractView view;
|
||||
|
||||
void initTimeEvent(in DOMString typeArg,
|
||||
in nsIDOMAbstractView viewArg,
|
||||
in long detailArg);
|
||||
};
|
|
@ -9,6 +9,8 @@ Local patches:
|
|||
|
||||
angle-sunstudio.patch - Fix compilation with Sun Studio on Solaris
|
||||
|
||||
fix-compile.patch - Remove some trailing commas
|
||||
|
||||
To regenerate the flex/yacc generated files:
|
||||
|
||||
flex --noline --nounistd --outfile=generated/glslang.cpp src/compiler/glslang.l
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
|
||||
# HG changeset patch
|
||||
# User Robert Sayre <sayrer@gmail.com>
|
||||
# Date 1280559674 25200
|
||||
# Node ID bb4a143ee814097076640c37df84ef7f1303b63b
|
||||
# Parent 9e08308ca8cb9d4584ff990f441f363f3d81bd57
|
||||
Fix ShaderLang.h bustage. Commas at the end of enum lists.
|
||||
|
||||
diff --git a/gfx/angle/include/GLSLANG/ShaderLang.h b/gfx/angle/include/GLSLANG/ShaderLang.h
|
||||
--- a/gfx/angle/include/GLSLANG/ShaderLang.h
|
||||
+++ b/gfx/angle/include/GLSLANG/ShaderLang.h
|
||||
@@ -47,7 +47,7 @@ ANGLE_API int ShFinalize();
|
||||
typedef enum {
|
||||
EShLangVertex,
|
||||
EShLangFragment,
|
||||
- EShLangCount,
|
||||
+ EShLangCount
|
||||
} EShLanguage;
|
||||
|
||||
//
|
||||
@@ -56,7 +56,7 @@ typedef enum {
|
||||
//
|
||||
typedef enum {
|
||||
EShSpecGLES2,
|
||||
- EShSpecWebGL,
|
||||
+ EShSpecWebGL
|
||||
} EShSpec;
|
||||
|
||||
//
|
||||
@@ -66,12 +66,12 @@ typedef enum {
|
||||
EShOptNoGeneration,
|
||||
EShOptNone,
|
||||
EShOptSimple, // Optimizations that can be done quickly
|
||||
- EShOptFull, // Optimizations that will take more time
|
||||
+ EShOptFull // Optimizations that will take more time
|
||||
} EShOptimizationLevel;
|
||||
|
||||
enum TDebugOptions {
|
||||
EDebugOpNone = 0x000,
|
||||
- EDebugOpIntermediate = 0x001, // Writes intermediate tree into info-log.
|
||||
+ EDebugOpIntermediate = 0x001 // Writes intermediate tree into info-log.
|
||||
};
|
||||
|
||||
//
|
||||
|
|
@ -693,13 +693,13 @@ static const yytype_uint16 yyrline[] =
|
|||
1385, 1405, 1434, 1454, 1530, 1540, 1566, 1569, 1575, 1583,
|
||||
1591, 1599, 1602, 1609, 1612, 1615, 1621, 1624, 1639, 1643,
|
||||
1647, 1651, 1660, 1665, 1670, 1675, 1680, 1685, 1690, 1695,
|
||||
1700, 1705, 1711, 1717, 1723, 1728, 1733, 1738, 1751, 1761,
|
||||
1769, 1772, 1787, 1813, 1817, 1823, 1828, 1841, 1845, 1849,
|
||||
1850, 1856, 1857, 1858, 1859, 1860, 1864, 1865, 1865, 1865,
|
||||
1873, 1874, 1879, 1882, 1890, 1893, 1899, 1900, 1904, 1912,
|
||||
1916, 1926, 1931, 1948, 1948, 1953, 1953, 1960, 1960, 1968,
|
||||
1971, 1977, 1980, 1986, 1990, 1997, 2004, 2011, 2018, 2029,
|
||||
2038, 2042, 2049, 2052, 2058, 2058
|
||||
1700, 1705, 1711, 1717, 1723, 1728, 1733, 1738, 1751, 1764,
|
||||
1772, 1775, 1790, 1816, 1820, 1826, 1834, 1850, 1854, 1858,
|
||||
1859, 1865, 1866, 1867, 1868, 1869, 1873, 1874, 1874, 1874,
|
||||
1882, 1883, 1888, 1891, 1899, 1902, 1908, 1909, 1913, 1921,
|
||||
1925, 1935, 1940, 1957, 1957, 1962, 1962, 1969, 1969, 1977,
|
||||
1980, 1986, 1989, 1995, 1999, 2006, 2013, 2020, 2027, 2038,
|
||||
2047, 2051, 2058, 2061, 2067, 2067
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -3943,6 +3943,9 @@ yyreduce:
|
|||
case 138:
|
||||
|
||||
{
|
||||
if (parseContext->reservedErrorCheck((yyvsp[(2) - (5)].lex).line, *(yyvsp[(2) - (5)].lex).string))
|
||||
parseContext->recover();
|
||||
|
||||
TType* structure = new TType((yyvsp[(4) - (5)].interm.typeList), *(yyvsp[(2) - (5)].lex).string);
|
||||
TVariable* userTypeDef = new TVariable((yyvsp[(2) - (5)].lex).string, *structure, true);
|
||||
if (! parseContext->symbolTable.insert(*userTypeDef)) {
|
||||
|
@ -4031,6 +4034,9 @@ yyreduce:
|
|||
case 145:
|
||||
|
||||
{
|
||||
if (parseContext->reservedErrorCheck((yyvsp[(1) - (1)].lex).line, *(yyvsp[(1) - (1)].lex).string))
|
||||
parseContext->recover();
|
||||
|
||||
(yyval.interm.typeLine).type = new TType(EbtVoid, EbpUndefined);
|
||||
(yyval.interm.typeLine).line = (yyvsp[(1) - (1)].lex).line;
|
||||
(yyval.interm.typeLine).type->setFieldName(*(yyvsp[(1) - (1)].lex).string);
|
||||
|
@ -4040,6 +4046,9 @@ yyreduce:
|
|||
case 146:
|
||||
|
||||
{
|
||||
if (parseContext->reservedErrorCheck((yyvsp[(1) - (4)].lex).line, *(yyvsp[(1) - (4)].lex).string))
|
||||
parseContext->recover();
|
||||
|
||||
(yyval.interm.typeLine).type = new TType(EbtVoid, EbpUndefined);
|
||||
(yyval.interm.typeLine).line = (yyvsp[(1) - (4)].lex).line;
|
||||
(yyval.interm.typeLine).type->setFieldName(*(yyvsp[(1) - (4)].lex).string);
|
||||
|
|
|
@ -152,3 +152,14 @@ interface nsITreeSelection : nsISupports
|
|||
*/
|
||||
readonly attribute long shiftSelectPivot;
|
||||
};
|
||||
|
||||
/**
|
||||
* The following interface is not scriptable and MUST NEVER BE MADE scriptable.
|
||||
* Native treeselections implement it, and we use this to check whether a
|
||||
* treeselection is native (and therefore suitable for use by untrusted content).
|
||||
*/
|
||||
[uuid(1bd59678-5cb3-4316-b246-31a91b19aabe)]
|
||||
interface nsINativeTreeSelection : nsITreeSelection
|
||||
{
|
||||
[noscript] void ensureNative();
|
||||
};
|
||||
|
|
|
@ -428,6 +428,8 @@ protected:
|
|||
InvalidateRow(aRow + aOrientation);
|
||||
}
|
||||
|
||||
public:
|
||||
static
|
||||
already_AddRefed<nsTreeColumn> GetColumnImpl(nsITreeColumn* aUnknownCol) {
|
||||
if (!aUnknownCol)
|
||||
return nsnull;
|
||||
|
@ -437,6 +439,8 @@ protected:
|
|||
return col;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
// Create a new timer. This method is used to delay various actions like
|
||||
// opening/closing folders or tree scrolling.
|
||||
// aID is type of the action, aFunc is the function to be called when
|
||||
|
|
|
@ -47,6 +47,14 @@
|
|||
#include "nsIEventStateManager.h"
|
||||
#include "nsINodeInfo.h"
|
||||
#include "nsIXULSortService.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsTreeBodyFrame.h"
|
||||
|
||||
#define NS_ENSURE_NATIVE_COLUMN(_col) \
|
||||
nsRefPtr<nsTreeColumn> col = nsTreeBodyFrame::GetColumnImpl(_col); \
|
||||
if (!col) { \
|
||||
return NS_ERROR_INVALID_ARG; \
|
||||
}
|
||||
|
||||
// A content model view implementation for the tree.
|
||||
|
||||
|
@ -194,9 +202,22 @@ nsTreeContentView::GetSelection(nsITreeSelection** aSelection)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsTreeContentView::CanTrustTreeSelection(nsISupports* aValue)
|
||||
{
|
||||
// Untrusted content is only allowed to specify known-good views
|
||||
if (nsContentUtils::IsCallerTrustedForWrite())
|
||||
return PR_TRUE;
|
||||
nsCOMPtr<nsINativeTreeSelection> nativeTreeSel = do_QueryInterface(aValue);
|
||||
return nativeTreeSel && NS_SUCCEEDED(nativeTreeSel->EnsureNative());
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTreeContentView::SetSelection(nsITreeSelection* aSelection)
|
||||
{
|
||||
NS_ENSURE_TRUE(!aSelection || CanTrustTreeSelection(aSelection),
|
||||
NS_ERROR_DOM_SECURITY_ERR);
|
||||
|
||||
mSelection = aSelection;
|
||||
if (!mSelection || !mUpdateSelection)
|
||||
return NS_OK;
|
||||
|
@ -247,7 +268,7 @@ nsTreeContentView::GetRowProperties(PRInt32 aIndex, nsISupportsArray* aPropertie
|
|||
NS_IMETHODIMP
|
||||
nsTreeContentView::GetCellProperties(PRInt32 aRow, nsITreeColumn* aCol, nsISupportsArray* aProperties)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCol);
|
||||
NS_ENSURE_NATIVE_COLUMN(aCol);
|
||||
NS_ENSURE_ARG_POINTER(aProperties);
|
||||
NS_PRECONDITION(aRow >= 0 && aRow < PRInt32(mRows.Length()), "bad row");
|
||||
if (aRow < 0 || aRow >= PRInt32(mRows.Length()))
|
||||
|
@ -272,7 +293,7 @@ nsTreeContentView::GetCellProperties(PRInt32 aRow, nsITreeColumn* aCol, nsISuppo
|
|||
NS_IMETHODIMP
|
||||
nsTreeContentView::GetColumnProperties(nsITreeColumn* aCol, nsISupportsArray* aProperties)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCol);
|
||||
NS_ENSURE_NATIVE_COLUMN(aCol);
|
||||
NS_ENSURE_ARG_POINTER(aProperties);
|
||||
nsCOMPtr<nsIDOMElement> element;
|
||||
aCol->GetElement(getter_AddRefs(element));
|
||||
|
@ -428,7 +449,7 @@ nsTreeContentView::GetLevel(PRInt32 aIndex, PRInt32* _retval)
|
|||
nsTreeContentView::GetImageSrc(PRInt32 aRow, nsITreeColumn* aCol, nsAString& _retval)
|
||||
{
|
||||
_retval.Truncate();
|
||||
NS_ENSURE_ARG_POINTER(aCol);
|
||||
NS_ENSURE_NATIVE_COLUMN(aCol);
|
||||
NS_PRECONDITION(aRow >= 0 && aRow < PRInt32(mRows.Length()), "bad row");
|
||||
if (aRow < 0 || aRow >= PRInt32(mRows.Length()))
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
@ -449,7 +470,7 @@ nsTreeContentView::GetImageSrc(PRInt32 aRow, nsITreeColumn* aCol, nsAString& _re
|
|||
NS_IMETHODIMP
|
||||
nsTreeContentView::GetProgressMode(PRInt32 aRow, nsITreeColumn* aCol, PRInt32* _retval)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCol);
|
||||
NS_ENSURE_NATIVE_COLUMN(aCol);
|
||||
NS_PRECONDITION(aRow >= 0 && aRow < PRInt32(mRows.Length()), "bad row");
|
||||
if (aRow < 0 || aRow >= PRInt32(mRows.Length()))
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
@ -480,7 +501,7 @@ NS_IMETHODIMP
|
|||
nsTreeContentView::GetCellValue(PRInt32 aRow, nsITreeColumn* aCol, nsAString& _retval)
|
||||
{
|
||||
_retval.Truncate();
|
||||
NS_ENSURE_ARG_POINTER(aCol);
|
||||
NS_ENSURE_NATIVE_COLUMN(aCol);
|
||||
NS_PRECONDITION(aRow >= 0 && aRow < PRInt32(mRows.Length()), "bad row");
|
||||
if (aRow < 0 || aRow >= PRInt32(mRows.Length()))
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
@ -502,7 +523,7 @@ NS_IMETHODIMP
|
|||
nsTreeContentView::GetCellText(PRInt32 aRow, nsITreeColumn* aCol, nsAString& _retval)
|
||||
{
|
||||
_retval.Truncate();
|
||||
NS_ENSURE_ARG_POINTER(aCol);
|
||||
NS_ENSURE_NATIVE_COLUMN(aCol);
|
||||
NS_PRECONDITION(aRow >= 0 && aRow < PRInt32(mRows.Length()), "bad row");
|
||||
NS_PRECONDITION(aCol, "bad column");
|
||||
|
||||
|
@ -610,7 +631,7 @@ nsTreeContentView::ToggleOpenState(PRInt32 aIndex)
|
|||
NS_IMETHODIMP
|
||||
nsTreeContentView::CycleHeader(nsITreeColumn* aCol)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCol);
|
||||
NS_ENSURE_NATIVE_COLUMN(aCol);
|
||||
|
||||
if (!mRoot)
|
||||
return NS_OK;
|
||||
|
@ -665,7 +686,7 @@ NS_IMETHODIMP
|
|||
nsTreeContentView::IsEditable(PRInt32 aRow, nsITreeColumn* aCol, PRBool* _retval)
|
||||
{
|
||||
*_retval = PR_FALSE;
|
||||
NS_ENSURE_ARG_POINTER(aCol);
|
||||
NS_ENSURE_NATIVE_COLUMN(aCol);
|
||||
NS_PRECONDITION(aRow >= 0 && aRow < PRInt32(mRows.Length()), "bad row");
|
||||
if (aRow < 0 || aRow >= PRInt32(mRows.Length()))
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
@ -690,6 +711,7 @@ nsTreeContentView::IsEditable(PRInt32 aRow, nsITreeColumn* aCol, PRBool* _retval
|
|||
NS_IMETHODIMP
|
||||
nsTreeContentView::IsSelectable(PRInt32 aRow, nsITreeColumn* aCol, PRBool* _retval)
|
||||
{
|
||||
NS_ENSURE_NATIVE_COLUMN(aCol);
|
||||
NS_PRECONDITION(aRow >= 0 && aRow < PRInt32(mRows.Length()), "bad row");
|
||||
if (aRow < 0 || aRow >= PRInt32(mRows.Length()))
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
@ -714,7 +736,7 @@ nsTreeContentView::IsSelectable(PRInt32 aRow, nsITreeColumn* aCol, PRBool* _retv
|
|||
NS_IMETHODIMP
|
||||
nsTreeContentView::SetCellValue(PRInt32 aRow, nsITreeColumn* aCol, const nsAString& aValue)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCol);
|
||||
NS_ENSURE_NATIVE_COLUMN(aCol);
|
||||
NS_PRECONDITION(aRow >= 0 && aRow < PRInt32(mRows.Length()), "bad row");
|
||||
if (aRow < 0 || aRow >= PRInt32(mRows.Length()))
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
@ -735,7 +757,7 @@ nsTreeContentView::SetCellValue(PRInt32 aRow, nsITreeColumn* aCol, const nsAStri
|
|||
NS_IMETHODIMP
|
||||
nsTreeContentView::SetCellText(PRInt32 aRow, nsITreeColumn* aCol, const nsAString& aValue)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCol);
|
||||
NS_ENSURE_NATIVE_COLUMN(aCol);
|
||||
NS_PRECONDITION(aRow >= 0 && aRow < PRInt32(mRows.Length()), "bad row");
|
||||
if (aRow < 0 || aRow >= PRInt32(mRows.Length()))
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
|
|
@ -82,6 +82,8 @@ class nsTreeContentView : public nsINativeTreeView,
|
|||
NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
|
||||
NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED
|
||||
|
||||
static PRBool CanTrustTreeSelection(nsISupports* aValue);
|
||||
|
||||
protected:
|
||||
// Recursive methods which deal with serializing of nested content.
|
||||
void Serialize(nsIContent* aContent, PRInt32 aParentIndex, PRInt32* aIndex,
|
||||
|
|
|
@ -280,6 +280,7 @@ DOMCI_DATA(TreeSelection, nsTreeSelection)
|
|||
// QueryInterface implementation for nsBoxObject
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsTreeSelection)
|
||||
NS_INTERFACE_MAP_ENTRY(nsITreeSelection)
|
||||
NS_INTERFACE_MAP_ENTRY(nsINativeTreeSelection)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(TreeSelection)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
class nsITreeBoxObject;
|
||||
struct nsTreeRange;
|
||||
|
||||
class nsTreeSelection : public nsITreeSelection
|
||||
class nsTreeSelection : public nsINativeTreeSelection
|
||||
{
|
||||
public:
|
||||
nsTreeSelection(nsITreeBoxObject* aTree);
|
||||
|
@ -60,6 +60,9 @@ public:
|
|||
NS_DECL_CYCLE_COLLECTION_CLASS(nsTreeSelection)
|
||||
NS_DECL_NSITREESELECTION
|
||||
|
||||
// nsINativeTreeSelection: Untrusted code can use us
|
||||
NS_IMETHOD EnsureNative() { return NS_OK; }
|
||||
|
||||
friend struct nsTreeRange;
|
||||
|
||||
protected:
|
||||
|
|
|
@ -48,14 +48,12 @@ _TEST_FILES = imgutils.js \
|
|||
test_bug399925.html \
|
||||
bug399925.gif \
|
||||
schrep.png \
|
||||
test_bug435296.html \
|
||||
bug468160.sjs \
|
||||
test_bug468160.html \
|
||||
red.png \
|
||||
test_bug466586.html \
|
||||
big.png \
|
||||
blue.png \
|
||||
test_bug478398.html \
|
||||
bug478398_ONLY.png \
|
||||
test_bug490949.html \
|
||||
bug490949-iframe.html \
|
||||
|
@ -75,5 +73,9 @@ _TEST_FILES = imgutils.js \
|
|||
test_bug553982.html \
|
||||
$(NULL)
|
||||
|
||||
# Tests disabled due to intermittent orange
|
||||
# test_bug435296.html disabled - See bug 578591
|
||||
# test_bug478398.html disabled - See bug 579139
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
|
||||
|
|
|
@ -101,6 +101,9 @@ class nsHashKey;
|
|||
#define NS_SVG_EVENT 30
|
||||
#define NS_SVGZOOM_EVENT 31
|
||||
#endif // MOZ_SVG
|
||||
#ifdef MOZ_SMIL
|
||||
#define NS_SMIL_TIME_EVENT 32
|
||||
#endif // MOZ_SMIL
|
||||
|
||||
#define NS_QUERY_CONTENT_EVENT 33
|
||||
|
||||
|
@ -460,6 +463,13 @@ class nsHashKey;
|
|||
#define NS_TRANSITION_EVENT_START 4200
|
||||
#define NS_TRANSITION_END (NS_TRANSITION_EVENT_START)
|
||||
|
||||
#ifdef MOZ_SMIL
|
||||
#define NS_SMIL_TIME_EVENT_START 4300
|
||||
#define NS_SMIL_BEGIN (NS_SMIL_TIME_EVENT_START)
|
||||
#define NS_SMIL_END (NS_SMIL_TIME_EVENT_START + 1)
|
||||
#define NS_SMIL_REPEAT (NS_SMIL_TIME_EVENT_START + 2)
|
||||
#endif // MOZ_SMIL
|
||||
|
||||
/**
|
||||
* Return status for event processors, nsEventStatus, is defined in
|
||||
* nsEvent.h.
|
||||
|
|
|
@ -53,9 +53,13 @@ class nsMenuItemIconX;
|
|||
class nsMenuItemX;
|
||||
class nsIWidget;
|
||||
|
||||
// MenuDelegate is used to receive Cocoa notifications for
|
||||
// setting up carbon events
|
||||
// MenuDelegate is used to receive Cocoa notifications for setting
|
||||
// up carbon events. Protocol is defined as of 10.6 SDK.
|
||||
#if defined(MAC_OS_X_VERSION_10_6) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6)
|
||||
@interface MenuDelegate : NSObject < NSMenuDelegate >
|
||||
#else
|
||||
@interface MenuDelegate : NSObject
|
||||
#endif
|
||||
{
|
||||
nsMenuX* mGeckoMenu; // weak ref
|
||||
}
|
||||
|
|
|
@ -69,9 +69,21 @@ GdkPixbuf*
|
|||
nsImageToPixbuf::ImageToPixbuf(imgIContainer* aImage)
|
||||
{
|
||||
nsRefPtr<gfxImageSurface> frame;
|
||||
aImage->CopyFrame(imgIContainer::FRAME_CURRENT,
|
||||
imgIContainer::FLAG_SYNC_DECODE,
|
||||
getter_AddRefs(frame));
|
||||
nsresult rv = aImage->CopyFrame(imgIContainer::FRAME_CURRENT,
|
||||
imgIContainer::FLAG_SYNC_DECODE,
|
||||
getter_AddRefs(frame));
|
||||
|
||||
// If the last call failed, it was probably because our call stack originates
|
||||
// in an imgIDecoderObserver event, meaning that we're not allowed request
|
||||
// a sync decode. Presumably the originating event is something sensible like
|
||||
// OnStopFrame(), so we can just retry the call without a sync decode.
|
||||
if (NS_FAILED(rv))
|
||||
aImage->CopyFrame(imgIContainer::FRAME_CURRENT,
|
||||
imgIContainer::FLAG_NONE,
|
||||
getter_AddRefs(frame));
|
||||
|
||||
if (!frame)
|
||||
return nsnull;
|
||||
|
||||
return ImgSurfaceToPixbuf(frame, frame->Width(), frame->Height());
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче