Bug 1214148 - patch 2 - from toplevel iframe to the nested iframe, r=alwu

This commit is contained in:
Andrea Marchesini 2015-12-09 16:46:25 -05:00
parent 09dc802de5
commit 669c119d14
8 changed files with 139 additions and 7 deletions

View File

@ -14,6 +14,7 @@
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/TabParent.h"
#include "nsContentUtils.h"
#include "nsIScriptSecurityManager.h"
@ -219,6 +220,7 @@ AudioChannelService::Shutdown()
gAudioChannelService->mWindows.Clear();
gAudioChannelService->mPlayingChildren.Clear();
gAudioChannelService->mTabParents.Clear();
#ifdef MOZ_WIDGET_GONK
gAudioChannelService->mSpeakerManager.Clear();
#endif
@ -341,6 +343,21 @@ AudioChannelService::UnregisterAudioChannelAgent(AudioChannelAgent* aAgent,
MaybeSendStatusUpdate();
}
void
AudioChannelService::RegisterTabParent(TabParent* aTabParent)
{
MOZ_ASSERT(aTabParent);
MOZ_ASSERT(!mTabParents.Contains(aTabParent));
mTabParents.AppendElement(aTabParent);
}
void
AudioChannelService::UnregisterTabParent(TabParent* aTabParent)
{
MOZ_ASSERT(aTabParent);
mTabParents.RemoveElement(aTabParent);
}
void
AudioChannelService::GetState(nsPIDOMWindow* aWindow, uint32_t aAudioChannel,
float* aVolume, bool* aMuted)
@ -560,6 +577,32 @@ AudioChannelService::Observe(nsISupports* aSubject, const char* aTopic,
return NS_OK;
}
void
AudioChannelService::RefreshAgentsVolumeAndPropagate(AudioChannel aAudioChannel,
nsPIDOMWindow* aWindow)
{
MOZ_ASSERT(aWindow);
MOZ_ASSERT(aWindow->IsOuterWindow());
nsCOMPtr<nsPIDOMWindow> topWindow = aWindow->GetScriptableTop();
if (!topWindow) {
return;
}
AudioChannelWindow* winData = GetWindowData(topWindow->WindowID());
if (!winData) {
return;
}
for (uint32_t i = 0; i < mTabParents.Length(); ++i) {
mTabParents[i]->AudioChannelChangeNotification(aWindow, aAudioChannel,
winData->mChannels[(uint32_t)aAudioChannel].mVolume,
winData->mChannels[(uint32_t)aAudioChannel].mMuted);
}
RefreshAgentsVolume(aWindow);
}
void
AudioChannelService::RefreshAgentsVolume(nsPIDOMWindow* aWindow)
{
@ -751,7 +794,7 @@ AudioChannelService::SetAudioChannelVolume(nsPIDOMWindow* aWindow,
AudioChannelWindow* winData = GetOrCreateWindowData(aWindow);
winData->mChannels[(uint32_t)aAudioChannel].mVolume = aVolume;
RefreshAgentsVolume(aWindow);
RefreshAgentsVolumeAndPropagate(aAudioChannel, aWindow);
}
NS_IMETHODIMP
@ -814,7 +857,7 @@ AudioChannelService::SetAudioChannelMuted(nsPIDOMWindow* aWindow,
AudioChannelWindow* winData = GetOrCreateWindowData(aWindow);
winData->mChannels[(uint32_t)aAudioChannel].mMuted = aMuted;
RefreshAgentsVolume(aWindow);
RefreshAgentsVolumeAndPropagate(aAudioChannel, aWindow);
}
NS_IMETHODIMP

View File

@ -23,10 +23,13 @@ struct PRLogModuleInfo;
namespace mozilla {
namespace dom {
#ifdef MOZ_WIDGET_GONK
class SpeakerManagerService;
#endif
class TabParent;
#define NUMBER_OF_AUDIO_CHANNELS (uint32_t)AudioChannel::EndGuard_
class AudioChannelService final : public nsIAudioChannelService
@ -63,6 +66,12 @@ public:
void UnregisterAudioChannelAgent(AudioChannelAgent* aAgent,
uint32_t aNotifyPlayback);
/**
* For nested iframes.
*/
void RegisterTabParent(TabParent* aTabParent);
void UnregisterTabParent(TabParent* aTabParent);
/**
* Return the state to indicate this audioChannel for his window should keep
* playing/muted.
@ -108,6 +117,9 @@ public:
void RefreshAgentsVolume(nsPIDOMWindow* aWindow);
void RefreshAgentsVolumeAndPropagate(AudioChannel aAudioChannel,
nsPIDOMWindow* aWindow);
// This method needs to know the inner window that wants to capture audio. We
// group agents per top outer window, but we can have multiple innerWindow per
// top outerWindow (subiframes, etc.) and we have to identify all the agents
@ -223,6 +235,9 @@ private:
nsTArray<SpeakerManagerService*> mSpeakerManager;
#endif
// Raw pointers because TabParents must unregister themselves.
nsTArray<TabParent*> mTabParents;
nsCOMPtr<nsIRunnable> mRunnable;
uint64_t mDefChannelChildID;

View File

@ -762,6 +762,13 @@ child:
*/
HandleAccessKey(uint32_t[] charCodes, bool isTrusted, int32_t modifierMask);
/**
* Propagate a refresh to the child process
*/
AudioChannelChangeNotification(uint32_t aAudioChannel,
float aVolume,
bool aMuted);
/*
* FIXME: write protocol!

View File

@ -2254,6 +2254,27 @@ TabChild::RecvHandleAccessKey(nsTArray<uint32_t>&& aCharCodes,
return true;
}
bool
TabChild::RecvAudioChannelChangeNotification(const uint32_t& aAudioChannel,
const float& aVolume,
const bool& aMuted)
{
nsCOMPtr<nsPIDOMWindow> window = do_GetInterface(WebNavigation());
if (window) {
RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
MOZ_ASSERT(service);
service->SetAudioChannelVolume(window,
static_cast<AudioChannel>(aAudioChannel),
aVolume);
service->SetAudioChannelMuted(window,
static_cast<AudioChannel>(aAudioChannel),
aMuted);
}
return true;
}
bool
TabChild::RecvDestroy()
{

View File

@ -504,6 +504,10 @@ public:
const bool& aIsTrusted,
const int32_t& aModifierMask) override;
virtual bool RecvAudioChannelChangeNotification(const uint32_t& aAudioChannel,
const float& aVolume,
const bool& aMuted) override;
/**
* Native widget remoting protocol for use with windowed plugins with e10s.
*/

View File

@ -184,7 +184,7 @@ private:
// Our TabParent may have been destroyed already. If so, don't send any
// fds over, just go back to the IO thread and close them.
if (!tabParent->IsDestroyed()) {
mozilla::Unused << tabParent->SendCacheFileDescriptor(mPath, fd);
Unused << tabParent->SendCacheFileDescriptor(mPath, fd);
}
if (!mFD) {
@ -232,7 +232,7 @@ private:
// Intentionally leak the runnable (but not the fd) rather
// than crash when trying to release a main thread object
// off the main thread.
mozilla::Unused << mTabParent.forget();
Unused << mTabParent.forget();
CloseFile();
}
}
@ -387,6 +387,11 @@ TabParent::AddWindowListeners()
mPresShellWithRefreshListener = shell;
shell->AddPostRefreshObserver(this);
}
RefPtr<AudioChannelService> acs = AudioChannelService::GetOrCreate();
if (acs) {
acs->RegisterTabParent(this);
}
}
}
@ -405,6 +410,11 @@ TabParent::RemoveWindowListeners()
mPresShellWithRefreshListener->RemovePostRefreshObserver(this);
mPresShellWithRefreshListener = nullptr;
}
RefPtr<AudioChannelService> acs = AudioChannelService::GetOrCreate();
if (acs) {
acs->UnregisterTabParent(this);
}
}
void
@ -2636,7 +2646,6 @@ TabParent::RecvAudioChannelActivityNotification(const uint32_t& aAudioChannel,
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
if (os) {
RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
nsAutoCString topic;
topic.Assign("audiochannel-activity-");
topic.Append(AudioChannelService::GetAudioChannelTable()[aAudioChannel].tag);
@ -3397,6 +3406,33 @@ TabParent::GetShowInfo()
mDPI, mDefaultScale.scale);
}
void
TabParent::AudioChannelChangeNotification(nsPIDOMWindow* aWindow,
AudioChannel aAudioChannel,
float aVolume,
bool aMuted)
{
if (!mFrameElement || !mFrameElement->OwnerDoc()) {
return;
}
nsCOMPtr<nsPIDOMWindow> window = mFrameElement->OwnerDoc()->GetWindow();
while (window) {
if (window == aWindow) {
Unused << SendAudioChannelChangeNotification(static_cast<uint32_t>(aAudioChannel),
aVolume, aMuted);
break;
}
nsCOMPtr<nsPIDOMWindow> win = window->GetScriptableParent();
if (window == win) {
break;
}
window = win;
}
}
NS_IMETHODIMP
FakeChannel::OnAuthAvailable(nsISupports *aContext, nsIAuthInformation *aAuthInfo)
{

View File

@ -9,6 +9,7 @@
#include "js/TypeDecls.h"
#include "mozilla/ContentCache.h"
#include "mozilla/dom/AudioChannelBinding.h"
#include "mozilla/dom/ipc/IdType.h"
#include "mozilla/dom/PBrowserParent.h"
#include "mozilla/dom/PContent.h"
@ -456,6 +457,11 @@ public:
void OnStartSignedPackageRequest(nsIChannel* aChannel,
const nsACString& aPackageId);
void AudioChannelChangeNotification(nsPIDOMWindow* aWindow,
AudioChannel aAudioChannel,
float aVolume,
bool aMuted);
protected:
bool ReceiveMessage(const nsString& aMessage,
bool aSync,

View File

@ -213,8 +213,8 @@ AudioChannelManager::GetAllowedAudioChannels(
}
nsBrowserElement::GenerateAllowedAudioChannels(window, nullptr, nullptr,
manifestURL, aAudioChannels,
aRv);
manifestURL, nullptr,
aAudioChannels, aRv);
NS_WARN_IF(aRv.Failed());
}