dom/speakermanager/SpeakerManager.cpp

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

mercurial