dom/speakermanager/SpeakerManager.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
michael@0 3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 #include "SpeakerManager.h"
michael@0 6 #include "nsIDOMClassInfo.h"
michael@0 7 #include "nsIDOMEvent.h"
michael@0 8 #include "nsIDOMEventListener.h"
michael@0 9 #include "SpeakerManagerService.h"
michael@0 10 #include "nsIPermissionManager.h"
michael@0 11 #include "nsIInterfaceRequestorUtils.h"
michael@0 12 #include "nsIDocShell.h"
michael@0 13 #include "AudioChannelService.h"
michael@0 14
michael@0 15 namespace mozilla {
michael@0 16 namespace dom {
michael@0 17
michael@0 18 NS_IMPL_QUERY_INTERFACE_INHERITED(SpeakerManager, DOMEventTargetHelper,
michael@0 19 nsIDOMEventListener)
michael@0 20 NS_IMPL_ADDREF_INHERITED(SpeakerManager, DOMEventTargetHelper)
michael@0 21 NS_IMPL_RELEASE_INHERITED(SpeakerManager, DOMEventTargetHelper)
michael@0 22
michael@0 23 SpeakerManager::SpeakerManager()
michael@0 24 : mForcespeaker(false)
michael@0 25 , mVisible(false)
michael@0 26 {
michael@0 27 SetIsDOMBinding();
michael@0 28 SpeakerManagerService *service =
michael@0 29 SpeakerManagerService::GetSpeakerManagerService();
michael@0 30 if (service) {
michael@0 31 service->RegisterSpeakerManager(this);
michael@0 32 }
michael@0 33 }
michael@0 34
michael@0 35 SpeakerManager::~SpeakerManager()
michael@0 36 {
michael@0 37 SpeakerManagerService *service = SpeakerManagerService::GetSpeakerManagerService();
michael@0 38 if (service) {
michael@0 39 service->UnRegisterSpeakerManager(this);
michael@0 40 }
michael@0 41 nsCOMPtr<EventTarget> target = do_QueryInterface(GetOwner());
michael@0 42 NS_ENSURE_TRUE_VOID(target);
michael@0 43
michael@0 44 target->RemoveSystemEventListener(NS_LITERAL_STRING("visibilitychange"),
michael@0 45 this,
michael@0 46 /* useCapture = */ true);
michael@0 47 }
michael@0 48
michael@0 49 bool
michael@0 50 SpeakerManager::Speakerforced()
michael@0 51 {
michael@0 52 // If a background app calls forcespeaker=true that doesn't change anything.
michael@0 53 // 'speakerforced' remains false everywhere.
michael@0 54 if (mForcespeaker && !mVisible) {
michael@0 55 return false;
michael@0 56 }
michael@0 57 SpeakerManagerService *service = SpeakerManagerService::GetSpeakerManagerService();
michael@0 58 if (service) {
michael@0 59 return service->GetSpeakerStatus();
michael@0 60 }
michael@0 61 return false;
michael@0 62 }
michael@0 63
michael@0 64 bool
michael@0 65 SpeakerManager::Forcespeaker()
michael@0 66 {
michael@0 67 return mForcespeaker;
michael@0 68 }
michael@0 69
michael@0 70 void
michael@0 71 SpeakerManager::SetForcespeaker(bool aEnable)
michael@0 72 {
michael@0 73 SpeakerManagerService *service = SpeakerManagerService::GetSpeakerManagerService();
michael@0 74 if (service) {
michael@0 75 service->ForceSpeaker(aEnable, mVisible);
michael@0 76 }
michael@0 77 mForcespeaker = aEnable;
michael@0 78 }
michael@0 79
michael@0 80 void
michael@0 81 SpeakerManager::DispatchSimpleEvent(const nsAString& aStr)
michael@0 82 {
michael@0 83 NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
michael@0 84 nsresult rv = CheckInnerWindowCorrectness();
michael@0 85 if (NS_FAILED(rv)) {
michael@0 86 return;
michael@0 87 }
michael@0 88
michael@0 89 nsCOMPtr<nsIDOMEvent> event;
michael@0 90 rv = NS_NewDOMEvent(getter_AddRefs(event), this, nullptr, nullptr);
michael@0 91 if (NS_FAILED(rv)) {
michael@0 92 NS_WARNING("Failed to create the error event!!!");
michael@0 93 return;
michael@0 94 }
michael@0 95 rv = event->InitEvent(aStr, false, false);
michael@0 96
michael@0 97 if (NS_FAILED(rv)) {
michael@0 98 NS_WARNING("Failed to init the error event!!!");
michael@0 99 return;
michael@0 100 }
michael@0 101
michael@0 102 event->SetTrusted(true);
michael@0 103
michael@0 104 rv = DispatchDOMEvent(nullptr, event, nullptr, nullptr);
michael@0 105 if (NS_FAILED(rv)) {
michael@0 106 NS_ERROR("Failed to dispatch the event!!!");
michael@0 107 return;
michael@0 108 }
michael@0 109 }
michael@0 110
michael@0 111 void
michael@0 112 SpeakerManager::Init(nsPIDOMWindow* aWindow)
michael@0 113 {
michael@0 114 BindToOwner(aWindow);
michael@0 115
michael@0 116 nsCOMPtr<nsIDocShell> docshell = do_GetInterface(GetOwner());
michael@0 117 NS_ENSURE_TRUE_VOID(docshell);
michael@0 118 docshell->GetIsActive(&mVisible);
michael@0 119
michael@0 120 nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(GetOwner());
michael@0 121 NS_ENSURE_TRUE_VOID(target);
michael@0 122
michael@0 123 target->AddSystemEventListener(NS_LITERAL_STRING("visibilitychange"),
michael@0 124 this,
michael@0 125 /* useCapture = */ true,
michael@0 126 /* wantsUntrusted = */ false);
michael@0 127 }
michael@0 128
michael@0 129 nsPIDOMWindow*
michael@0 130 SpeakerManager::GetParentObject() const
michael@0 131 {
michael@0 132 return GetOwner();
michael@0 133 }
michael@0 134
michael@0 135 /* static */ already_AddRefed<SpeakerManager>
michael@0 136 SpeakerManager::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv)
michael@0 137 {
michael@0 138 nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(aGlobal.GetAsSupports());
michael@0 139 if (!sgo) {
michael@0 140 aRv.Throw(NS_ERROR_FAILURE);
michael@0 141 return nullptr;
michael@0 142 }
michael@0 143
michael@0 144 nsCOMPtr<nsPIDOMWindow> ownerWindow = do_QueryInterface(aGlobal.GetAsSupports());
michael@0 145 if (!ownerWindow) {
michael@0 146 aRv.Throw(NS_ERROR_FAILURE);
michael@0 147 return nullptr;
michael@0 148 }
michael@0 149
michael@0 150 nsCOMPtr<nsIPermissionManager> permMgr =
michael@0 151 do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
michael@0 152 NS_ENSURE_TRUE(permMgr, nullptr);
michael@0 153
michael@0 154 uint32_t permission = nsIPermissionManager::DENY_ACTION;
michael@0 155 nsresult rv =
michael@0 156 permMgr->TestPermissionFromWindow(ownerWindow, "speaker-control",
michael@0 157 &permission);
michael@0 158 NS_ENSURE_SUCCESS(rv, nullptr);
michael@0 159
michael@0 160 if (permission != nsIPermissionManager::ALLOW_ACTION) {
michael@0 161 aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
michael@0 162 return nullptr;
michael@0 163 }
michael@0 164
michael@0 165 nsRefPtr<SpeakerManager> object = new SpeakerManager();
michael@0 166 object->Init(ownerWindow);
michael@0 167 return object.forget();
michael@0 168 }
michael@0 169
michael@0 170 JSObject*
michael@0 171 SpeakerManager::WrapObject(JSContext* aCx)
michael@0 172 {
michael@0 173 return MozSpeakerManagerBinding::Wrap(aCx, this);
michael@0 174 }
michael@0 175
michael@0 176 NS_IMETHODIMP
michael@0 177 SpeakerManager::HandleEvent(nsIDOMEvent* aEvent)
michael@0 178 {
michael@0 179 nsAutoString type;
michael@0 180 aEvent->GetType(type);
michael@0 181
michael@0 182 if (!type.EqualsLiteral("visibilitychange")) {
michael@0 183 return NS_ERROR_FAILURE;
michael@0 184 }
michael@0 185
michael@0 186 nsCOMPtr<nsIDocShell> docshell = do_GetInterface(GetOwner());
michael@0 187 NS_ENSURE_TRUE(docshell, NS_ERROR_FAILURE);
michael@0 188 docshell->GetIsActive(&mVisible);
michael@0 189
michael@0 190 // If an app that has called forcespeaker=true is switched
michael@0 191 // from the background to the foreground 'speakerforced'
michael@0 192 // switches to true in all apps. I.e. the app doesn't have to
michael@0 193 // call forcespeaker=true again when it comes into foreground.
michael@0 194 SpeakerManagerService *service =
michael@0 195 SpeakerManagerService::GetSpeakerManagerService();
michael@0 196 if (service && mVisible && mForcespeaker) {
michael@0 197 service->ForceSpeaker(mForcespeaker, mVisible);
michael@0 198 }
michael@0 199 // If an application that has called forcespeaker=true, but no audio is
michael@0 200 // currently playing in the app itself, if application switch to
michael@0 201 // the background, we switch 'speakerforced' to false.
michael@0 202 if (!mVisible && mForcespeaker) {
michael@0 203 AudioChannelService* audioChannelService =
michael@0 204 AudioChannelService::GetAudioChannelService();
michael@0 205 if (audioChannelService && !audioChannelService->AnyAudioChannelIsActive()) {
michael@0 206 service->ForceSpeaker(false, mVisible);
michael@0 207 }
michael@0 208 }
michael@0 209 return NS_OK;
michael@0 210 }
michael@0 211
michael@0 212 void
michael@0 213 SpeakerManager::SetAudioChannelActive(bool isActive)
michael@0 214 {
michael@0 215 if (!isActive && !mVisible) {
michael@0 216 SpeakerManagerService *service =
michael@0 217 SpeakerManagerService::GetSpeakerManagerService();
michael@0 218 if (service) {
michael@0 219 service->ForceSpeaker(false, mVisible);
michael@0 220 }
michael@0 221 }
michael@0 222 }
michael@0 223
michael@0 224 } // namespace dom
michael@0 225 } // namespace mozilla

mercurial