Bug 1167690 - Part 2: Integrate plugins which support the NPAPI audio extensions with the Audio Channel Service; r=BenWa

This commit is contained in:
Andrea Marchesini 2015-07-28 17:09:48 -04:00 committed by Ehsan Akhgari
parent 20d8877c66
commit 3b6bd2528b
4 changed files with 122 additions and 16 deletions

View File

@ -411,7 +411,9 @@ typedef enum {
, NPNVsupportsCocoaBool = 3001 /* TRUE if the browser supports the Cocoa event model */
, NPNVsupportsUpdatedCocoaTextInputBool = 3002 /* TRUE if the browser supports the updated
Cocoa text input specification. */
#endif
, NPNVmuteAudioBool = 4000 /* Request that the browser wants to mute or unmute the plugin */
#if defined(XP_MACOSX)
, NPNVsupportsCompositingCoreAnimationPluginsBool = 74656 /* TRUE if the browser supports
CA model compositing */
#endif

View File

@ -106,6 +106,8 @@ using mozilla::plugins::PluginModuleContentParent;
#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "GeckoPlugins" , ## args)
#endif
#include "nsIAudioChannelAgent.h"
using namespace mozilla;
using namespace mozilla::plugins::parent;
@ -2403,23 +2405,42 @@ _setvalue(NPP npp, NPPVariable variable, void *result)
}
case NPPVpluginIsPlayingAudio: {
// For testing, remove me
printf("set audio %p\n", result);
bool isPlaying = !!result;
bool isMuted = !result;
nsCOMPtr<nsIDocument> doc = GetDocumentFromNPP(npp);
if (doc) {
nsCOMPtr<nsPIDOMWindow> domwindow = doc->GetWindow();
nsCOMPtr<nsIObserverService> observerService =
services::GetObserverService();
if (observerService) {
// XXX THIS NEEDS A BETTER API
observerService->NotifyObservers(ToSupports(domwindow),
"media-playback",
isPlaying ? NS_LITERAL_STRING("active").get() :
NS_LITERAL_STRING("inactive").get());
nsNPAPIPluginInstance* inst = (nsNPAPIPluginInstance*) npp->ndata;
MOZ_ASSERT(inst);
if (isMuted && !inst->HasAudioChannelAgent()) {
return NPERR_NO_ERROR;
}
nsCOMPtr<nsIAudioChannelAgent> agent;
nsresult rv = inst->GetOrCreateAudioChannelAgent(getter_AddRefs(agent));
if (NS_WARN_IF(NS_FAILED(rv))) {
return NPERR_NO_ERROR;
}
MOZ_ASSERT(agent);
if (isMuted) {
rv = agent->NotifyStoppedPlaying();
if (NS_WARN_IF(NS_FAILED(rv))) {
return NPERR_NO_ERROR;
}
} else {
float volume = 0.0;
bool muted = true;
rv = agent->NotifyStartedPlaying(&volume, &muted);
if (NS_WARN_IF(NS_FAILED(rv))) {
return NPERR_NO_ERROR;
}
rv = inst->WindowVolumeChanged(volume, muted);
if (NS_WARN_IF(NS_FAILED(rv))) {
return NPERR_NO_ERROR;
}
}
return NPERR_NO_ERROR;
}

View File

@ -40,6 +40,7 @@
#include "mozilla/unused.h"
#include "nsILoadContext.h"
#include "mozilla/dom/HTMLObjectElementBinding.h"
#include "AudioChannelService.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -169,7 +170,7 @@ using namespace mozilla::layers;
static NS_DEFINE_IID(kIOutputStreamIID, NS_IOUTPUTSTREAM_IID);
NS_IMPL_ISUPPORTS0(nsNPAPIPluginInstance)
NS_IMPL_ISUPPORTS(nsNPAPIPluginInstance, nsIAudioChannelAgentCallback)
nsNPAPIPluginInstance::nsNPAPIPluginInstance()
: mDrawingModel(kDefaultDrawingModel)
@ -253,6 +254,7 @@ nsNPAPIPluginInstance::Destroy()
{
Stop();
mPlugin = nullptr;
mAudioChannelAgent = nullptr;
#if MOZ_WIDGET_ANDROID
if (mContentSurface)
@ -1788,3 +1790,71 @@ nsNPAPIPluginInstance::GetRunID(uint32_t* aRunID)
return library->GetRunID(aRunID);
}
nsresult
nsNPAPIPluginInstance::GetOrCreateAudioChannelAgent(nsIAudioChannelAgent** aAgent)
{
if (!mAudioChannelAgent) {
nsresult rv;
mAudioChannelAgent = do_CreateInstance("@mozilla.org/audiochannelagent;1", &rv);
if (NS_WARN_IF(!mAudioChannelAgent)) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsPIDOMWindow> window = GetDOMWindow();
if (NS_WARN_IF(!window)) {
return NS_ERROR_FAILURE;
}
rv = mAudioChannelAgent->Init(window->GetCurrentInnerWindow(),
(int32_t)AudioChannelService::GetDefaultAudioChannel(),
this);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
nsCOMPtr<nsIAudioChannelAgent> agent = mAudioChannelAgent;
agent.forget(aAgent);
return NS_OK;
}
NS_IMETHODIMP
nsNPAPIPluginInstance::WindowVolumeChanged(float aVolume, bool aMuted)
{
// We just support mute/unmute
nsresult rv = SetMuted(aMuted);
NS_WARN_IF(NS_FAILED(rv));
return rv;
}
NS_IMETHODIMP
nsNPAPIPluginInstance::WindowAudioCaptureChanged()
{
return NS_OK;
}
nsresult
nsNPAPIPluginInstance::SetMuted(bool aIsMuted)
{
if (RUNNING != mRunning)
return NS_OK;
PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("nsNPAPIPluginInstance informing plugin of mute state change this=%p\n",this));
if (!mPlugin || !mPlugin->GetLibrary())
return NS_ERROR_FAILURE;
NPPluginFuncs* pluginFunctions = mPlugin->PluginFuncs();
if (!pluginFunctions->setvalue)
return NS_ERROR_FAILURE;
PluginDestructionGuard guard(this);
NPError error;
NPBool value = static_cast<NPBool>(aIsMuted);
NS_TRY_SAFE_CALL_RETURN(error, (*pluginFunctions->setvalue)(&mNPP, NPNVmuteAudioBool, &value), this,
NS_PLUGIN_CALL_UNSAFE_TO_REENTER_GECKO);
return (error == NPERR_NO_ERROR) ? NS_OK : NS_ERROR_FAILURE;
}

View File

@ -17,6 +17,7 @@
#include "nsHashKeys.h"
#include <prinrval.h>
#include "js/TypeDecls.h"
#include "nsIAudioChannelAgent.h"
#ifdef MOZ_WIDGET_ANDROID
#include "nsAutoPtr.h"
#include "nsIRunnable.h"
@ -74,13 +75,14 @@ public:
bool needUnschedule;
};
class nsNPAPIPluginInstance : public nsISupports
class nsNPAPIPluginInstance final : public nsIAudioChannelAgentCallback
{
private:
typedef mozilla::PluginLibrary PluginLibrary;
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIAUDIOCHANNELAGENTCALLBACK
nsresult Initialize(nsNPAPIPlugin *aPlugin, nsPluginInstanceOwner* aOwner, const nsACString& aMIMEType);
nsresult Start();
@ -117,6 +119,15 @@ public:
nsPluginInstanceOwner* GetOwner();
void SetOwner(nsPluginInstanceOwner *aOwner);
bool HasAudioChannelAgent() const
{
return !!mAudioChannelAgent;
}
nsresult GetOrCreateAudioChannelAgent(nsIAudioChannelAgent** aAgent);
nsresult SetMuted(bool aIsMuted);
nsNPAPIPlugin* GetPlugin();
nsresult GetNPP(NPP * aNPP);
@ -404,6 +415,8 @@ private:
uint32_t mCachedParamLength;
char **mCachedParamNames;
char **mCachedParamValues;
nsCOMPtr<nsIAudioChannelAgent> mAudioChannelAgent;
};
// On Android, we need to guard against plugin code leaking entries in the local