PRBool nsVideoFrame::ShouldDisplayPoster() { if (!HasVideoElement()) return PR_FALSE; nsHTMLVideoElement* element = static_cast<nsHTMLVideoElement*>(GetContent()); if (element->GetPlayedOrSeeked() && HasVideoData()) return PR_FALSE; nsCOMPtr<nsIImageLoadingContent> imgContent = do_QueryInterface(mPosterImage); NS_ENSURE_TRUE(imgContent, PR_FALSE); nsCOMPtr<imgIRequest> request; nsresult res = imgContent->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST, getter_AddRefs(request)); if (NS_FAILED(res) || !request) { return PR_FALSE; } PRUint32 status = 0; res = request->GetImageStatus(&status); if (NS_FAILED(res) || (status & imgIRequest::STATUS_ERROR)) return PR_FALSE; return PR_TRUE; }
PRBool nsVideoFrame::HasVideoData() { if (!HasVideoElement()) return PR_FALSE; nsHTMLVideoElement* element = static_cast<nsHTMLVideoElement*>(GetContent()); nsIntSize size = element->GetVideoSize(nsIntSize(0,0)); return size != nsIntSize(0,0); }
nsresult nsVideoFrame::CreateAnonymousContent(nsTArray<nsIContent*>& aElements) { nsNodeInfoManager *nodeInfoManager = GetContent()->GetCurrentDoc()->NodeInfoManager(); nsCOMPtr<nsINodeInfo> nodeInfo; if (HasVideoElement()) { // Create an anonymous image element as a child to hold the poster // image. We may not have a poster image now, but one could be added // before we load, or on a subsequent load. nodeInfo = nodeInfoManager->GetNodeInfo(nsGkAtoms::img, nsnull, kNameSpaceID_XHTML); NS_ENSURE_TRUE(nodeInfo, NS_ERROR_OUT_OF_MEMORY); mPosterImage = NS_NewHTMLImageElement(nodeInfo); NS_ENSURE_TRUE(mPosterImage, NS_ERROR_OUT_OF_MEMORY); // Push a null JSContext on the stack so that code that runs // within the below code doesn't think it's being called by // JS. See bug 604262. nsCxPusher pusher; pusher.PushNull(); // Set the nsImageLoadingContent::ImageState() to 0. This means that the // image will always report its state as 0, so it will never be reframed // to show frames for loading or the broken image icon. This is important, // as the image is native anonymous, and so can't be reframed (currently). nsCOMPtr<nsIImageLoadingContent> imgContent = do_QueryInterface(mPosterImage); NS_ENSURE_TRUE(imgContent, NS_ERROR_FAILURE); imgContent->ForceImageState(PR_TRUE, 0); nsresult res = UpdatePosterSource(PR_FALSE); NS_ENSURE_SUCCESS(res,res); if (!aElements.AppendElement(mPosterImage)) return NS_ERROR_OUT_OF_MEMORY; } // Set up "videocontrols" XUL element which will be XBL-bound to the // actual controls. nodeInfo = nodeInfoManager->GetNodeInfo(nsGkAtoms::videocontrols, nsnull, kNameSpaceID_XUL); NS_ENSURE_TRUE(nodeInfo, NS_ERROR_OUT_OF_MEMORY); nsresult rv = NS_NewElement(getter_AddRefs(mVideoControls), kNameSpaceID_XUL, nodeInfo, PR_FALSE); NS_ENSURE_SUCCESS(rv, rv); if (!aElements.AppendElement(mVideoControls)) return NS_ERROR_OUT_OF_MEMORY; return NS_OK; }
NS_IMETHODIMP nsVideoFrame::AttributeChanged(PRInt32 aNameSpaceID, nsIAtom* aAttribute, PRInt32 aModType) { if (aAttribute == nsGkAtoms::poster && HasVideoElement()) { nsresult res = UpdatePosterSource(PR_TRUE); NS_ENSURE_SUCCESS(res,res); } return nsContainerFrame::AttributeChanged(aNameSpaceID, aAttribute, aModType); }
nsresult nsVideoFrame::UpdatePosterSource(PRBool aNotify) { NS_ASSERTION(HasVideoElement(), "Only call this on <video> elements."); nsHTMLVideoElement* element = static_cast<nsHTMLVideoElement*>(GetContent()); nsAutoString posterStr; element->GetPoster(posterStr); nsresult res = mPosterImage->SetAttr(kNameSpaceID_None, nsGkAtoms::src, posterStr, aNotify); NS_ENSURE_SUCCESS(res,res); return NS_OK; }