Bug 1263799 - Support IPC for TV service between B2G and content processes. Part 3 - Enhance TV mochitests. r=schien draft
authorSean Lin <selin@mozilla.com>
Fri, 18 Dec 2015 16:33:16 +0800
changeset 357232 35d398296d2bfa96a41f938c8b4a9386b406b758
parent 357231 f3d5186c0c26e61e80d6485262c45564f8ac45cf
child 519604 100b6117f3c46ed25f88974f026b824979d2d68e
push id16736
push userbmo:kechen@mozilla.com
push dateThu, 28 Apr 2016 09:03:26 +0000
reviewersschien
bugs1263799
milestone49.0a1
Bug 1263799 - Support IPC for TV service between B2G and content processes. Part 3 - Enhance TV mochitests. r=schien MozReview-Commit-ID: IsCVCxtSzEn
dom/tv/TVSimulatorService.js
dom/tv/nsITVSimulatorService.idl
dom/tv/test/mochitest/head.js
dom/tv/test/mochitest/mochitest.ini
dom/tv/test/mochitest/test_tv_eit_broadcasted.html
dom/tv/test/mochitest/test_tv_scan_channels_completed.html
dom/tv/test/mochitest/test_tv_scan_channels_error.html
dom/tv/test/mochitest/tv_chrome_script.js
--- a/dom/tv/TVSimulatorService.js
+++ b/dom/tv/TVSimulatorService.js
@@ -39,55 +39,48 @@ function TVSimulatorService() {
   //     "sourceType1": [ /* source listeners */ ],
   //     "sourceType2": [ /* source listeners */ ],
   //     ...
   //   },
   //   ...
   // }
   this._sourceListeners = {};
   this._internalTuners = null;
-  this._scanCompleteTimer = null;
-  this._scanningWrapTunerData = null;
-  this._init();
+  try {
+    this.initData();
+  } catch (e) {
+    debug("Error: " + e + ", Cannot init the data.");
+  }
 }
 
 TVSimulatorService.prototype = {
   classID: Components.ID("{94b065ad-d45a-436a-b394-6dabc3cf110f}"),
   QueryInterface: XPCOMUtils.generateQI([Ci.nsITVSimulatorService,
-                                         Ci.nsITVService,
-                                         Ci.nsITimerCallback]),
-
-  _init: function TVSimInit() {
-    if (this._internalTuners) {
-      return;
-    }
+                                         Ci.nsITVService]),
 
