Bug 1057689 - Add xpcshell test checking correct notifications and app-offline state r=jduell
authorValentin Gosu <valentin.gosu@gmail.com>
Mon, 01 Sep 2014 17:29:28 +0300
changeset 290047 1686be775813bb687d3e015313f85957ee28af59
parent 290046 c143be9df73e9f540d8d406590e934afb8dea3de
child 290048 530267937f67c9ba12b7b442caff7a36aed1d9e9
push id30114
push usercbook@mozilla.com
push dateThu, 24 Mar 2016 15:15:54 +0000
treeherdermozilla-central@24c5fbde4488 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjduell
bugs1057689
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 1057689 - Add xpcshell test checking correct notifications and app-offline state r=jduell Changes NeckoParent to send the ipdl message if !UsingNeckoIPCSecurity() because xpcshell tests don't have TabParents. MozReview-Commit-ID: F50WXzg3TIA
netwerk/ipc/NeckoParent.cpp
netwerk/test/unit_ipc/child_app_offline_notifications.js
netwerk/test/unit_ipc/test_app_offline_notifications.js
netwerk/test/unit_ipc/xpcshell.ini
--- a/netwerk/ipc/NeckoParent.cpp
+++ b/netwerk/ipc/NeckoParent.cpp
@@ -1001,16 +1001,27 @@ NeckoParent::OfflineNotification(nsISupp
         }
         // Once we found the targetAppId, we don't need to continue
         break;
       }
     }
 
   }
 
