Bug 983984 - Default AudioChannel from a pref, r=ehsan, r=roc, r=mchen

This commit is contained in:
Andrea Marchesini 2014-03-20 10:45:55 +00:00
parent b1f2dc648a
commit d849d65073
7 changed files with 223 additions and 43 deletions

View File

@ -462,7 +462,23 @@ NS_IMPL_BOOL_ATTR(HTMLMediaElement, Autoplay, autoplay)
NS_IMPL_BOOL_ATTR(HTMLMediaElement, Loop, loop)
NS_IMPL_BOOL_ATTR(HTMLMediaElement, DefaultMuted, muted)
NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(HTMLMediaElement, Preload, preload, nullptr)
NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(HTMLMediaElement, MozAudioChannelType, mozaudiochannel, "normal")
NS_IMETHODIMP
HTMLMediaElement::GetMozAudioChannelType(nsAString& aValue)
{
nsString defaultValue;
AudioChannelService::GetDefaultAudioChannelString(defaultValue);
NS_ConvertUTF16toUTF8 str(defaultValue);
GetEnumAttr(nsGkAtoms::mozaudiochannel, str.get(), aValue);
return NS_OK;
}
NS_IMETHODIMP
HTMLMediaElement::SetMozAudioChannelType(const nsAString& aValue)
{
return SetAttrHelper(nsGkAtoms::mozaudiochannel, aValue);
}
already_AddRefed<DOMMediaStream>
HTMLMediaElement::GetMozSrcObject() const
@ -2344,19 +2360,28 @@ bool HTMLMediaElement::CheckAudioChannelPermissions(const nsAString& aString)
}
// Only normal channel doesn't need permission.
if (!aString.EqualsASCII("normal")) {
nsCOMPtr<nsIPermissionManager> permissionManager =
do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
if (!permissionManager) {
return false;
}
if (aString.EqualsASCII("normal")) {
return true;
}
uint32_t perm = nsIPermissionManager::UNKNOWN_ACTION;
permissionManager->TestExactPermissionFromPrincipal(NodePrincipal(),
nsCString(NS_LITERAL_CSTRING("audio-channel-") + NS_ConvertUTF16toUTF8(aString)).get(), &perm);
if (perm != nsIPermissionManager::ALLOW_ACTION) {
return false;
}
// Maybe this audio channel is equal to the default value from the pref.
nsString audioChannel;
AudioChannelService::GetDefaultAudioChannelString(audioChannel);
if (audioChannel.Equals(aString)) {
return true;
}
nsCOMPtr<nsIPermissionManager> permissionManager =
do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
if (!permissionManager) {
return false;
}
uint32_t perm = nsIPermissionManager::UNKNOWN_ACTION;
permissionManager->TestExactPermissionFromPrincipal(NodePrincipal(),
nsCString(NS_LITERAL_CSTRING("audio-channel-") + NS_ConvertUTF16toUTF8(aString)).get(), &perm);
if (perm != nsIPermissionManager::ALLOW_ACTION) {
return false;
}
return true;
@ -3988,7 +4013,7 @@ HTMLMediaElement::MozAudioChannelType() const
return AudioChannel::Publicnotification;
default:
return AudioChannel::Normal;
return AudioChannelService::GetDefaultAudioChannel();
}
}

View File

