Bug 1254378 - Make SpeechSynthesis an event target with a "voiceschanged" event. r=smaug
authorEitan Isaacson <eitan@monotonous.org>
Wed, 23 Mar 2016 10:30:00 -0700
changeset 291116 7f8bd64aaadd033af0bd933cbb0f2dca4c2b9245
parent 291115 b78ed68af2fb7051771b49260d7f5394a7c30c63
child 291117 3ace54af7a05d57bb02b4360a09c156fd5442d0e
push id19656
push usergwagner@mozilla.com
push dateMon, 04 Apr 2016 13:43:23 +0000
treeherderb2g-inbound@e99061fde28a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1254378
milestone48.0a1
Bug 1254378 - Make SpeechSynthesis an event target with a "voiceschanged" event. r=smaug MozReview-Commit-ID: AmreVzU18LI
dom/base/nsGkAtomList.h
dom/media/webspeech/synth/SpeechSynthesis.cpp
dom/media/webspeech/synth/SpeechSynthesis.h
dom/webidl/SpeechSynthesis.webidl
--- a/dom/base/nsGkAtomList.h
+++ b/dom/base/nsGkAtomList.h
@@ -934,16 +934,17 @@ GK_ATOM(ontransitionend, "ontransitionen
 GK_ATOM(onunderflow, "onunderflow")
 GK_ATOM(onunload, "onunload")
 GK_ATOM(onupdatefound, "onupdatefound")
 GK_ATOM(onupdateready, "onupdateready")
 GK_ATOM(onupgradeneeded, "onupgradeneeded")
 GK_ATOM(onussdreceived, "onussdreceived")
 GK_ATOM(onversionchange, "onversionchange")
 GK_ATOM(onvoicechange, "onvoicechange")
+GK_ATOM(onvoiceschanged, "onvoiceschanged")
 GK_ATOM(onwebkitAnimationEnd, "onwebkitAnimationEnd")
 GK_ATOM(onwebkitAnimationIteration, "onwebkitAnimationIteration")
 GK_ATOM(onwebkitAnimationStart, "onwebkitAnimationStart")
 GK_ATOM(onwebkitTransitionEnd, "onwebkitTransitionEnd")
 GK_ATOM(onwheel, "onwheel")
 GK_ATOM(open, "open")
 GK_ATOM(optgroup, "optgroup")
 GK_ATOM(optimum, "optimum")
--- a/dom/media/webspeech/synth/SpeechSynthesis.cpp
+++ b/dom/media/webspeech/synth/SpeechSynthesis.cpp
@@ -26,51 +26,41 @@ GetSpeechSynthLog()
 }
 #define LOG(type, msg) MOZ_LOG(GetSpeechSynthLog(), type, msg)
 
 namespace mozilla {
 namespace dom {
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(SpeechSynthesis)
 
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(SpeechSynthesis)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(SpeechSynthesis, DOMEventTargetHelper)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mCurrentTask)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mSpeechQueue)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
   tmp->mVoiceCache.Clear();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(SpeechSynthesis)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(SpeechSynthesis, DOMEventTargetHelper)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCurrentTask)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSpeechQueue)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
   for (auto iter = tmp->mVoiceCache.Iter(); !iter.Done(); iter.Next()) {
     SpeechSynthesisVoice* voice = iter.UserData();
     cb.NoteXPCOMChild(voice);
   }
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
-NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(SpeechSynthesis)
-  NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
-NS_IMPL_CYCLE_COLLECTION_TRACE_END
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(SpeechSynthesis)
-  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIObserver)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(SpeechSynthesis)
   NS_INTERFACE_MAP_ENTRY(nsIObserver)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
-NS_INTERFACE_MAP_END
+NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
 
-NS_IMPL_CYCLE_COLLECTING_ADDREF(SpeechSynthesis)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(SpeechSynthesis)
+NS_IMPL_ADDREF_INHERITED(SpeechSynthesis, DOMEventTargetHelper)
+NS_IMPL_RELEASE_INHERITED(SpeechSynthesis, DOMEventTargetHelper)
 
 SpeechSynthesis::SpeechSynthesis(nsPIDOMWindowInner* aParent)
