2013-11-24 15:50:03 -08:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
|
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
|
|
|
|
#include "SpeakerManager.h"
|
|
|
|
#include "nsIDOMClassInfo.h"
|
2014-03-04 16:37:43 -08:00
|
|
|
#include "nsIDOMEvent.h"
|
2013-11-24 15:50:03 -08:00
|
|
|
#include "nsIDOMEventListener.h"
|
|
|
|
#include "SpeakerManagerService.h"
|
|
|
|
#include "nsIPermissionManager.h"
|
|
|
|
#include "nsIInterfaceRequestorUtils.h"
|
|
|
|
#include "nsIDocShell.h"
|
|
|
|
#include "AudioChannelService.h"
|
2014-04-29 10:27:26 -07:00
|
|
|
#include "mozilla/Services.h"
|
2013-11-24 15:50:03 -08:00
|
|
|
|
2014-03-31 23:13:50 -07:00
|
|
|
namespace mozilla {
|
|
|
|
namespace dom {
|
2013-11-24 15:50:03 -08:00
|
|
|
|
2014-04-27 00:06:00 -07:00
|
|
|
NS_IMPL_QUERY_INTERFACE_INHERITED(SpeakerManager, DOMEventTargetHelper,
|
|
|
|
nsIDOMEventListener)
|
2014-03-31 23:13:50 -07:00
|
|
|
NS_IMPL_ADDREF_INHERITED(SpeakerManager, DOMEventTargetHelper)
|
|
|
|
NS_IMPL_RELEASE_INHERITED(SpeakerManager, DOMEventTargetHelper)
|
2013-11-24 15:50:03 -08:00
|
|
|
|
|
|
|
SpeakerManager::SpeakerManager()
|
|
|
|
: mForcespeaker(false)
|
|
|
|
, mVisible(false)
|
|
|
|
{
|
|
|
|
SpeakerManagerService *service =
|
2014-08-19 19:25:55 -07:00
|
|
|
SpeakerManagerService::GetOrCreateSpeakerManagerService();
|
|
|
|
MOZ_ASSERT(service);
|
|
|
|
service->RegisterSpeakerManager(this);
|
2013-11-24 15:50:03 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
SpeakerManager::~SpeakerManager()
|
|
|
|
{
|
2014-08-19 19:25:55 -07:00
|
|
|
SpeakerManagerService *service = SpeakerManagerService::GetOrCreateSpeakerManagerService();
|
|
|
|
MOZ_ASSERT(service);
|
|
|
|
|
|
|
|
service->UnRegisterSpeakerManager(this);
|
2013-11-24 15:50:03 -08:00
|
|
|
nsCOMPtr<EventTarget> target = do_QueryInterface(GetOwner());
|
|
|
|
NS_ENSURE_TRUE_VOID(target);
|
|
|
|
|
|
|
|
target->RemoveSystemEventListener(NS_LITERAL_STRING("visibilitychange"),
|
|
|
|
this,
|
|
|
|
/* useCapture = */ true);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
SpeakerManager::Speakerforced()
|
|
|
|
{
|
|
|
|
// If a background app calls forcespeaker=true that doesn't change anything.
|
|
|
|
// 'speakerforced' remains false everywhere.
|
|
|
|
if (mForcespeaker && !mVisible) {
|
|
|
|
return false;
|
|
|
|
}
|
2014-08-19 19:25:55 -07:00
|
|
|
SpeakerManagerService *service = SpeakerManagerService::GetOrCreateSpeakerManagerService();
|
|
|
|
MOZ_ASSERT(service);
|
|
|
|
return service->GetSpeakerStatus();
|
|
|
|
|
2013-11-24 15:50:03 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
SpeakerManager::Forcespeaker()
|
|
|
|
{
|
|
|
|
return mForcespeaker;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
SpeakerManager::SetForcespeaker(bool aEnable)
|
|
|
|
{
|
2014-08-19 19:25:55 -07:00
|
|
|
SpeakerManagerService *service = SpeakerManagerService::GetOrCreateSpeakerManagerService();
|
|
|
|
MOZ_ASSERT(service);
|
|
|
|
|
|
|
|
service->ForceSpeaker(aEnable, mVisible);
|
2013-11-24 15:50:03 -08:00
|
|
|
mForcespeaker = aEnable;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
SpeakerManager::DispatchSimpleEvent(const nsAString& aStr)
|
|
|
|
{
|
|
|
|
NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
|
|
|
|
nsresult rv = CheckInnerWindowCorrectness();
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMEvent> event;
|
|
|
|
rv = NS_NewDOMEvent(getter_AddRefs(event), this, nullptr, nullptr);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
NS_WARNING("Failed to create the error event!!!");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
rv = event->InitEvent(aStr, false, false);
|
|
|
|
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
NS_WARNING("Failed to init the error event!!!");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
event->SetTrusted(true);
|
|
|
|
|
|
|
|
rv = DispatchDOMEvent(nullptr, event, nullptr, nullptr);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
NS_ERROR("Failed to dispatch the event!!!");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
SpeakerManager::Init(nsPIDOMWindow* aWindow)
|
|
|
|
{
|
2013-11-30 21:23:00 -08:00
|
|
|
BindToOwner(aWindow);
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDocShell> docshell = do_GetInterface(GetOwner());
|
|
|
|
NS_ENSURE_TRUE_VOID(docshell);
|
|
|
|
docshell->GetIsActive(&mVisible);
|
2013-11-24 15:50:03 -08:00
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(GetOwner());
|
|
|
|
NS_ENSURE_TRUE_VOID(target);
|
|
|
|
|
|
|
|
target->AddSystemEventListener(NS_LITERAL_STRING("visibilitychange"),
|
|
|
|
this,
|
|
|
|
/* useCapture = */ true,
|
|
|
|
/* wantsUntrusted = */ false);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsPIDOMWindow*
|
|
|
|
SpeakerManager::GetParentObject() const
|
|
|
|
{
|
|
|
|
return GetOwner();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* static */ already_AddRefed<SpeakerManager>
|
|
|
|
SpeakerManager::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(aGlobal.GetAsSupports());
|
|
|
|
if (!sgo) {
|
|
|
|
aRv.Throw(NS_ERROR_FAILURE);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsPIDOMWindow> ownerWindow = do_QueryInterface(aGlobal.GetAsSupports());
|
|
|
|
if (!ownerWindow) {
|
|
|
|
aRv.Throw(NS_ERROR_FAILURE);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2014-04-29 10:27:26 -07:00
|
|
|
nsCOMPtr<nsIPermissionManager> permMgr = services::GetPermissionManager();
|
2013-11-24 15:50:03 -08:00
|
|
|
NS_ENSURE_TRUE(permMgr, nullptr);
|
|
|
|
|
|
|
|
uint32_t permission = nsIPermissionManager::DENY_ACTION;
|
|
|
|
nsresult rv =
|
|
|
|
permMgr->TestPermissionFromWindow(ownerWindow, "speaker-control",
|
|
|
|
&permission);
|
|
|
|
NS_ENSURE_SUCCESS(rv, nullptr);
|
|
|
|
|
|
|
|
if (permission != nsIPermissionManager::ALLOW_ACTION) {
|
|
|
|
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsRefPtr<SpeakerManager> object = new SpeakerManager();
|
|
|
|
object->Init(ownerWindow);
|
|
|
|
return object.forget();
|
|
|
|
}
|
|
|
|
|
|
|
|
JSObject*
|
2014-04-08 15:27:18 -07:00
|
|
|
SpeakerManager::WrapObject(JSContext* aCx)
|
2013-11-24 15:50:03 -08:00
|
|
|
{
|
Bug 991742 part 6. Remove the "aScope" argument of binding Wrap() methods. r=bholley
This patch was mostly generated with this command:
find . -name "*.h" -o -name "*.cpp" | xargs sed -e 's/Binding::Wrap(aCx, aScope, this/Binding::Wrap(aCx, this/' -e 's/Binding_workers::Wrap(aCx, aScope, this/Binding_workers::Wrap(aCx, this/' -e 's/Binding::Wrap(cx, scope, this/Binding::Wrap(cx, this/' -i ""
plus a few manual fixes to dom/bindings/Codegen.py, js/xpconnect/src/event_impl_gen.py, and a few C++ files that were not caught in the search-and-replace above.
2014-04-08 15:27:17 -07:00
|
|
|
return MozSpeakerManagerBinding::Wrap(aCx, this);
|
2013-11-24 15:50:03 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
SpeakerManager::HandleEvent(nsIDOMEvent* aEvent)
|
|
|
|
{
|
|
|
|
nsAutoString type;
|
|
|
|
aEvent->GetType(type);
|
|
|
|
|
|
|
|
if (!type.EqualsLiteral("visibilitychange")) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDocShell> docshell = do_GetInterface(GetOwner());
|
|
|
|
NS_ENSURE_TRUE(docshell, NS_ERROR_FAILURE);
|
|
|
|
docshell->GetIsActive(&mVisible);
|
|
|
|
|
|
|
|
// If an app that has called forcespeaker=true is switched
|
|
|
|
// from the background to the foreground 'speakerforced'
|
|
|
|
// switches to true in all apps. I.e. the app doesn't have to
|
|
|
|
// call forcespeaker=true again when it comes into foreground.
|
|
|
|
SpeakerManagerService *service =
|
2014-08-19 19:25:55 -07:00
|
|
|
SpeakerManagerService::GetOrCreateSpeakerManagerService();
|
|
|
|
MOZ_ASSERT(service);
|
|
|
|
|
|
|
|
if (mVisible && mForcespeaker) {
|
2013-11-24 15:50:03 -08:00
|
|
|
service->ForceSpeaker(mForcespeaker, mVisible);
|
|
|
|
}
|
|
|
|
// If an application that has called forcespeaker=true, but no audio is
|
|
|
|
// currently playing in the app itself, if application switch to
|
|
|
|
// the background, we switch 'speakerforced' to false.
|
|
|
|
if (!mVisible && mForcespeaker) {
|
|
|
|
AudioChannelService* audioChannelService =
|
2014-08-28 23:10:16 -07:00
|
|
|
AudioChannelService::GetOrCreateAudioChannelService();
|
2013-11-24 15:50:03 -08:00
|
|
|
if (audioChannelService && !audioChannelService->AnyAudioChannelIsActive()) {
|
|
|
|
service->ForceSpeaker(false, mVisible);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
SpeakerManager::SetAudioChannelActive(bool isActive)
|
|
|
|
{
|
|
|
|
if (!isActive && !mVisible) {
|
|
|
|
SpeakerManagerService *service =
|
2014-08-19 19:25:55 -07:00
|
|
|
SpeakerManagerService::GetOrCreateSpeakerManagerService();
|
|
|
|
MOZ_ASSERT(service);
|
|
|
|
|
|
|
|
service->ForceSpeaker(false, mVisible);
|
2013-11-24 15:50:03 -08:00
|
|
|
}
|
|
|
|
}
|
2014-03-31 23:13:50 -07:00
|
|
|
|
|
|
|
} // namespace dom
|
|
|
|
} // namespace mozilla
|