Bug 998872 - [Stingray] TV Manager API. Part 4 - TV channel & TV program. r=ehsan
authorSean Lin <selin@mozilla.com>
Fri, 22 Aug 2014 13:53:39 +0800
changeset 212872 edf60abe62a5a7da09c9caed36ab49bb65a10558
parent 212871 544aa604483f62f0b99fa3112c4df3ec47b6a0e8
child 212873 34b56f3f0cbc5a828486f496758c9bab3a16ebaf
push id27734
push userryanvm@gmail.com
push dateWed, 29 Oct 2014 20:15:52 +0000
treeherdermozilla-central@8345ae427a3f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersehsan
bugs998872
milestone36.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 998872 - [Stingray] TV Manager API. Part 4 - TV channel & TV program. r=ehsan
dom/tv/TVChannel.cpp
dom/tv/TVChannel.h
dom/tv/TVProgram.cpp
dom/tv/TVProgram.h
dom/tv/TVServiceCallbacks.cpp
dom/tv/TVSource.cpp
--- a/dom/tv/TVChannel.cpp
+++ b/dom/tv/TVChannel.cpp
@@ -1,135 +1,213 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/Promise.h"
+#include "mozilla/dom/TVServiceCallbacks.h"
+#include "mozilla/dom/TVServiceFactory.h"
+#include "mozilla/dom/TVSource.h"
+#include "mozilla/dom/TVTuner.h"
+#include "mozilla/dom/TVUtils.h"
+#include "nsITVService.h"
+#include "nsServiceManagerUtils.h"
 #include "TVChannel.h"
 
 namespace mozilla {
 namespace dom {
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(TVChannel)
-
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(TVChannel,
-                                                  DOMEventTargetHelper)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(TVChannel,
-                                                DOMEventTargetHelper)
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+NS_IMPL_CYCLE_COLLECTION_INHERITED(TVChannel, DOMEventTargetHelper,
+                                   mTVService, mSource)
 
 NS_IMPL_ADDREF_INHERITED(TVChannel, DOMEventTargetHelper)
 NS_IMPL_RELEASE_INHERITED(TVChannel, DOMEventTargetHelper)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(TVChannel)
 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
 
-TVChannel::TVChannel(nsPIDOMWindow* aWindow)
+TVChannel::TVChannel(nsPIDOMWindow* aWindow,
+                     TVSource* aSource)
   : DOMEventTargetHelper(aWindow)
+  , mSource(aSource)
 {
+  MOZ_ASSERT(mSource);
 }
 
 TVChannel::~TVChannel()
 {
 }
 
+/* static */ already_AddRefed<TVChannel>
+TVChannel::Create(nsPIDOMWindow* aWindow,
+                  TVSource* aSource,
+                  nsITVChannelData* aData)
+{
+  nsRefPtr<TVChannel> channel = new TVChannel(aWindow, aSource);
+  return (channel->Init(aData)) ? channel.forget() : nullptr;
+}
+
+bool
+TVChannel::Init(nsITVChannelData* aData)
+{
+  NS_ENSURE_TRUE(aData, false);
+
+  nsString channelType;
+  aData->GetType(channelType);
+  mType = ToTVChannelType(channelType);
+  if (NS_WARN_IF(mType == TVChannelType::EndGuard_)) {
+    return false;
+  }
+
+  aData->GetNetworkId(mNetworkId);
+  aData->GetTransportStreamId(mTransportStreamId);
+  aData->GetServiceId(mServiceId);
+  aData->GetName(mName);
+  aData->GetNumber(mNumber);
+  aData->GetIsEmergency(&mIsEmergency);
+  aData->GetIsFree(&mIsFree);
+
+  mTVService = TVServiceFactory::AutoCreateTVService();
+  NS_ENSURE_TRUE(mTVService, false);
+
+  return true;
+}
+
 /* virtual */ JSObject*
 TVChannel::WrapObject(JSContext* aCx)
 {
   return TVChannelBinding::Wrap(aCx, this);
 }
 
+nsresult
+TVChannel::DispatchTVEvent(nsIDOMEvent* aEvent)
+{
+  return DispatchTrustedEvent(aEvent);
+}
+
 already_AddRefed<Promise>
 TVChannel::GetPrograms(const TVGetProgramsOptions& aOptions, ErrorResult& aRv)
 {
   nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
   MOZ_ASSERT(global);
 
   nsRefPtr<Promise> promise = Promise::Create(global, aRv);
-  if (aRv.Failed()) {
+  if (NS_WARN_IF(aRv.Failed())) {
     return nullptr;
   }
 
-  // TODO Resolve/reject the promise in follow-up patches.
+  nsRefPtr<TVTuner> tuner = mSource->Tuner();
+  nsString tunerId;
+  tuner->GetId(tunerId);
+
+  uint64_t startTime = aOptions.mStartTime.WasPassed() ?
+                       aOptions.mStartTime.Value() :
+                       PR_Now();
+  uint64_t endTime = aOptions.mDuration.WasPassed() ?
+                     (startTime + aOptions.mDuration.Value()) :
+                     std::numeric_limits<uint64_t>::max();
+  nsCOMPtr<nsITVServiceCallback> callback =
+    new TVServiceProgramGetterCallback(this, promise, false);
+  nsresult rv =
+    mTVService->GetPrograms(tunerId,
+                            ToTVSourceTypeStr(mSource->Type()),
+                            mNumber,
+                            startTime,
+                            endTime,
+                            callback);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
+  }
 
   return promise.forget();
 }
 
 void
 TVChannel::GetNetworkId(nsAString& aNetworkId) const
 {
-  // TODO Implement in follow-up patches.
+  aNetworkId = mNetworkId;
 }
 
 void
 TVChannel::GetTransportStreamId(nsAString& aTransportStreamId) const
 {
-  // TODO Implement in follow-up patches.
+  aTransportStreamId = mTransportStreamId;
 }
 
 void
 TVChannel::GetServiceId(nsAString& aServiceId) const
 {
-  // TODO Implement in follow-up patches.
+  aServiceId = mServiceId;
 }
 
 already_AddRefed<TVSource>
 TVChannel::Source() const
 {
-  // TODO Implement in follow-up patches.
-  return nullptr;
+  nsRefPtr<TVSource> source = mSource;
+  return source.forget();
 }
 
 TVChannelType
 TVChannel::Type() const
 {
-  // TODO Implement in follow-up patches.
-  return TVChannelType::Tv;
+  return mType;
 }
 
 void
 TVChannel::GetName(nsAString& aName) const
 {
-  // TODO Implement in follow-up patches.
+  aName = mName;
 }
 
 void
 TVChannel::GetNumber(nsAString& aNumber) const
 {
-  // TODO Implement in follow-up patches.
+  aNumber = mNumber;
 }
 
 bool
 TVChannel::IsEmergency() const
 {
-  // TODO Implement in follow-up patches.
-  return false;
+  return mIsEmergency;
 }
 
 bool
 TVChannel::IsFree() const
 {
-  // TODO Implement in follow-up patches.
-  return false;
+  return mIsFree;
 }
 
 already_AddRefed<Promise>
 TVChannel::GetCurrentProgram(ErrorResult& aRv)
 {
   nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
   MOZ_ASSERT(global);
 
   nsRefPtr<Promise> promise = Promise::Create(global, aRv);
   if (aRv.Failed()) {
     return nullptr;
   }
 
-  // TODO Resolve/reject the promise in follow-up patches.
+  nsRefPtr<TVTuner> tuner = mSource->Tuner();
+  nsString tunerId;
+  tuner->GetId(tunerId);
+
+  // Get only one program from now on.
+  nsCOMPtr<nsITVServiceCallback> callback =
+    new TVServiceProgramGetterCallback(this, promise, true);
+  nsresult rv =
+    mTVService->GetPrograms(tunerId,
+                            ToTVSourceTypeStr(mSource->Type()),
+                            mNumber,
+                            PR_Now(),
+                            std::numeric_limits<uint64_t>::max(),
+                            callback);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
+  }
 
   return promise.forget();
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/tv/TVChannel.h
+++ b/dom/tv/TVChannel.h
@@ -1,40 +1,47 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef mozilla_dom_TVChannel_h__
-#define mozilla_dom_TVChannel_h__
+#ifndef mozilla_dom_TVChannel_h
+#define mozilla_dom_TVChannel_h
 
 #include "mozilla/DOMEventTargetHelper.h"
 // Include TVChannelBinding.h since enum TVChannelType can't be forward declared.
 #include "mozilla/dom/TVChannelBinding.h"
 
+class nsITVChannelData;
+class nsITVService;
+
 namespace mozilla {
 namespace dom {
 
 class Promise;
 class TVProgram;
 class TVSource;
 
 class TVChannel MOZ_FINAL : public DOMEventTargetHelper
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(TVChannel, DOMEventTargetHelper)
 
-  explicit TVChannel(nsPIDOMWindow* aWindow);
+  static already_AddRefed<TVChannel> Create(nsPIDOMWindow* aWindow,
+                                            TVSource* aSource,
+                                            nsITVChannelData* aData);
 
   // WebIDL (internal functions)
 
   virtual JSObject* WrapObject(JSContext *aCx) MOZ_OVERRIDE;
 
+  nsresult DispatchTVEvent(nsIDOMEvent* aEvent);
+
   // WebIDL (public APIs)
 
   already_AddRefed<Promise> GetPrograms(const TVGetProgramsOptions& aOptions,
                                         ErrorResult& aRv);
 
   already_AddRefed<Promise> GetCurrentProgram(ErrorResult& aRv);
 
   void GetNetworkId(nsAString& aNetworkId) const;
@@ -51,16 +58,31 @@ public:
 
   void GetNumber(nsAString& aNumber) const;
 
   bool IsEmergency() const;
 
   bool IsFree() const;
 
 private:
+  TVChannel(nsPIDOMWindow* aWindow,
+            TVSource* aSource);
+
   ~TVChannel();
 
+  bool Init(nsITVChannelData* aData);
+
+  nsCOMPtr<nsITVService> mTVService;
+  nsRefPtr<TVSource> mSource;
+  nsString mNetworkId;
+  nsString mTransportStreamId;
+  nsString mServiceId;
+  TVChannelType mType;
+  nsString mNumber;
+  nsString mName;
+  bool mIsEmergency;
+  bool mIsFree;
 };
 
 } // namespace dom
 } // namespace mozilla
 
-#endif // mozilla_dom_TVChannel_h__
+#endif // mozilla_dom_TVChannel_h
--- a/dom/tv/TVProgram.cpp
+++ b/dom/tv/TVProgram.cpp
@@ -1,96 +1,128 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+#include "mozilla/dom/TVChannel.h"
 #include "mozilla/dom/TVProgramBinding.h"
+#include "nsITVService.h"
 #include "TVProgram.h"
 
 namespace mozilla {
 namespace dom {
 
-NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(TVProgram, mOwner)
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(TVProgram, mOwner, mChannel)
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(TVProgram)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(TVProgram)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TVProgram)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
-TVProgram::TVProgram(nsISupports* aOwner)
+TVProgram::TVProgram(nsISupports* aOwner,
+                     TVChannel* aChannel,
+                     nsITVProgramData* aData)
   : mOwner(aOwner)
+  , mChannel(aChannel)
 {
+  MOZ_ASSERT(mChannel);
+  MOZ_ASSERT(aData);
+
+  aData->GetEventId(mEventId);
+  aData->GetTitle(mTitle);
+  aData->GetStartTime(&mStartTime);
+  aData->GetDuration(&mDuration);
+  aData->GetDescription(mDescription);
+  aData->GetRating(mRating);
+
+  uint32_t count;
+  char** languages;
+  aData->GetAudioLanguages(&count, &languages);
+  SetLanguages(count, languages, mAudioLanguages);
+  aData->GetSubtitleLanguages(&count, &languages);
+  SetLanguages(count, languages, mSubtitleLanguages);
 }
 
 TVProgram::~TVProgram()
 {
 }
 
 /* virtual */ JSObject*
 TVProgram::WrapObject(JSContext* aCx)
 {
   return TVProgramBinding::Wrap(aCx, this);
 }
 
 void
 TVProgram::GetAudioLanguages(nsTArray<nsString>& aLanguages) const
 {
-  // TODO Implement in follow-up patches.
+  aLanguages = mAudioLanguages;
 }
 
 void
 TVProgram::GetSubtitleLanguages(nsTArray<nsString>& aLanguages) const
 {
-  // TODO Implement in follow-up patches.
+  aLanguages = mSubtitleLanguages;
 }
 
 void
 TVProgram::GetEventId(nsAString& aEventId) const
 {
-  // TODO Implement in follow-up patches.
+  aEventId = mEventId;
 }
 
 already_AddRefed<TVChannel>
 TVProgram::Channel() const
 {
-  // TODO Implement in follow-up patches.
-  return nullptr;
+  nsRefPtr<TVChannel> channel = mChannel;
+  return channel.forget();
 }
 
 void
 TVProgram::GetTitle(nsAString& aTitle) const
 {
-  // TODO Implement in follow-up patches.
+  aTitle = mTitle;
 }
 
 uint64_t
 TVProgram::StartTime() const
 {
-  // TODO Implement in follow-up patches.
-  return 0;
+  return mStartTime;
 }
 
 uint64_t
 TVProgram::Duration() const
 {
-  // TODO Implement in follow-up patches.
-  return 0;
+  return mDuration;
 }
 
 void
 TVProgram::GetDescription(nsAString& aDescription) const
 {
-  // TODO Implement in follow-up patches.
+  aDescription = mDescription;
 }
 
 void
 TVProgram::GetRating(nsAString& aRating) const
 {
-  // TODO Implement in follow-up patches.
+  aRating = mRating;
+}
+
+void
+TVProgram::SetLanguages(uint32_t aCount,
+                        char** aLanguages,
+                        nsTArray<nsString>& aLanguageList)
+{
+  for (uint32_t i = 0; i < aCount; i++) {
+    nsString language;
+    language.AssignASCII(aLanguages[i]);
+    aLanguageList.AppendElement(language);
+  }
+  NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(aCount, aLanguages);
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/tv/TVProgram.h
+++ b/dom/tv/TVProgram.h
@@ -1,32 +1,36 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef mozilla_dom_TVProgram_h__
-#define mozilla_dom_TVProgram_h__
+#ifndef mozilla_dom_TVProgram_h
+#define mozilla_dom_TVProgram_h
 
 #include "nsWrapperCache.h"
 
+class nsITVProgramData;
+
 namespace mozilla {
 namespace dom {
 
 class TVChannel;
 
 class TVProgram MOZ_FINAL : public nsISupports
                           , public nsWrapperCache
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(TVProgram)
 
-  explicit TVProgram(nsISupports* aOwner);
+  TVProgram(nsISupports* aOwner,
+            TVChannel* aChannel,
+            nsITVProgramData* aData);
 
   // WebIDL (internal functions)
 
   nsISupports* GetParentObject() const
   {
     return mOwner;
   }
 
@@ -50,15 +54,29 @@ public:
 
   void GetDescription(nsAString& aDescription) const;
 
   void GetRating(nsAString& aRating) const;
 
 private:
   ~TVProgram();
 
+  void SetLanguages(uint32_t aCount,
+                    char** aLanguages,
+                    nsTArray<nsString>& aLanguageList);
+
   nsCOMPtr<nsISupports> mOwner;
+  nsRefPtr<TVChannel> mChannel;
+  nsString mEventId;
+  nsString mTitle;
+  uint64_t mStartTime;
+  uint64_t mDuration;
+  nsString mDescription;
+  nsString mRating;
+  bool mIsInterrupting;
+  nsTArray<nsString> mAudioLanguages;
+  nsTArray<nsString> mSubtitleLanguages;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_TVProgram_h__
--- a/dom/tv/TVServiceCallbacks.cpp
+++ b/dom/tv/TVServiceCallbacks.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/TVManager.h"
+#include "mozilla/dom/TVProgram.h"
 #include "mozilla/dom/TVSource.h"
 #include "mozilla/dom/TVTuner.h"
 #include "nsArrayUtils.h"
 #include "TVServiceCallbacks.h"
 
 namespace mozilla {
 namespace dom {
 
@@ -354,17 +355,18 @@ TVServiceChannelGetterCallback::NotifySu
   nsTArray<nsRefPtr<TVChannel>> channels(length);
   for (uint32_t i = 0; i < length; i++) {
     nsCOMPtr<nsITVChannelData> channelData = do_QueryElementAt(aDataList, i);
     if (NS_WARN_IF(!channelData)) {
       mPromise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
       return NS_ERROR_DOM_ABORT_ERR;
     }
 
-    nsRefPtr<TVChannel> channel = new TVChannel(mSource->GetOwner());
+    nsRefPtr<TVChannel> channel =
+      TVChannel::Create(mSource->GetOwner(), mSource, channelData);
     channels.AppendElement(channel);
   }
 
   mPromise->MaybeResolve(channels);
 
   return NS_OK;
 }
 
@@ -419,18 +421,55 @@ TVServiceProgramGetterCallback::~TVServi
 
 /* virtual */ NS_IMETHODIMP
 TVServiceProgramGetterCallback::NotifySuccess(nsIArray* aDataList)
 {
   if (!aDataList) {
     return NS_ERROR_INVALID_ARG;
   }
 
-  // TODO Store the results to MozStorage in follow-up patches.
+  uint32_t length;
+  nsresult rv = aDataList->GetLength(&length);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    mPromise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
+    return rv;
+  }
+
+  if (mIsSingular && length == 0) {
+    mPromise->MaybeResolve(JS::UndefinedHandleValue);
+    return NS_OK;
+  }
+
+  if (mIsSingular) {
+    nsCOMPtr<nsITVProgramData> programData = do_QueryElementAt(aDataList, 0);
+    if (NS_WARN_IF(!programData)) {
+      mPromise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
+      return NS_ERROR_DOM_ABORT_ERR;
+    }
 
+    nsRefPtr<TVProgram> program = new TVProgram(mChannel->GetOwner(), mChannel,
+                                                programData);
+    mPromise->MaybeResolve(program);
+    return NS_OK;
+  }
+
+  nsTArray<nsRefPtr<TVProgram>> programs(length);
+  for (uint32_t i = 0; i < length; i++) {
+    nsCOMPtr<nsITVProgramData> programData = do_QueryElementAt(aDataList, i);
+    if (NS_WARN_IF(!programData)) {
+      mPromise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
+      return NS_ERROR_DOM_ABORT_ERR;
+    }
+
+    nsRefPtr<TVProgram> program = new TVProgram(mChannel->GetOwner(), mChannel,
+                                                programData);
+    programs.AppendElement(program);
+  }
+
+  mPromise->MaybeResolve(programs);
   return NS_OK;
 }
 
 /* virtual */ NS_IMETHODIMP
 TVServiceProgramGetterCallback::NotifyError(uint16_t aErrorCode)
 {
   switch (aErrorCode) {
   case nsITVServiceCallback::TV_ERROR_FAILURE:
--- a/dom/tv/TVSource.cpp
+++ b/dom/tv/TVSource.cpp
@@ -125,18 +125,18 @@ TVSource::SetCurrentChannel(nsITVChannel
     nsString currentChannelNumber;
     mCurrentChannel->GetNumber(currentChannelNumber);
     if (newChannelNumber.Equals(currentChannelNumber)) {
       // No actual change.
       return NS_OK;
     }
   }
 
-  // TODO Use channel data to initialize TVChannel in follow-up patches.
-  mCurrentChannel = new TVChannel(GetOwner());
+  mCurrentChannel = TVChannel::Create(GetOwner(), this, aChannelData);
+  NS_ENSURE_TRUE(mCurrentChannel, NS_ERROR_DOM_ABORT_ERR);
 
   return DispatchCurrentChannelChangedEvent(mCurrentChannel);
 }
 
 nsresult
 TVSource::UnsetCurrentChannel()
 {
   mCurrentChannel = nullptr;
@@ -314,18 +314,19 @@ TVSource::GetCurrentChannel() const
 {
   nsRefPtr<TVChannel> currentChannel = mCurrentChannel;
   return currentChannel.forget();
 }
 
 nsresult
 TVSource::NotifyChannelScanned(nsITVChannelData* aChannelData)
 {
-  // TODO Use channel data to initialize TVChannel in follow-up patches.
-  nsRefPtr<TVChannel> channel = new TVChannel(GetOwner());
+  nsRefPtr<TVChannel> channel = TVChannel::Create(GetOwner(), this, aChannelData);
+  NS_ENSURE_TRUE(channel, NS_ERROR_DOM_ABORT_ERR);
+
   return DispatchScanningStateChangedEvent(TVScanningState::Scanned, channel);
 }
 
 nsresult
 TVSource::NotifyChannelScanComplete()
 {
   SetIsScanning(false);
   return DispatchScanningStateChangedEvent(TVScanningState::Completed, nullptr);
@@ -338,22 +339,21 @@ TVSource::NotifyChannelScanStopped()
   return DispatchScanningStateChangedEvent(TVScanningState::Stopped, nullptr);
 }
 
 nsresult
 TVSource::NotifyEITBroadcasted(nsITVChannelData* aChannelData,
                                nsITVProgramData** aProgramDataList,
                                uint32_t aCount)
 {
-  // TODO Use channel data to initialize TVChannel in follow-up patches.
-  nsRefPtr<TVChannel> channel = new TVChannel(GetOwner());
+  nsRefPtr<TVChannel> channel = TVChannel::Create(GetOwner(), this, aChannelData);
   Sequence<OwningNonNull<TVProgram>> programs;
   for (uint32_t i = 0; i < aCount; i++) {
-    // TODO Use program data to initialize TVProgram in follow-up patches.
-    nsRefPtr<TVProgram> program = new TVProgram(GetOwner());
+    nsRefPtr<TVProgram> program =
+      new TVProgram(GetOwner(), channel, aProgramDataList[i]);
     *programs.AppendElement() = program;
   }
   return DispatchEITBroadcastedEvent(programs);
 }
 
 nsresult
 TVSource::DispatchCurrentChannelChangedEvent(TVChannel* aChannel)
 {