2015-05-03 22:32:37 +03:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
2013-11-25 03:50:03 +04: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-05 04:37:43 +04:00
|
|
|
#include "nsIDOMEvent.h"
|
2013-11-25 03:50:03 +04:00
|
|
|
#include "nsIDOMEventListener.h"
|
|
|
|
#include "SpeakerManagerService.h"
|
|
|
|
#include "nsIPermissionManager.h"
|
|
|
|
#include "nsIInterfaceRequestorUtils.h"
|
|
|
|
#include "nsIDocShell.h"
|
|
|
|
#include "AudioChannelService.h"
|
2014-04-29 21:27:26 +04:00
|
|
|
#include "mozilla/Services.h"
|
2013-11-25 03:50:03 +04:00
|
|
|
|
2014-04-01 10:13:50 +04:00
|
|
|
namespace mozilla {
|
|
|
|
namespace dom {
|
2013-11-25 03:50:03 +04:00
|
|
|
|
2014-04-27 11:06:00 +04:00
|
|
|
NS_IMPL_QUERY_INTERFACE_INHERITED(SpeakerManager, DOMEventTargetHelper,
|
|
|
|
nsIDOMEventListener)
|
2014-04-01 10:13:50 +04:00
|
|
|
NS_IMPL_ADDREF_INHERITED(SpeakerManager, DOMEventTargetHelper)
|
|
|
|
NS_IMPL_RELEASE_INHERITED(SpeakerManager, DOMEventTargetHelper)
|
2013-11-25 03:50:03 +04:00
|
|
|
|
|
|
|
SpeakerManager::SpeakerManager()
|
|
|
|
: mForcespeaker(false)
|
|
|
|
, mVisible(false)
|
|
|
|
{
|
|
|
|
SpeakerManagerService *service =
|
2014-08-20 06:25:55 +04:00
|
|
|
SpeakerManagerService::GetOrCreateSpeakerManagerService();
|
|
|
|
MOZ_ASSERT(service);
|
|
|
|
service->RegisterSpeakerManager(this);
|
2013-11-25 03:50:03 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
SpeakerManager::~SpeakerManager()
|
|
|
|
{
|
2014-08-20 06:25:55 +04:00
|
|
|
SpeakerManagerService *service = SpeakerManagerService::GetOrCreateSpeakerManagerService();
|
|
|
|
MOZ_ASSERT(service);
|
|
|
|
|
|
|
|
service->UnRegisterSpeakerManager(this);
|
2013-11-25 03:50:03 +04: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-20 06:25:55 +04:00
|
|
|
SpeakerManagerService *service = SpeakerManagerService::GetOrCreateSpeakerManagerService();
|
|
|
|
MOZ_ASSERT(service);
|
|
|
|
return service->GetSpeakerStatus();
|
|
|
|
|
2013-11-25 03:50:03 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
SpeakerManager::Forcespeaker()
|
|
|
|
{
|
|
|
|
return mForcespeaker;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
SpeakerManager::SetForcespeaker(bool aEnable)
|
|
|
|
{
|
2014-08-20 06:25:55 +04:00
|
|
|
SpeakerManagerService *service = SpeakerManagerService::GetOrCreateSpeakerManagerService();
|
|
|
|
MOZ_ASSERT(service);
|
|
|
|
|
|
|
|
service->ForceSpeaker(aEnable, mVisible);
|
2013-11-25 03:50:03 +04:00
|
|
|
mForcespeaker = aEnable;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
SpeakerManager::DispatchSimpleEvent(const nsAString& aStr)
|
|
|
|
{
|
2015-02-10 01:34:50 +03:00
|
|
|
MOZ_ASSERT(NS_IsMainThread(), "Not running on main thread");
|
2013-11-25 03:50:03 +04:00
|
|
|
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-12-01 09:23:00 +04:00
|
|
|
BindToOwner(aWindow);
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDocShell> docshell = do_GetInterface(GetOwner());
|
|
|
|
NS_ENSURE_TRUE_VOID(docshell);
|
|
|
|
docshell->GetIsActive(&mVisible);
|
2013-11-25 03:50:03 +04: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 21:27:26 +04:00
|
|
|
nsCOMPtr<nsIPermissionManager> permMgr = services::GetPermissionManager();
|
2013-11-25 03:50:03 +04: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*
|
Bug 1117172 part 3. Change the wrappercached WrapObject methods to allow passing in aGivenProto. r=peterv
The only manual changes here are to BindingUtils.h, BindingUtils.cpp,
Codegen.py, Element.cpp, IDBFileRequest.cpp, IDBObjectStore.cpp,
dom/workers/Navigator.cpp, WorkerPrivate.cpp, DeviceStorageRequestChild.cpp,
Notification.cpp, nsGlobalWindow.cpp, MessagePort.cpp, nsJSEnvironment.cpp,
Sandbox.cpp, XPCConvert.cpp, ExportHelpers.cpp, and DataStoreService.cpp. The
rest of this diff was generated by running the following commands:
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObjectInternal\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObjectInternal\((?:aCx|cx|aContext|aCtx|js))\)/\1, aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapNode\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapNode\((?:aCx|cx|aContext|aCtx|js))\)/\1, aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObject\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(Binding(?:_workers)?::Wrap\((?:aCx|cx|aContext|aCtx|js), [^,)]+)\)/\1, aGivenProto)/g'
2015-03-19 17:13:33 +03:00
|
|
|
SpeakerManager::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
2013-11-25 03:50:03 +04:00
|
|
|
{
|
Bug 1117172 part 3. Change the wrappercached WrapObject methods to allow passing in aGivenProto. r=peterv
The only manual changes here are to BindingUtils.h, BindingUtils.cpp,
Codegen.py, Element.cpp, IDBFileRequest.cpp, IDBObjectStore.cpp,
dom/workers/Navigator.cpp, WorkerPrivate.cpp, DeviceStorageRequestChild.cpp,
Notification.cpp, nsGlobalWindow.cpp, MessagePort.cpp, nsJSEnvironment.cpp,
Sandbox.cpp, XPCConvert.cpp, ExportHelpers.cpp, and DataStoreService.cpp. The
rest of this diff was generated by running the following commands:
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObjectInternal\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObjectInternal\((?:aCx|cx|aContext|aCtx|js))\)/\1, aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapNode\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapNode\((?:aCx|cx|aContext|aCtx|js))\)/\1, aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObject\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(Binding(?:_workers)?::Wrap\((?:aCx|cx|aContext|aCtx|js), [^,)]+)\)/\1, aGivenProto)/g'
2015-03-19 17:13:33 +03:00
|
|
|
return MozSpeakerManagerBinding::Wrap(aCx, this, aGivenProto);
|
2013-11-25 03:50:03 +04: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-20 06:25:55 +04:00
|
|
|
SpeakerManagerService::GetOrCreateSpeakerManagerService();
|
|
|
|
MOZ_ASSERT(service);
|
|
|
|
|
|
|
|
if (mVisible && mForcespeaker) {
|
2013-11-25 03:50:03 +04: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) {
|
2015-07-11 15:14:58 +03:00
|
|
|
AudioChannelService* audioChannelService =
|
|
|
|
AudioChannelService::GetOrCreateAudioChannelService();
|
2013-11-25 03:50:03 +04:00
|
|
|
if (audioChannelService && !audioChannelService->AnyAudioChannelIsActive()) {
|
|
|
|
service->ForceSpeaker(false, mVisible);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
SpeakerManager::SetAudioChannelActive(bool isActive)
|
|
|
|
{
|
2015-02-16 05:50:56 +03:00
|
|
|
if (mForcespeaker) {
|
2013-11-25 03:50:03 +04:00
|
|
|
SpeakerManagerService *service =
|
2014-08-20 06:25:55 +04:00
|
|
|
SpeakerManagerService::GetOrCreateSpeakerManagerService();
|
|
|
|
MOZ_ASSERT(service);
|
2015-02-16 05:50:56 +03:00
|
|
|
service->ForceSpeaker(isActive, mVisible);
|
2013-11-25 03:50:03 +04:00
|
|
|
}
|
|
|
|
}
|
2014-04-01 10:13:50 +04:00
|
|
|
|
|
|
|
} // namespace dom
|
|
|
|
} // namespace mozilla
|