@ -17,36 +17,86 @@
<pre id="test">
<script type="application/javascript">
var audio1 = document.getElementById("audio1");
ok(audio1, "Audio Element exists");
ok(audio1.mozAudioChannelType == "normal", "Default audio1 channel == 'normal'");
try {
audio1.mozAudioChannelType = "foo";
} catch(e) {}
ok(audio1.mozAudioChannelType == "normal", "Default audio1 channel == 'normal'");
audio1.mozAudioChannelType = "alarm";
ok(audio1.mozAudioChannelType == "alarm", "Default audio1 channel == 'alarm'");
function test_basic() {
var audio1 = document.getElementById("audio1");
ok(audio1, "Audio Element exists");
is(audio1.mozAudioChannelType, "normal", "Default audio1 channel == 'normal'");
try {
audio1.mozAudioChannelType = "foo";
} catch(e) {}
is(audio1.mozAudioChannelType, "normal", "Default audio1 channel == 'normal'");
audio1.mozAudioChannelType = "alarm";
is(audio1.mozAudioChannelType, "alarm", "Default audio1 channel == 'alarm'");
var audio2 = document.getElementById("audio2");
ok(audio2, "Audio Element exists");
ok(audio2.mozAudioChannelType == "normal", "Default audio2 channel == 'normal'");
try {
audio2.mozAudioChannelType = "foo";
} catch(e) {}
ok(audio2.mozAudioChannelType == "normal", "Default audio2 channel == 'normal'");
audio2.mozAudioChannelType = "alarm";
ok(audio2.mozAudioChannelType == "alarm", "Default audio2 channel == 'alarm'");
var audio2 = document.getElementById("audio2");
ok(audio2, "Audio Element exists");
is(audio2.mozAudioChannelType, "normal", "Default audio2 channel == 'normal'");
try {
audio2.mozAudioChannelType = "foo";
} catch(e) {}
is(audio2.mozAudioChannelType, "normal", "Default audio2 channel == 'normal'");
audio2.mozAudioChannelType = "alarm";
is(audio2.mozAudioChannelType, "alarm", "Default audio2 channel == 'alarm'");
var audio3 = document.getElementById("audio3");
ok(audio3, "Audio Element exists");
ok(audio3.mozAudioChannelType == "content", "Default audio3 channel == 'content'");
try {
audio3.mozAudioChannelType = "foo";
} catch(e) {}
ok(audio3.mozAudioChannelType == "content", "audio3 channel == 'content'");
audio3.mozAudioChannelType = "alarm";
ok(audio3.mozAudioChannelType == "alarm", "audio3 channel == 'alarm'");
var audio3 = document.getElementById("audio3");
ok(audio3, "Audio Element exists");
is(audio3.mozAudioChannelType, "content", "Default audio3 channel == 'content'");
try {
audio3.mozAudioChannelType = "foo";
} catch(e) {}
is(audio3.mozAudioChannelType, "content", "audio3 channel == 'content'");
audio3.mozAudioChannelType = "alarm";
is(audio3.mozAudioChannelType, "alarm", "audio3 channel == 'alarm'");
runTest();
}
function test_preferences(aChannel) {
SpecialPowers.pushPrefEnv({"set": [["media.defaultAudioChannel", aChannel ]]},
function() {
var audio = document.createElement('audio');
ok(audio, "Audio Element created");
is(audio.mozAudioChannelType, aChannel, "Default audio channel == '" + aChannel + "'");
runTest();
}
);
}
function test_wrong_preferences() {
SpecialPowers.pushPrefEnv({"set": [["media.defaultAudioChannel", 'foobar' ]]},
function() {
var audio = document.createElement('audio');
ok(audio, "Audio Element created");
is(audio.mozAudioChannelType, 'normal', "Default audio channel == 'normal'");
runTest();
}
);
}
var tests = [
test_basic,
function() { test_preferences("content"); },
function() { test_preferences("notification"); },
function() { test_preferences("alarm"); },
function() { test_preferences("telephony"); },
function() { test_preferences("ringer"); },
function() { test_preferences("publicnotification"); },
test_wrong_preferences,
];
function runTest() {
if (!tests.length) {
SimpleTest.finish();
return;
}
var test = tests.shift();
test();
}
SimpleTest.waitForExplicitFinish();
runTest();
</script>
</pre>
</body>

View File