+  // XPCShells don't have any TabParents
+  // Just send the ipdl message to the child process.
+  if (!UsingNeckoIPCSecurity()) {
+    bool offline = false;
+    gIOService->IsAppOffline(targetAppId, &offline);
+    if (!SendAppOfflineStatus(targetAppId, offline)) {
+      printf_stderr("NeckoParent: "
+                    "SendAppOfflineStatus failed for targetAppId: %u\n", targetAppId);
+    }
+  }
+
   return NS_OK;
 }
 
 bool
 NeckoParent::RecvRemoveSchedulingContext(const nsCString& scid)
 {
   nsCOMPtr<nsISchedulingContextService> scsvc =
     do_GetService("@mozilla.org/network/scheduling-context-service;1");
new file mode 100644
--- /dev/null
+++ b/netwerk/test/unit_ipc/child_app_offline_notifications.js
@@ -0,0 +1,43 @@
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+
+function is_app_offline(appId) {
+  let ioservice = Cc['@mozilla.org/network/io-service;1'].
+    getService(Ci.nsIIOService);
+  return ioservice.isAppOffline(appId);
+}
+
+var events_observed_no = 0;
+
+// Holds the last observed app-offline event
+var info = null;
+function observer(aSubject, aTopic, aData) {
+  events_observed_no++;
+  info = aSubject.QueryInterface(Ci.nsIAppOfflineInfo);
+  dump("ChildObserver - subject: {" + aSubject.appId + ", " + aSubject.mode + "} ");
+}
+
+// Add observer for the app-offline notification
+function run_test() {
+  Services.obs.addObserver(observer, "network:app-offline-status-changed", false);
+}
+
+// Chech that the app has the proper offline status
+function check_status(appId, status)
+{
+  do_check_eq(is_app_offline(appId), status == Ci.nsIAppOfflineInfo.OFFLINE);
+}
+
+// Check that the app has the proper offline status
+// and that the correct notification has been received
+function check_notification_and_status(appId, status) {
+  do_check_eq(info.appId, appId);
+  do_check_eq(info.mode, status);
+  do_check_eq(is_app_offline(appId), status == Ci.nsIAppOfflineInfo.OFFLINE);
+}
+
+// Remove the observer from the child process
+function finished() {
+  Services.obs.removeObserver(observer, "network:app-offline-status-changed");
+  do_check_eq(events_observed_no, 2);
+}
new file mode 100644
--- /dev/null
+++ b/netwerk/test/unit_ipc/test_app_offline_notifications.js
@@ -0,0 +1,102 @@
+// Checks that app-offline notifications are received in both the parent
+// and the child process, and that after receiving the notification
+// isAppOffline returns the correct value
+
+
+Cu.import("resource://testing-common/httpd.js");
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+
+var test_index = 0;
+var APP_ID = 42;
+var events_observed_no = 0;
+
+function set_app_offline(appId, offline) {
+  let ioservice = Cc['@mozilla.org/network/io-service;1'].
+    getService(Ci.nsIIOService);
+  ioservice.setAppOffline(appId, offline);
+}
+
+function is_app_offline(appId) {
+  let ioservice = Cc['@mozilla.org/network/io-service;1'].
+    getService(Ci.nsIIOService);
+  return ioservice.isAppOffline(appId);
+}
+
+// The expected offline status after running each function,
+// and the next function that should be run.
+
+//                       test0   test1   test2   test3   test4
+let expected_offline = [ false,  true,   true,  false,  false];
+let callbacks =        [ test1,  test2,  test3,  test4,  finished];
+
+function observer(aSubject, aTopic, aData) {
+  events_observed_no++;
+  let info = aSubject.QueryInterface(Ci.nsIAppOfflineInfo);
+  dump("ParentObserver - subject: {" + aSubject.appId + ", " + aSubject.mode + "} " +
+       "topic: " + aTopic + "\n");
+
+  // Check that the correct offline status is in place
+  do_check_eq(is_app_offline(APP_ID), expected_offline[test_index]);
+
+  // Execute the callback for the current test
+  do_execute_soon(callbacks[test_index]);
+}
+
+function run_test() {
+  Services.obs.addObserver(observer, "network:app-offline-status-changed", false);
+
+  test_index = 0;
+  do_check_eq(is_app_offline(APP_ID), expected_offline[test_index]) // The app should be online at first
+  run_test_in_child("child_app_offline_notifications.js", test0);
+}
+
+// Check that the app is online by default in the child
+function test0() {
+  dump("parent: RUNNING: test0\n");
+  test_index = 0;
+  sendCommand('check_status('+APP_ID+','+Ci.nsIAppOfflineInfo.ONLINE+');\n', test1);
+}
+
+// Set the app OFFLINE
+// Check that the notification is emmited in the parent process
+// The observer function will execute test2 which does the check in the child
+function test1() {
+  dump("parent: RUNNING: test1\n");
+  test_index = 1;
+  set_app_offline(APP_ID, Ci.nsIAppOfflineInfo.OFFLINE);
+}
+
+// Checks that child process sees the app OFFLINE
+function test2() {
+  dump("parent: RUNNING: test2\n");
+  test_index = 2;
+  sendCommand('check_notification_and_status('+APP_ID+','+Ci.nsIAppOfflineInfo.OFFLINE+');\n', test3);
+}
+
+// Set the app ONLINE
+// Chech that the notification is received in the parent
+// The observer function will execute test3 and do the check in the child
+function test3() {
+  dump("parent: RUNNING: test3\n");
+  test_index = 3;
+  set_app_offline(APP_ID, Ci.nsIAppOfflineInfo.ONLINE);
+}
+
+// Chech that the app is back online
+function test4() {
+  dump("parent: RUNNING: test4\n");
+  test_index = 4;
+  sendCommand('check_notification_and_status('+APP_ID+','+Ci.nsIAppOfflineInfo.ONLINE+');\n', function() {
+    // Send command to unregister observer on the child
+    sendCommand('finished();\n', finished);
+  });
+}
+
+// Remove observer and end test
+function finished() {
+  dump("parent: RUNNING: finished\n");
+  Services.obs.removeObserver(observer, "network:app-offline-status-changed");
+  do_check_eq(events_observed_no, 2);
+  do_test_finished();
+}
--- a/netwerk/test/unit_ipc/xpcshell.ini
+++ b/netwerk/test/unit_ipc/xpcshell.ini
@@ -1,13 +1,14 @@
 [DEFAULT]
 head = head_channels_clone.js head_cc.js
 tail =
 skip-if = toolkit == 'android' || toolkit == 'gonk'
 support-files = child_app_offline.js
+	child_app_offline_notifications.js
 
 [test_bug528292_wrap.js]
 [test_bug248970_cookie_wrap.js]
 [test_cacheflags_wrap.js]
 [test_cache_jar_wrap.js]
 [test_channel_close_wrap.js]
 [test_cookie_header_wrap.js]
 [test_cookiejars_wrap.js]
@@ -37,8 +38,9 @@ skip-if = true
 [test_simple_wrap.js]
 [test_synthesized_response_wrap.js]
 [test_xmlhttprequest_wrap.js]
 [test_XHR_redirects.js]
 [test_redirect_history_wrap.js]
 [test_reply_without_content_type_wrap.js]
 [test_app_offline_http.js]
 [test_getHost_wrap.js]
+[test_app_offline_notifications.js]