dom/fmradio/FMRadio.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
michael@0 3 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #include "mozilla/dom/FMRadio.h"
michael@0 8 #include "nsContentUtils.h"
michael@0 9 #include "mozilla/Hal.h"
michael@0 10 #include "mozilla/HalTypes.h"
michael@0 11 #include "mozilla/Preferences.h"
michael@0 12 #include "mozilla/dom/FMRadioBinding.h"
michael@0 13 #include "mozilla/dom/ContentChild.h"
michael@0 14 #include "mozilla/dom/PFMRadioChild.h"
michael@0 15 #include "mozilla/dom/FMRadioService.h"
michael@0 16 #include "DOMRequest.h"
michael@0 17 #include "nsDOMClassInfo.h"
michael@0 18 #include "nsIDocShell.h"
michael@0 19 #include "nsIInterfaceRequestorUtils.h"
michael@0 20 #include "nsIAudioManager.h"
michael@0 21
michael@0 22 #undef LOG
michael@0 23 #define LOG(args...) FM_LOG("FMRadio", args)
michael@0 24
michael@0 25 // The pref indicates if the device has an internal antenna.
michael@0 26 // If the pref is true, the antanna will be always available.
michael@0 27 #define DOM_FM_ANTENNA_INTERNAL_PREF "dom.fmradio.antenna.internal"
michael@0 28
michael@0 29 using namespace mozilla::hal;
michael@0 30 using mozilla::Preferences;
michael@0 31
michael@0 32 BEGIN_FMRADIO_NAMESPACE
michael@0 33
michael@0 34 class FMRadioRequest MOZ_FINAL : public FMRadioReplyRunnable
michael@0 35 , public DOMRequest
michael@0 36 {
michael@0 37 public:
michael@0 38 NS_DECL_ISUPPORTS_INHERITED
michael@0 39
michael@0 40 FMRadioRequest(nsPIDOMWindow* aWindow, FMRadio* aFMRadio)
michael@0 41 : DOMRequest(aWindow)
michael@0 42 , mType(FMRadioRequestArgs::T__None)
michael@0 43 {
michael@0 44 // |FMRadio| inherits from |nsIDOMEventTarget| and |nsISupportsWeakReference|
michael@0 45 // which both inherits from nsISupports, so |nsISupports| is an ambiguous
michael@0 46 // base of |FMRadio|, we have to cast |aFMRadio| to one of the base classes.
michael@0 47 mFMRadio = do_GetWeakReference(static_cast<nsIDOMEventTarget*>(aFMRadio));
michael@0 48 }
michael@0 49
michael@0 50 FMRadioRequest(nsPIDOMWindow* aWindow, FMRadio* aFMRadio,
michael@0 51 FMRadioRequestArgs::Type aType)
michael@0 52 : DOMRequest(aWindow)
michael@0 53 {
michael@0 54 MOZ_ASSERT(aType >= FMRadioRequestArgs::T__None &&
michael@0 55 aType <= FMRadioRequestArgs::T__Last,
michael@0 56 "Wrong FMRadioRequestArgs in FMRadioRequest");
michael@0 57
michael@0 58 mFMRadio = do_GetWeakReference(static_cast<nsIDOMEventTarget*>(aFMRadio));
michael@0 59 mType = aType;
michael@0 60 }
michael@0 61
michael@0 62 ~FMRadioRequest() { }
michael@0 63
michael@0 64 NS_IMETHODIMP
michael@0 65 Run()
michael@0 66 {
michael@0 67 MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
michael@0 68
michael@0 69 nsCOMPtr<nsIDOMEventTarget> target = do_QueryReferent(mFMRadio);
michael@0 70 if (!target) {
michael@0 71 return NS_OK;
michael@0 72 }
michael@0 73
michael@0 74 FMRadio* fmRadio = static_cast<FMRadio*>(
michael@0 75 static_cast<nsIDOMEventTarget*>(target));
michael@0 76
michael@0 77 if (fmRadio->mIsShutdown) {
michael@0 78 return NS_OK;
michael@0 79 }
michael@0 80
michael@0 81 switch (mResponseType.type()) {
michael@0 82 case FMRadioResponseType::TErrorResponse:
michael@0 83 FireError(mResponseType.get_ErrorResponse().error());
michael@0 84 break;
michael@0 85 case FMRadioResponseType::TSuccessResponse:
michael@0 86 if (mType == FMRadioRequestArgs::TEnableRequestArgs) {
michael@0 87 fmRadio->EnableAudioChannelAgent();
michael@0 88 }
michael@0 89
michael@0 90 FireSuccess(JS::UndefinedHandleValue);
michael@0 91 break;
michael@0 92 default:
michael@0 93 MOZ_CRASH();
michael@0 94 }
michael@0 95
michael@0 96 return NS_OK;
michael@0 97 }
michael@0 98
michael@0 99 private:
michael@0 100 FMRadioRequestArgs::Type mType;
michael@0 101 nsWeakPtr mFMRadio;
michael@0 102 };
michael@0 103
michael@0 104 NS_IMPL_ISUPPORTS_INHERITED0(FMRadioRequest, DOMRequest)
michael@0 105
michael@0 106 FMRadio::FMRadio()
michael@0 107 : mHeadphoneState(SWITCH_STATE_OFF)
michael@0 108 , mAudioChannelAgentEnabled(false)
michael@0 109 , mHasInternalAntenna(false)
michael@0 110 , mIsShutdown(false)
michael@0 111 {
michael@0 112 LOG("FMRadio is initialized.");
michael@0 113
michael@0 114 SetIsDOMBinding();
michael@0 115 }
michael@0 116
michael@0 117 FMRadio::~FMRadio()
michael@0 118 {
michael@0 119 }
michael@0 120
michael@0 121 void
michael@0 122 FMRadio::Init(nsPIDOMWindow *aWindow)
michael@0 123 {
michael@0 124 BindToOwner(aWindow);
michael@0 125
michael@0 126 IFMRadioService::Singleton()->AddObserver(this);
michael@0 127
michael@0 128 mHasInternalAntenna = Preferences::GetBool(DOM_FM_ANTENNA_INTERNAL_PREF,
michael@0 129 /* default = */ false);
michael@0 130 if (mHasInternalAntenna) {
michael@0 131 LOG("We have an internal antenna.");
michael@0 132 } else {
michael@0 133 mHeadphoneState = GetCurrentSwitchState(SWITCH_HEADPHONES);
michael@0 134 RegisterSwitchObserver(SWITCH_HEADPHONES, this);
michael@0 135 }
michael@0 136
michael@0 137 nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(GetOwner());
michael@0 138 NS_ENSURE_TRUE_VOID(target);
michael@0 139 target->AddSystemEventListener(NS_LITERAL_STRING("visibilitychange"), this,
michael@0 140 /* useCapture = */ true,
michael@0 141 /* wantsUntrusted = */ false);
michael@0 142
michael@0 143
michael@0 144 // All of the codes below are for AudioChannel. We can directly return here
michael@0 145 // if preferences doesn't enable AudioChannelService.
michael@0 146 NS_ENSURE_TRUE_VOID(Preferences::GetBool("media.useAudioChannelService"));
michael@0 147
michael@0 148 nsCOMPtr<nsIAudioChannelAgent> audioChannelAgent =
michael@0 149 do_CreateInstance("@mozilla.org/audiochannelagent;1");
michael@0 150 NS_ENSURE_TRUE_VOID(audioChannelAgent);
michael@0 151
michael@0 152 audioChannelAgent->InitWithWeakCallback(
michael@0 153 GetOwner(),
michael@0 154 nsIAudioChannelAgent::AUDIO_AGENT_CHANNEL_CONTENT,
michael@0 155 this);
michael@0 156
michael@0 157 nsCOMPtr<nsIDocShell> docshell = do_GetInterface(GetOwner());
michael@0 158 NS_ENSURE_TRUE_VOID(docshell);
michael@0 159
michael@0 160 bool isActive = false;
michael@0 161 docshell->GetIsActive(&isActive);
michael@0 162 audioChannelAgent->SetVisibilityState(isActive);
michael@0 163
michael@0 164 // Once all necessary resources are got successfully, we just enabled
michael@0 165 // mAudioChannelAgent.
michael@0 166 mAudioChannelAgent = audioChannelAgent;
michael@0 167 }
michael@0 168
michael@0 169 void
michael@0 170 FMRadio::Shutdown()
michael@0 171 {
michael@0 172 IFMRadioService::Singleton()->RemoveObserver(this);
michael@0 173
michael@0 174 if (!mHasInternalAntenna) {
michael@0 175 UnregisterSwitchObserver(SWITCH_HEADPHONES, this);
michael@0 176 }
michael@0 177
michael@0 178 nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(GetOwner());
michael@0 179 NS_ENSURE_TRUE_VOID(target);
michael@0 180 target->RemoveSystemEventListener(NS_LITERAL_STRING("visibilitychange"), this,
michael@0 181 /* useCapture = */ true);
michael@0 182
michael@0 183 mIsShutdown = true;
michael@0 184 }
michael@0 185
michael@0 186 JSObject*
michael@0 187 FMRadio::WrapObject(JSContext* aCx)
michael@0 188 {
michael@0 189 return FMRadioBinding::Wrap(aCx, this);
michael@0 190 }
michael@0 191
michael@0 192 void
michael@0 193 FMRadio::Notify(const SwitchEvent& aEvent)
michael@0 194 {
michael@0 195 MOZ_ASSERT(!mHasInternalAntenna);
michael@0 196
michael@0 197 if (mHeadphoneState != aEvent.status()) {
michael@0 198 mHeadphoneState = aEvent.status();
michael@0 199
michael@0 200 DispatchTrustedEvent(NS_LITERAL_STRING("antennaavailablechange"));
michael@0 201 }
michael@0 202 }
michael@0 203
michael@0 204 void
michael@0 205 FMRadio::Notify(const FMRadioEventType& aType)
michael@0 206 {
michael@0 207 switch (aType) {
michael@0 208 case FrequencyChanged:
michael@0 209 DispatchTrustedEvent(NS_LITERAL_STRING("frequencychange"));
michael@0 210 break;
michael@0 211 case EnabledChanged:
michael@0 212 if (Enabled()) {
michael@0 213 DispatchTrustedEvent(NS_LITERAL_STRING("enabled"));
michael@0 214 } else {
michael@0 215 if (mAudioChannelAgentEnabled) {
michael@0 216 mAudioChannelAgent->StopPlaying();
michael@0 217 mAudioChannelAgentEnabled = false;
michael@0 218 }
michael@0 219
michael@0 220 DispatchTrustedEvent(NS_LITERAL_STRING("disabled"));
michael@0 221 }
michael@0 222 break;
michael@0 223 default:
michael@0 224 MOZ_CRASH();
michael@0 225 }
michael@0 226 }
michael@0 227
michael@0 228 /* static */
michael@0 229 bool
michael@0 230 FMRadio::Enabled()
michael@0 231 {
michael@0 232 return IFMRadioService::Singleton()->IsEnabled();
michael@0 233 }
michael@0 234
michael@0 235 bool
michael@0 236 FMRadio::AntennaAvailable() const
michael@0 237 {
michael@0 238 return mHasInternalAntenna ? true : (mHeadphoneState != SWITCH_STATE_OFF) &&
michael@0 239 (mHeadphoneState != SWITCH_STATE_UNKNOWN);
michael@0 240 }
michael@0 241
michael@0 242 Nullable<double>
michael@0 243 FMRadio::GetFrequency() const
michael@0 244 {
michael@0 245 return Enabled() ?
michael@0 246 Nullable<double>(IFMRadioService::Singleton()->GetFrequency()) :
michael@0 247 Nullable<double>();
michael@0 248 }
michael@0 249
michael@0 250 double
michael@0 251 FMRadio::FrequencyUpperBound() const
michael@0 252 {
michael@0 253 return IFMRadioService::Singleton()->GetFrequencyUpperBound();
michael@0 254 }
michael@0 255
michael@0 256 double
michael@0 257 FMRadio::FrequencyLowerBound() const
michael@0 258 {
michael@0 259 return IFMRadioService::Singleton()->GetFrequencyLowerBound();
michael@0 260 }
michael@0 261
michael@0 262 double
michael@0 263 FMRadio::ChannelWidth() const
michael@0 264 {
michael@0 265 return IFMRadioService::Singleton()->GetChannelWidth();
michael@0 266 }
michael@0 267
michael@0 268 already_AddRefed<DOMRequest>
michael@0 269 FMRadio::Enable(double aFrequency)
michael@0 270 {
michael@0 271 nsCOMPtr<nsPIDOMWindow> win = GetOwner();
michael@0 272 if (!win) {
michael@0 273 return nullptr;
michael@0 274 }
michael@0 275
michael@0 276 nsRefPtr<FMRadioRequest> r =
michael@0 277 new FMRadioRequest(win, this, FMRadioRequestArgs::TEnableRequestArgs);
michael@0 278 IFMRadioService::Singleton()->Enable(aFrequency, r);
michael@0 279
michael@0 280 return r.forget();
michael@0 281 }
michael@0 282
michael@0 283 already_AddRefed<DOMRequest>
michael@0 284 FMRadio::Disable()
michael@0 285 {
michael@0 286 nsCOMPtr<nsPIDOMWindow> win = GetOwner();
michael@0 287 if (!win) {
michael@0 288 return nullptr;
michael@0 289 }
michael@0 290
michael@0 291 nsRefPtr<FMRadioRequest> r = new FMRadioRequest(win, this);
michael@0 292 IFMRadioService::Singleton()->Disable(r);
michael@0 293
michael@0 294 return r.forget();
michael@0 295 }
michael@0 296
michael@0 297 already_AddRefed<DOMRequest>
michael@0 298 FMRadio::SetFrequency(double aFrequency)
michael@0 299 {
michael@0 300 nsCOMPtr<nsPIDOMWindow> win = GetOwner();
michael@0 301 if (!win) {
michael@0 302 return nullptr;
michael@0 303 }
michael@0 304
michael@0 305 nsRefPtr<FMRadioRequest> r = new FMRadioRequest(win, this);
michael@0 306 IFMRadioService::Singleton()->SetFrequency(aFrequency, r);
michael@0 307
michael@0 308 return r.forget();
michael@0 309 }
michael@0 310
michael@0 311 already_AddRefed<DOMRequest>
michael@0 312 FMRadio::SeekUp()
michael@0 313 {
michael@0 314 nsCOMPtr<nsPIDOMWindow> win = GetOwner();
michael@0 315 if (!win) {
michael@0 316 return nullptr;
michael@0 317 }
michael@0 318
michael@0 319 nsRefPtr<FMRadioRequest> r = new FMRadioRequest(win, this);
michael@0 320 IFMRadioService::Singleton()->Seek(FM_RADIO_SEEK_DIRECTION_UP, r);
michael@0 321
michael@0 322 return r.forget();
michael@0 323 }
michael@0 324
michael@0 325 already_AddRefed<DOMRequest>
michael@0 326 FMRadio::SeekDown()
michael@0 327 {
michael@0 328 nsCOMPtr<nsPIDOMWindow> win = GetOwner();
michael@0 329 if (!win) {
michael@0 330 return nullptr;
michael@0 331 }
michael@0 332
michael@0 333 nsRefPtr<FMRadioRequest> r = new FMRadioRequest(win, this);
michael@0 334 IFMRadioService::Singleton()->Seek(FM_RADIO_SEEK_DIRECTION_DOWN, r);
michael@0 335
michael@0 336 return r.forget();
michael@0 337 }
michael@0 338
michael@0 339 already_AddRefed<DOMRequest>
michael@0 340 FMRadio::CancelSeek()
michael@0 341 {
michael@0 342 nsCOMPtr<nsPIDOMWindow> win = GetOwner();
michael@0 343 if (!win) {
michael@0 344 return nullptr;
michael@0 345 }
michael@0 346
michael@0 347 nsRefPtr<FMRadioRequest> r = new FMRadioRequest(win, this);
michael@0 348 IFMRadioService::Singleton()->CancelSeek(r);
michael@0 349
michael@0 350 return r.forget();
michael@0 351 }
michael@0 352
michael@0 353 NS_IMETHODIMP
michael@0 354 FMRadio::HandleEvent(nsIDOMEvent* aEvent)
michael@0 355 {
michael@0 356 nsAutoString type;
michael@0 357 aEvent->GetType(type);
michael@0 358
michael@0 359 if (!type.EqualsLiteral("visibilitychange")) {
michael@0 360 return NS_ERROR_FAILURE;
michael@0 361 }
michael@0 362
michael@0 363 nsCOMPtr<nsIDocShell> docshell = do_GetInterface(GetOwner());
michael@0 364 NS_ENSURE_TRUE(docshell, NS_ERROR_FAILURE);
michael@0 365
michael@0 366 bool isActive = false;
michael@0 367 docshell->GetIsActive(&isActive);
michael@0 368
michael@0 369 mAudioChannelAgent->SetVisibilityState(isActive);
michael@0 370 return NS_OK;
michael@0 371 }
michael@0 372
michael@0 373 void
michael@0 374 FMRadio::EnableAudioChannelAgent()
michael@0 375 {
michael@0 376 NS_ENSURE_TRUE_VOID(mAudioChannelAgent);
michael@0 377
michael@0 378 int32_t playingState = 0;
michael@0 379 mAudioChannelAgent->StartPlaying(&playingState);
michael@0 380 SetCanPlay(playingState == AudioChannelState::AUDIO_CHANNEL_STATE_NORMAL);
michael@0 381
michael@0 382 mAudioChannelAgentEnabled = true;
michael@0 383 }
michael@0 384
michael@0 385 NS_IMETHODIMP
michael@0 386 FMRadio::CanPlayChanged(int32_t aCanPlay)
michael@0 387 {
michael@0 388 SetCanPlay(aCanPlay == AudioChannelState::AUDIO_CHANNEL_STATE_NORMAL);
michael@0 389 return NS_OK;
michael@0 390 }
michael@0 391
michael@0 392 NS_IMETHODIMP
michael@0 393 FMRadio::WindowVolumeChanged()
michael@0 394 {
michael@0 395 return NS_ERROR_NOT_IMPLEMENTED;
michael@0 396 }
michael@0 397
michael@0 398 void
michael@0 399 FMRadio::SetCanPlay(bool aCanPlay)
michael@0 400 {
michael@0 401 IFMRadioService::Singleton()->EnableAudio(aCanPlay);
michael@0 402 }
michael@0 403
michael@0 404 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(FMRadio)
michael@0 405 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
michael@0 406 NS_INTERFACE_MAP_ENTRY(nsIAudioChannelAgentCallback)
michael@0 407 NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
michael@0 408 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
michael@0 409
michael@0 410 NS_IMPL_ADDREF_INHERITED(FMRadio, DOMEventTargetHelper)
michael@0 411 NS_IMPL_RELEASE_INHERITED(FMRadio, DOMEventTargetHelper)
michael@0 412
michael@0 413 END_FMRADIO_NAMESPACE
michael@0 414

mercurial