Bug 1324883 - Shutdow the decoder when receiving nsIWebProgressListener with flag LOAD_RELOAD_BYPASS_PROXY_AND_CACHE in docshell. r=jwwang,smaug

We register the nsIWebProgressListener at the root docshell(GetSameTypeRootTreeItem) to handle video element embedded in iframe.

MozReview-Commit-ID: D4CavLDAnKD

--HG--
extra : rebase_source : 93032297272bbfc8570dce0c8c13ea9f0d45f7a8
This commit is contained in:
bechen@mozilla.com 2017-10-03 12:07:09 +08:00
Родитель e3de08b829
Коммит b6e091b3ea
3 изменённых файлов: 122 добавлений и 2 удалений

Просмотреть файл

@ -9565,7 +9565,6 @@ nsDocument::OnPageHide(bool aPersisted,
mVisible = false;
UpdateVisibilityState();
EnumerateExternalResources(NotifyPageHide, &aPersisted);
EnumerateActivityObservers(NotifyActivityChanged, nullptr);

Просмотреть файл

@ -21,6 +21,7 @@
#include "TimeRanges.h"
#include "nsGenericHTMLElement.h"
#include "nsAttrValueInlines.h"
#include "nsDocShellLoadTypes.h"
#include "nsPresContext.h"
#include "nsIClassOfService.h"
#include "nsIPresShell.h"
@ -3845,6 +3846,105 @@ private:
NS_IMPL_ISUPPORTS(HTMLMediaElement::ShutdownObserver, nsIObserver)
class HTMLMediaElement::ForceReloadListener : public nsIWebProgressListener
, public nsSupportsWeakReference
{
public:
NS_DECL_ISUPPORTS
void Subscribe(HTMLMediaElement* aPtr, nsIWebProgress* aWebProgress)
{
MOZ_DIAGNOSTIC_ASSERT(!mWeak);
MOZ_DIAGNOSTIC_ASSERT(aWebProgress);
mWeak = aPtr;
aWebProgress->AddProgressListener(this,
nsIWebProgress::NOTIFY_STATE_NETWORK);
}
void Unsubscribe(nsIWebProgress* aWebProgress)
{
MOZ_DIAGNOSTIC_ASSERT(mWeak);
mWeak = nullptr;
if (aWebProgress) {
aWebProgress->RemoveProgressListener(this);
}
}
NS_IMETHODIMP OnStateChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest,
uint32_t aProgressStateFlags,
nsresult aStatus) override
{
MOZ_DIAGNOSTIC_ASSERT(mWeak);
if ((aProgressStateFlags & STATE_IS_NETWORK) &&
(aProgressStateFlags & STATE_START)) {
// Query the LoadType to see if it's a ctrl+F5.
nsCOMPtr<nsIDocShell> shell(do_QueryInterface(aWebProgress));
if (shell) {
uint32_t loadType;
shell->GetLoadType(&loadType);
if (LOAD_RELOAD_BYPASS_PROXY_AND_CACHE == loadType && mWeak->mDecoder) {
mWeak->ShutdownDecoder();
}
}
}
return NS_OK;
}
NS_IMETHODIMP
OnProgressChange(nsIWebProgress* aProgress,
nsIRequest* aRequest,
int32_t aCurSelfProgress,
int32_t aMaxSelfProgress,
int32_t aCurTotalProgress,
int32_t aMaxTotalProgress) override
{
NS_NOTREACHED("notification excluded in AddProgressListener(...)");
return NS_OK;
}
NS_IMETHODIMP
OnLocationChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest,
nsIURI* aLocation,
uint32_t aFlags) override
{
NS_NOTREACHED("notification excluded in AddProgressListener(...)");
return NS_OK;
}
NS_IMETHODIMP
OnStatusChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest,
nsresult aStatus,
const char16_t* aMessage) override
{
NS_NOTREACHED("notification excluded in AddProgressListener(...)");
return NS_OK;
}
NS_IMETHODIMP
OnSecurityChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest,
uint32_t aState) override
{
NS_NOTREACHED("notification excluded in AddProgressListener(...)");
return NS_OK;
}
protected:
virtual ~ForceReloadListener()
{
MOZ_DIAGNOSTIC_ASSERT(!mWeak);
}
private:
HTMLMediaElement* mWeak = nullptr;
};
NS_IMPL_ISUPPORTS(HTMLMediaElement::ForceReloadListener,
nsIWebProgressListener,
nsISupportsWeakReference)
HTMLMediaElement::HTMLMediaElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
: nsGenericHTMLElement(aNodeInfo),
mMainThreadEventTarget(OwnerDoc()->EventTargetFor(TaskCategory::Other)),
@ -3928,14 +4028,33 @@ HTMLMediaElement::HTMLMediaElement(already_AddRefed<mozilla::dom::NodeInfo>& aNo
mWatchManager.Watch(mReadyState, &HTMLMediaElement::UpdateReadyStateInternal);
mShutdownObserver->Subscribe(this);
nsIDocShell* docShell = OwnerDoc()->GetDocShell();
if (docShell) {
nsCOMPtr<nsIDocShellTreeItem> root;
docShell->GetSameTypeRootTreeItem(getter_AddRefs(root));
nsCOMPtr<nsIWebProgress> webProgress = do_GetInterface(root);
if (webProgress) {
mForceReloadListener = new ForceReloadListener();
mForceReloadListener->Subscribe(this, webProgress);
}
}
}
HTMLMediaElement::~HTMLMediaElement()
{
NS_ASSERTION(!mHasSelfReference,
"How can we be destroyed if we're still holding a self reference?");
mShutdownObserver->Unsubscribe();
nsIDocShell* docShell = OwnerDoc()->GetDocShell();
nsCOMPtr<nsIWebProgress> webProgress;
if (docShell) {
nsCOMPtr<nsIDocShellTreeItem> root;
docShell->GetSameTypeRootTreeItem(getter_AddRefs(root));
webProgress = do_GetInterface(root);
}
if (mForceReloadListener) {
mForceReloadListener->Unsubscribe(webProgress);
}
if (mVideoFrameContainer) {
mVideoFrameContainer->ForgetElement();

Просмотреть файл

@ -810,6 +810,7 @@ protected:
class StreamListener;
class StreamSizeListener;
class ShutdownObserver;
class ForceReloadListener;
MediaDecoderOwner::NextFrameStatus NextFrameStatus();
@ -1391,6 +1392,7 @@ protected:
RefPtr<VideoStreamTrack> mSelectedVideoStreamTrack;
const RefPtr<ShutdownObserver> mShutdownObserver;
RefPtr<ForceReloadListener> mForceReloadListener;
// Holds a reference to the MediaSource, if any, referenced by the src
// attribute on the media element.