-    // I try to load the testing mock data if related preference are already set.
-    // Otherwise, use to the simulation data from prefences.
-    // See /dom/tv/test/mochitest/head.js for more details.
-    let settingStr = "";
-    try {
-      settingStr = Services.prefs.getCharPref("dom.testing.tv_mock_data");
-    } catch(e) {
+  initData: function(aMockedData) {
+    // Use the passed-in mocked data. If it doesn't exist, then try to load the
+    // simulation data.
+    let settingStr = aMockedData;
+    if (!settingStr) {
       try {
         settingStr = this._getDummyData();
       } catch(e) {
         debug("TV Simulator service failed to load simulation data: " + e);
-        return;
+        throw Cr.NS_ERROR_FAILURE;
       }
     }
 
     let settingsObj;
     try {
       /*
        *
        * Setting JSON file format:
        *
-       * Note: This setting JSON is not allow empty array.
-       *       If set the empty array, _init() will fail.
+       * Note: Empty arrays are not allowed in the format.
        *       e.g.
        *        - "tuners": []
        *        - "channels":[]
        * Format:
        *   {
        *    "tuners": [{
        *      "id":                     "The ID of the tuner",
        *      "supportedType":          ["The array of source type to be used."],
@@ -116,23 +109,23 @@ TVSimulatorService.prototype = {
        *         },]
        *       },]
        *     },]
        *   }
        */
       settingsObj = JSON.parse(settingStr);
     } catch(e) {
       debug("File load error: " + e);
-      return;
+      throw Cr.NS_ERROR_FAILURE;
     }
 
     // validation
     if (!this._validateSettings(settingsObj)) {
       debug("Failed to validate settings.");
-      return;
+      throw Cr.NS_ERROR_INVALID_ARG;
     }
 
     // Key is as follow
     // {'tunerId':tunerId, 'sourceType':sourceType}
     this._internalTuners = new Map();
 
     // TVTunerData
     for (let tunerData of settingsObj.tuners) {
@@ -294,80 +287,32 @@ TVSimulatorService.prototype = {
   },
 
   startScanningChannels: function(aTunerId, aSourceType, aCallback) {
     if (!aCallback) {
       debug("aCallback is null\n");
       throw Cr.NS_ERROR_INVALID_ARG;
     }
 
-    if (this._scanningWrapTunerData) {
-      aCallback.notifyError(Cr.NS_ERROR_DOM_INVALID_STATE_ERR);
-      return;
-    }
-
     let wrapTunerData = this._getWrapTunerData(aTunerId, aSourceType);
     if (!wrapTunerData || !wrapTunerData.channels) {
       aCallback.notifyError(Ci.nsITVServiceCallback.TV_ERROR_FAILURE);
       return;
     }
 
-    this._scanningWrapTunerData = wrapTunerData;
-
     aCallback.notifySuccess(null);
-
-    for (let [key, wrapChannelData] of wrapTunerData.channels) {
-      for (let listener of this._getSourceListeners(aTunerId, aSourceType)) {
-        listener.notifyChannelScanned(aTunerId, aSourceType, wrapChannelData.channel);
-      }
-    }
-
-    this._scanCompleteTimer = Cc["@mozilla.org/timer;1"]
-                                .createInstance(Ci.nsITimer);
-    this._scanCompleteTimer.initWithCallback(this, 10,
-                                             Ci.nsITimer.TYPE_ONE_SHOT);
-  },
-
-  notify: function(aTimer) {
-    if (!this._scanningWrapTunerData) {
-      return;
-    }
-
-    this._scanCompleteTimer = null;
-
-    let tunerId = this._scanningWrapTunerData.tuner.id;
-    let sourceType = this._scanningWrapTunerData.sourceType;
-    let notifyResult = Cr.NS_OK;
-    for (let listener of this._getSourceListeners(tunerId, sourceType)) {
-      notifyResult = listener.notifyChannelScanComplete(tunerId, sourceType);
-    }
-    this._scanningWrapTunerData = null;
-    return notifyResult;
   },
 
   stopScanningChannels: function(aTunerId, aSourceType, aCallback) {
+
     if (!aCallback) {
       debug("aCallback is null\n");
       throw Cr.NS_ERROR_INVALID_ARG;
     }
 
-    if (!this._scanningWrapTunerData ||
-        aTunerId != this._scanningWrapTunerData.tuner.id ||
-        aSourceType != this._scanningWrapTunerData.sourceType) {
-      aCallback.notifyError(Cr.NS_ERROR_DOM_INVALID_STATE_ERR);
-      return;
-    }
-
-    this._scanningWrapTunerData = null;
-
-    if (this._scanCompleteTimer) {
-      this._scanCompleteTimer.cancel();
-      this._scanCompleteTimer = null;
-    }
-
     for (let listener of this._getSourceListeners(aTunerId, aSourceType)) {
       listener.notifyChannelScanStopped(aTunerId, aSourceType);
     }
 
     aCallback.notifySuccess(null);
   },
 
   clearScannedChannelsCache: function(aTunerId, aSourceType, aCallback) {
@@ -459,16 +404,61 @@ TVSimulatorService.prototype = {
     }
 
     let videoFile = new File(this._getFilePath(wrapChannelData.videoFilePath));
     let videoBlobURL = aWin.URL.createObjectURL(videoFile);
 
     return videoBlobURL;
   },
 
+  simulateChannelScanned: function(aTunerId, aSourceType) {
+    let wrapTunerData = this._getWrapTunerData(aTunerId, aSourceType);
+    if (!wrapTunerData || !wrapTunerData.channels) {
+      throw Cr.NS_ERROR_INVALID_ARG;
+    }
+
+    let listeners = this._getSourceListeners(aTunerId, aSourceType);
+    for (let [key, wrapChannelData] of wrapTunerData.channels) {
+      for (let listener of listeners) {
+        listener.notifyChannelScanned(aTunerId, aSourceType, wrapChannelData.channel);
+      }
+    }
+  },
+
+  simulateChannelScanComplete: function(aTunerId, aSourceType) {
+    for (let listener of this._getSourceListeners(aTunerId, aSourceType)) {
+      listener.notifyChannelScanComplete(aTunerId, aSourceType);
+    }
+  },
+
+  simulateChannelScanError: function(aTunerId, aSourceType) {
+    for (let listener of this._getSourceListeners(aTunerId, aSourceType)) {
+      listener.notifyChannelScanStopped(aTunerId, aSourceType);
+    }
+  },
+
+  simulateEITBroadcasted: function(aTunerId, aSourceType, aChannelNumber) {
+    let wrapTunerData = this._getWrapTunerData(aTunerId, aSourceType);
+    if (!wrapTunerData || !wrapTunerData.channels) {
+      throw Cr.NS_ERROR_INVALID_ARG;
+    }
+
+    let wrapChannelData = wrapTunerData.channels.get(aChannelNumber);
+    if (!wrapChannelData || !wrapChannelData.programs) {
+      throw Cr.NS_ERROR_INVALID_ARG;
+    }
+
+    for (let listener of this._getSourceListeners(aTunerId, aSourceType)) {
+      listener.notifyEITBroadcasted(aTunerId, aSourceType,
+                                    wrapChannelData.channel,
+                                    wrapChannelData.programs,
+                                    wrapChannelData.programs.length);
+    }
+  },
+
   _getDummyData : function() {
     // Load the setting file from local JSON file.
     // Synchrhronous File Reading.
     let file = Cc["@mozilla.org/file/local;1"]
                  .createInstance(Ci.nsILocalFile);
 
     let fstream = Cc["@mozilla.org/network/file-input-stream;1"]
                     .createInstance(Ci.nsIFileInputStream);
--- a/dom/tv/nsITVSimulatorService.idl
+++ b/dom/tv/nsITVSimulatorService.idl
@@ -11,22 +11,67 @@ interface mozIDOMWindow;
 #define TV_SIMULATOR_SERVICE_CONTRACTID\
   "@mozilla.org/tv/simulatorservice;1"
 %}
 
 [scriptable, uuid(3f670994-5915-415a-b906-7ead54bb3be1)]
 interface nsITVSimulatorService : nsITVService
 {
   /*
+   * Init the simulation data.
+   *
+   * @param mockedData    The preloaded mocked data in stringified JSON format.
+   */
+  void initData([optional] in DOMString mockedData);
+
+  /*
    * Get the URL of simulated video blob.
    *
    * @param tunerId       The ID of the tuner.
    * @param sourceType    The source type to be used.
    * @param channelNumber The LCN (Logical Channel Number) of the channel.
    * @param window        The window object of content.
    * @return blobUrl      The URL of created blob from local video file.
    */
   void getSimulatorVideoBlobURL(in DOMString tunerId,
                                 in DOMString sourceType,
                                 in DOMString channelNumber,
                                 in mozIDOMWindow window,
                                 [retval] out DOMString blobUrl);
+
+  /*
+   * Simulate some channels are scanned.
+   *
+   * @param tunerId       The ID of the tuner.
+   * @param sourceType    The source type to be used.
+   */
+  void simulateChannelScanned(in DOMString tunerId,
+                              in DOMString sourceType);
+
+  /*
+   * Simulate channel scanning complete.
+   *
+   * @param tunerId       The ID of the tuner.
+   * @param sourceType    The source type to be used.
+   */
+  void simulateChannelScanComplete(in DOMString tunerId,
+                                   in DOMString sourceType);
+
+  /*
+   * Simulate error occurs during channel scanning.
+   *
+   * @param tunerId       The ID of the tuner.
+   * @param sourceType    The source type to be used.
+   */
+  void simulateChannelScanError(in DOMString tunerId,
+                                in DOMString sourceType);
+
+  /*
+   * Simulate EIT broadcasted.
+   *
+   * @param tunerId       The ID of the tuner.
+   * @param sourceType    The source type to be used.
+   * @param channelNumber The LCN (Logical Channel Number) of the channel.
+   */
+  void simulateEITBroadcasted(in DOMString tunerId,
+                              in DOMString sourceType,
+                              in DOMString channelNumber);
 };
--- a/dom/tv/test/mochitest/head.js
+++ b/dom/tv/test/mochitest/head.js
@@ -1,40 +1,45 @@
 "use strict";
 
-function setupPrefsAndPermissions(callback) {
+function setupPrefsAndPermissions(aCallback) {
   setupPrefs(function() {
       SpecialPowers.pushPermissions([
         {"type":"tv", "allow":1, "context":document}
-      ], callback);
+      ], aCallback);
+  });
+}
+
+function setupPrefs(aCallback) {
+  SpecialPowers.pushPrefEnv({"set": [
+                              ["dom.tv.enabled", true],
+                              ["dom.ignore_webidl_scope_checks", true],
+                            ]}, function() {
+    aCallback();
   });
 }
 
-function setupPrefs(callback) {
+function removePrefsAndPermissions(aCallback) {
+  SpecialPowers.popPrefEnv(function() {
+    SpecialPowers.popPermissions(aCallback);
+  });
+}
+
+function prepareTest(aCallback) {
+  removePrefsAndPermissions(function() {
+    setupPrefsAndPermissions(function() {
+      initMockedData(aCallback);
+    });
+  });
+}
+
+function initMockedData(aCallback) {
   let xhr = new XMLHttpRequest;
-  let data;
-
   xhr.open("GET", "./mock_data.json", false);
   xhr.send(null);
   if (xhr.status == 200) {
-    data = xhr.responseText;
-  }
+    var gScript = SpecialPowers.loadChromeScript(SimpleTest.getTestFileURL('tv_chrome_script.js'));
 
-  SpecialPowers.pushPrefEnv({"set": [
-                              ["dom.tv.enabled", true],
-                              ["dom.ignore_webidl_scope_checks", true],
-                              ["dom.testing.tv_mock_data", data]
-                            ]}, function() {
-    callback();
-  });
-}
+    gScript.addMessageListener('init-mocked-data-complete', aCallback);
 
-function removePrefsAndPermissions(callback) {
-  SpecialPowers.popPrefEnv(function() {
-    SpecialPowers.popPermissions(callback);
-  });
+    gScript.sendAsyncMessage('init-mocked-data', xhr.responseText);
+  }
 }
-
-function prepareTest(callback) {
-  removePrefsAndPermissions(function() {
-    setupPrefsAndPermissions(callback);
-  });
-}
--- a/dom/tv/test/mochitest/mochitest.ini
+++ b/dom/tv/test/mochitest/mochitest.ini
@@ -1,20 +1,27 @@
 [DEFAULT]
+skip-if = toolkit == "gonk"
 support-files =
   head.js
   mock_data.json
+  tv_chrome_script.js
 
 [test_tv_non_permitted_app.html]
 [test_tv_permitted_app.html]
 [test_tv_get_tuners.html]
 [test_tv_get_sources.html]
 [test_tv_get_channels.html]
 [test_tv_get_channels_during_scanning.html]
 [test_tv_get_programs.html]
 [test_tv_get_current_program.html]
 [test_tv_set_current_source.html]
 [test_tv_set_invalid_current_source.html]
 [test_tv_set_current_channel.html]
 [test_tv_set_current_channel_during_scanning.html]
 [test_tv_set_invalid_current_channel.html]
 [test_tv_scan_channels_stopped.html]
+skip-if = e10s || buildapp == 'b2g'
 [test_tv_scan_channels_completed.html]
+skip-if = e10s || buildapp == 'b2g'
+[test_tv_scan_channels_error.html]
+skip-if = e10s || buildapp == 'b2g'
+[test_tv_eit_broadcasted.html]
new file mode 100644
--- /dev/null
+++ b/dom/tv/test/mochitest/test_tv_eit_broadcasted.html
@@ -0,0 +1,77 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test TVEITBroadcastedEvent for TV API</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none"></div>
+<pre id="test">
+<script type="application/javascript" src="./head.js"></script>
+<script type="application/javascript">
+
+function runTest() {
+  ok('tv' in navigator, "navigator.tv should exist.");
+  var gScript = SpecialPowers.loadChromeScript(SimpleTest.getTestFileURL('tv_chrome_script.js'));
+
+  navigator.tv.getTuners().then(
+    function(aTuners) {
+      ok(aTuners.length > 0, "Got at least 1 tuner.");
+
+      aTuners[0].getSources().then(
+        function(aSources) {
+          ok(aSources.length > 0, "Got at least 1 source.");
+          var source = aSources[0];
+
+          source.oneitbroadcasted = function(aEvent) {
+            info("Received EIT broadcasted event.");
+
+            var programs = aEvent.programs;
+            for (var i = 0; i < programs.length; i++) {
+              ok(programs[i], "Program " + i + " should be set.")
+            }
+
+            gScript.destroy();
+            SimpleTest.finish();
+          };
+
+          source.getChannels().then(
+            function(aChannels) {
+              ok(aChannels.length > 0, "Got at least 1 channel.");
+
+              gScript.sendAsyncMessage('trigger-eit-broadcasted',
+                                       { tunerId: aTuners[0].id,
+                                         sourceType: source.type,
+                                         channelNumber: aChannels[0].number });
+            },
+            function(aError) {
+              ok(false, "Error occurred when getting channels: " + aError);
+              gScript.destroy();
+              SimpleTest.finish();
+            }
+          );
+        },
+        function(aError) {
+          ok(false, "Error occurred when getting sources: " + aError);
+          gScript.destroy();
+          SimpleTest.finish();
+        }
+      );
+    },
+    function(aError) {
+      ok(false, "Error occurred when getting tuners: " + aError);
+      gScript.destroy();
+      SimpleTest.finish();
+    }
+  );
+}
+
+SimpleTest.waitForExplicitFinish();
+prepareTest(runTest);
+
+</script>
+</pre>
+</body>
+</html>
--- a/dom/tv/test/mochitest/test_tv_scan_channels_completed.html
+++ b/dom/tv/test/mochitest/test_tv_scan_channels_completed.html
@@ -11,63 +11,68 @@
 <pre id="test">
 <script type="application/javascript" src="./head.js"></script>
 <script type="application/javascript">
 
 function runTest() {
   ok('tv' in navigator, "navigator.tv should exist.");
 
   var isScannedEventFired = false;
-  
+  var gScript = SpecialPowers.loadChromeScript(SimpleTest.getTestFileURL('tv_chrome_script.js'));
+
   navigator.tv.getTuners().then(
     function(aTuners) {
       ok(aTuners.length > 0, "Got at least 1 tuner.");
 
       aTuners[0].getSources().then(
         function(aSources) {
           ok(aSources.length > 0, "Got at least 1 source.");
           var source = aSources[0];
 
-          source.oneitbroadcasted = function(aEvent) {
-            info("Received EIT broadcasted event.");
-
-            var programs = aEvent.programs;
-            for (var i = 0; i < programs.length; i++) {
-              ok(programs[i], "Program " + i + " should be set.")
-            }
-          };
-
           source.onscanningstatechanged = function(aEvent) {
             if (aEvent.state === 'scanned') {
-              isScannedEventFired = true;
+              if (!isScannedEventFired) {
+                isScannedEventFired = true;
+                gScript.sendAsyncMessage('trigger-channel-scan-complete',
+                                         { tunerId: aTuners[0].id,
+                                           sourceType: source.type });
+              }
               info("Received channel scanned event.");
               ok(aEvent.channel, "Scanned channel should be set.");
             } else if (aEvent.state === 'completed') {
               ok(isScannedEventFired, "Received channel scanning completed event after channel scanned event.");
+              gScript.destroy();
               SimpleTest.finish();
             }
           };
 
           // TODO Bug 1088818 - Modify the behavior of channel scanning.
           source.startScanning({}).then(
-            function() {},
+            function() {
+              gScript.sendAsyncMessage('trigger-channel-scanned',
+                                       { tunerId: aTuners[0].id,
+                                         sourceType: source.type });
+            },
             function(aError) {
               ok(false, "Error occurred when starting scanning: " + aError);
+              gScript.destroy();
               SimpleTest.finish();
             }
           );
         },
         function(aError) {
           ok(false, "Error occurred when getting sources: " + aError);
+          gScript.destroy();
           SimpleTest.finish();
         }
       );
     },
     function(aError) {
       ok(false, "Error occurred when getting tuners: " + aError);
+      gScript.destroy();
       SimpleTest.finish();
     }
   );
 }
 
 SimpleTest.expectAssertions(0, 2);
 SimpleTest.waitForExplicitFinish();
 prepareTest(runTest);
new file mode 100644
--- /dev/null
+++ b/dom/tv/test/mochitest/test_tv_scan_channels_error.html
@@ -0,0 +1,72 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test channel scanning error for TV API</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none"></div>
+<pre id="test">
+<script type="application/javascript" src="./head.js"></script>
+<script type="application/javascript">
+
+function runTest() {
+  ok('tv' in navigator, "navigator.tv should exist.");
+
+  var gScript = SpecialPowers.loadChromeScript(SimpleTest.getTestFileURL('tv_chrome_script.js'));
+
+  navigator.tv.getTuners().then(
+    function(aTuners) {
+      ok(aTuners.length > 0, "Got at least 1 tuner.");
+
+      aTuners[0].getSources().then(
+        function(aSources) {
+          ok(aSources.length > 0, "Got at least 1 source.");
+          var source = aSources[0];
+
+          source.onscanningstatechanged = function(aEvent) {
+            if (aEvent.state === 'stopped') {
+              ok(true, "Received channel scanning stopped event.");
+              gScript.destroy();
+              SimpleTest.finish();
+            }
+          };
+
+          // TODO Bug 1088818 - Modify the behavior of channel scanning.
+          source.startScanning().then(
+            function() {
+              gScript.sendAsyncMessage('trigger-channel-scan-error',
+                                       { tunerId: aTuners[0].id,
+                                         sourceType: source.type });
+            },
+            function(aError) {
+              ok(false, "Error occurred when starting scanning: " + aError);
+              gScript.destroy();
+              SimpleTest.finish();
+            }
+          );
+        },
+        function(aError) {
+          ok(false, "Error occurred when getting sources: " + aError);
+          gScript.destroy();
+          SimpleTest.finish();
+        }
+      );
+    },
+    function(aError) {
+      ok(false, "Error occurred when getting tuners: " + aError);
+      gScript.destroy();
+      SimpleTest.finish();
+    }
+  );
+}
+
+SimpleTest.waitForExplicitFinish();
+prepareTest(runTest);
+
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/tv/test/mochitest/tv_chrome_script.js
@@ -0,0 +1,44 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+'use strict';
+
+const { classes: Cc, interfaces: Ci, manager: Cm, utils: Cu, results: Cr } = Components;
+
+Cu.import('resource://gre/modules/XPCOMUtils.jsm');
+
+addMessageListener('init-mocked-data', function(aData) {
+  var service = Cc["@mozilla.org/tv/tvservice;1"].getService(Ci.nsITVService);
+  try {
+    service.QueryInterface(Ci.nsITVSimulatorService).initData(aData);
+    sendAsyncMessage('init-mocked-data-complete');
+  } catch (e) {}
+});
+
+addMessageListener('trigger-channel-scanned', function(aData) {
+  var service = Cc["@mozilla.org/tv/tvservice;1"].getService(Ci.nsITVService);
+  try {
+    service.QueryInterface(Ci.nsITVSimulatorService).simulateChannelScanned(aData.tunerId, aData.sourceType);
+  } catch (e) {}
+});
+
+addMessageListener('trigger-channel-scan-complete', function(aData) {
+  var service = Cc["@mozilla.org/tv/tvservice;1"].getService(Ci.nsITVService);
+  try {
+    service.QueryInterface(Ci.nsITVSimulatorService).simulateChannelScanComplete(aData.tunerId, aData.sourceType);
+  } catch (e) {}
+});
+
+addMessageListener('trigger-channel-scan-error', function(aData) {
+  var service = Cc["@mozilla.org/tv/tvservice;1"].getService(Ci.nsITVService);
+  try {
+    service.QueryInterface(Ci.nsITVSimulatorService).simulateChannelScanError(aData.tunerId, aData.sourceType);
+  } catch (e) {}
+});
+
+addMessageListener('trigger-eit-broadcasted', function(aData) {
+  var service = Cc["@mozilla.org/tv/tvservice;1"].getService(Ci.nsITVService);
+  try {
+    service.QueryInterface(Ci.nsITVSimulatorService).simulateEITBroadcasted(aData.tunerId, aData.sourceType, aData.channelNumber);
+  } catch (e) {}
+});