@ -8,6 +8,7 @@
#include "mozilla/dom/AudioDestinationNodeBinding.h"
#include "mozilla/Preferences.h"
#include "AudioChannelAgent.h"
#include "AudioChannelService.h"
#include "AudioNodeEngine.h"
#include "AudioNodeStream.h"
#include "MediaStreamGraph.h"
@ -237,6 +238,12 @@ AudioDestinationNode::AudioDestinationNode(AudioContext* aContext,
mStream->AddMainThreadListener(this);
mStream->AddAudioOutput(&gWebAudioOutputKey);
AudioChannel channel = AudioChannelService::GetDefaultAudioChannel();
if (channel != AudioChannel::Normal) {
ErrorResult rv;
SetMozAudioChannelType(channel, rv);
}
if (!aIsOffline && UseAudioChannelService()) {
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(GetOwner());
if (target) {
@ -436,6 +443,11 @@ AudioDestinationNode::CheckAudioChannelPermissions(AudioChannel aValue)
return true;
}
// Maybe this audio channel is equal to the default one.
if (aValue == AudioChannelService::GetDefaultAudioChannel()) {
return true;
}
nsCOMPtr<nsIPermissionManager> permissionManager =
do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
if (!permissionManager) {

View File

@ -51,7 +51,7 @@ function test_permission(aChannel) {
is(ac.mozAudioChannelType, "normal", "Default ac channel == 'normal'");
SpecialPowers.pushPermissions(
[{ "type": "audio-channel-" + aChannel, "allow": 1, "context": document }],
[{ "type": "audio-channel-" + aChannel, "allow": true, "context": document }],
function() {
ac.mozAudioChannelType = aChannel;
is(ac.mozAudioChannelType, aChannel, "Default ac channel == '" + aChannel + "'");
@ -60,6 +60,33 @@ function test_permission(aChannel) {
);
}
function test_preferences(aChannel) {
SpecialPowers.pushPrefEnv({"set": [["media.defaultAudioChannel", aChannel ]]},
function() {
SpecialPowers.pushPermissions(
[{ "type": "audio-channel-" + aChannel, "allow": false, "context": document }],
function() {
var ac = new AudioContext();
ok(ac, "AudioContext created");
is(ac.mozAudioChannelType, aChannel, "Default ac channel == '" + aChannel + "'");
runTest();
}
);
}
);
}
function test_wrong_preferences() {
SpecialPowers.pushPrefEnv({"set": [["media.defaultAudioChannel", 'foobar' ]]},
function() {
var ac = new AudioContext();
ok(ac, "AudioContext created");
is(ac.mozAudioChannelType, 'normal', "Default ac channel == 'normal'");
runTest();
}
);
}
var tests = [
test_basic,
@ -68,7 +95,16 @@ var tests = [
function() { test_permission("alarm"); },
function() { test_permission("telephony"); },
function() { test_permission("ringer"); },
function() { test_permission("publicnotification"); }
function() { test_permission("publicnotification"); },
function() { test_preferences("content"); },
function() { test_preferences("notification"); },
function() { test_preferences("alarm"); },
function() { test_preferences("telephony"); },
function() { test_preferences("ringer"); },
function() { test_preferences("publicnotification"); },
test_wrong_preferences,
];
function runTest() {

View File

@ -30,6 +30,7 @@ enum AudioChannelState {
AUDIO_CHANNEL_STATE_FADED,
AUDIO_CHANNEL_STATE_LAST
};
} // namespace dom
} // namespace mozilla

View File

@ -29,6 +29,8 @@
#define NS_AUDIOMANAGER_CONTRACTID "@mozilla.org/telephony/audiomanager;1"
#endif
#include "mozilla/Preferences.h"
using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::hal;
@ -880,3 +882,52 @@ AudioChannelService::CountWindow(nsIDOMWindow* aWindow)
mAgents.EnumerateRead(CountWindowEnumerator, &data);
return data.mCount;
}
// Mappings from 'mozaudiochannel' attribute strings to an enumeration.
static const struct AudioChannelTable
{
const char* string;
AudioChannel value;
} kMozAudioChannelAttributeTable[] = {
{ "normal", AudioChannel::Normal },
{ "content", AudioChannel::Content },
{ "notification", AudioChannel::Notification },
{ "alarm", AudioChannel::Alarm },
{ "telephony", AudioChannel::Telephony },
{ "ringer", AudioChannel::Ringer },
{ "publicnotification", AudioChannel::Publicnotification },
{ nullptr }
};
/* static */ AudioChannel
AudioChannelService::GetDefaultAudioChannel()
{
nsString audioChannel = Preferences::GetString("media.defaultAudioChannel");
if (audioChannel.IsEmpty()) {
return AudioChannel::Normal;
}
for (uint32_t i = 0; kMozAudioChannelAttributeTable[i].string; ++i) {
if (audioChannel.EqualsASCII(kMozAudioChannelAttributeTable[i].string)) {
return kMozAudioChannelAttributeTable[i].value;
}
}
return AudioChannel::Normal;
}
/* static */ void
AudioChannelService::GetDefaultAudioChannelString(nsString& aString)
{
aString.AssignASCII("normal");
nsString audioChannel = Preferences::GetString("media.defaultAudioChannel");
if (!audioChannel.IsEmpty()) {
for (uint32_t i = 0; kMozAudioChannelAttributeTable[i].string; ++i) {
if (audioChannel.EqualsASCII(kMozAudioChannelAttributeTable[i].string)) {
aString = audioChannel;
break;
}
}
}
}

View File

@ -15,6 +15,7 @@
#include "AudioChannelCommon.h"
#include "AudioChannelAgent.h"
#include "nsClassHashtable.h"
#include "mozilla/dom/AudioChannelBinding.h"
class nsPIDOMWindow;
@ -102,6 +103,10 @@ public:
mSpeakerManager.RemoveElement(aSpeakerManager);
}
#endif
static AudioChannel GetDefaultAudioChannel();
static void GetDefaultAudioChannelString(nsString& aString);
protected:
void Notify();