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 291057 7f8bd64aaadd033af0bd933cbb0f2dca4c2b9245
parent 291056 b78ed68af2fb7051771b49260d7f5394a7c30c63
child 291058 3ace54af7a05d57bb02b4360a09c156fd5442d0e
push id74438
push usereisaacson@mozilla.com
push dateFri, 01 Apr 2016 00:05:56 +0000
treeherdermozilla-inbound@f2c661c123c0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1254378
milestone48.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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();
 };