-  : mParent(aParent)
+  : DOMEventTargetHelper(aParent)
   , mHoldQueue(false)
   , mInnerID(aParent->WindowID())
 {
   MOZ_ASSERT(aParent->IsInnerWindow());
   MOZ_ASSERT(NS_IsMainThread());
 
   nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   if (obs) {
@@ -84,22 +74,16 @@ SpeechSynthesis::~SpeechSynthesis()
 }
 
 JSObject*
 SpeechSynthesis::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return SpeechSynthesisBinding::Wrap(aCx, this, aGivenProto);
 }
 
-nsPIDOMWindowInner*
-SpeechSynthesis::GetParentObject() const
-{
-  return mParent;
-}
-
 bool
 SpeechSynthesis::Pending() const
 {
   switch (mSpeechQueue.Length()) {
   case 0:
     return false;
 
   case 1:
@@ -159,17 +143,18 @@ SpeechSynthesis::AdvanceQueue()
 
   if (mSpeechQueue.IsEmpty()) {
     return;
   }
 
   RefPtr<SpeechSynthesisUtterance> utterance = mSpeechQueue.ElementAt(0);
 
   nsAutoString docLang;
-  nsIDocument* doc = mParent->GetExtantDoc();
+  nsCOMPtr<nsPIDOMWindowInner> window = GetOwner();
+  nsIDocument* doc = window ? window->GetExtantDoc() : nullptr;
 
   if (doc) {
     Element* elm = doc->GetHtmlElement();
 
     if (elm) {
       elm->GetLang(docLang);
     }
   }
--- a/dom/media/webspeech/synth/SpeechSynthesis.h
+++ b/dom/media/webspeech/synth/SpeechSynthesis.h
@@ -20,30 +20,27 @@
 
 class nsIDOMWindow;
 
 namespace mozilla {
 namespace dom {
 
 class nsSpeechTask;
 
-class SpeechSynthesis final : public nsIObserver
-                            , public nsWrapperCache
+class SpeechSynthesis final : public DOMEventTargetHelper
+                            , public nsIObserver
                             , public nsSupportsWeakReference
 {
 public:
   explicit SpeechSynthesis(nsPIDOMWindowInner* aParent);
 
-  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(SpeechSynthesis,
-                                                         nsIObserver)
+  NS_DECL_ISUPPORTS_INHERITED
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(SpeechSynthesis, DOMEventTargetHelper)
   NS_DECL_NSIOBSERVER
 
-  nsPIDOMWindowInner* GetParentObject() const;
-
   JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   bool Pending() const;
 
   bool Speaking() const;
 
   bool Paused() const;
 
@@ -58,23 +55,23 @@ public:
   void Resume();
 
   void OnEnd(const nsSpeechTask* aTask);
 
   void GetVoices(nsTArray< RefPtr<SpeechSynthesisVoice> >& aResult);
 
   void ForceEnd();
 
+  IMPL_EVENT_HANDLER(voiceschanged)
+
 private:
   virtual ~SpeechSynthesis();
 
   void AdvanceQueue();
 
-  nsCOMPtr<nsPIDOMWindowInner> mParent;
-
   nsTArray<RefPtr<SpeechSynthesisUtterance> > mSpeechQueue;
 
   RefPtr<nsSpeechTask> mCurrentTask;
 
   nsRefPtrHashtable<nsStringHashKey, SpeechSynthesisVoice> mVoiceCache;
 
   bool mHoldQueue;
 
--- a/dom/webidl/SpeechSynthesis.webidl
+++ b/dom/webidl/SpeechSynthesis.webidl
@@ -6,25 +6,27 @@
  * The origin of this IDL file is
  * http://dvcs.w3.org/hg/speech-api/raw-file/tip/speechapi.html
  *
  * Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
  * liability, trademark and document use rules apply.
  */
 
 [Pref="media.webspeech.synth.enabled"]
-interface SpeechSynthesis {
+interface SpeechSynthesis : EventTarget{
   readonly attribute boolean pending;
   readonly attribute boolean speaking;
   readonly attribute boolean paused;
 
   [UnsafeInPrerendering]
   void speak(SpeechSynthesisUtterance utterance);
   void cancel();
   void pause();
   [UnsafeInPrerendering]
   void resume();
   sequence<SpeechSynthesisVoice> getVoices();
 
+  attribute EventHandler onvoiceschanged;
+
   [ChromeOnly]
   // Force an utterance to end. Circumvents bad speech service implementations.
   void forceEnd();
 };