Bug 941459 - [e10s] pushPrefEnv, popPrefEnv in specialPowersAPI.js not e10s friendly. r=jmaher
authorMartijn Wargers <mwargers@mozilla.com>
Sun, 13 Jul 2014 17:00:26 +0200
changeset 216778 f701b67c24051bce8d22a14008310d36b953dd53
parent 216777 a283c1237d96d3e37b6735df0cce6ce4fc20ac88
child 216779 ea66bf9982ffd35f43b5517ce7fe9651577aa943
push id515
push userraliiev@mozilla.com
push dateMon, 06 Oct 2014 12:51:51 +0000
treeherdermozilla-release@267c7a481bef [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjmaher
bugs941459
milestone33.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 941459 - [e10s] pushPrefEnv, popPrefEnv in specialPowersAPI.js not e10s friendly. r=jmaher
layout/base/tests/mochitest.ini
testing/specialpowers/content/specialpowersAPI.js
--- a/layout/base/tests/mochitest.ini
+++ b/layout/base/tests/mochitest.ini
@@ -173,16 +173,17 @@ support-files =
 [test_bug607529.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') || e10s #Bug 931116, b2g desktop specific, initial triage
 support-files = file_bug607529.html
 [test_bug667512.html]
 [test_bug677878.html]
 [test_bug696020.html]
 [test_event_target_radius.html]
 [test_event_target_iframe_oop.html]
+skip-if = e10s # bug 1020135, nested oop iframes not supported
 support-files = bug921928_event_target_iframe_apps_oop.html
 [test_mozPaintCount.html]
 skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s # b2g(depends on plugins support) b2g-debug(depends on plugins support) b2g-desktop(depends on plugins support)
 [test_scroll_event_ordering.html]
 [test_bug583889.html]
 support-files = bug583889_inner1.html bug583889_inner2.html
 [test_bug582771.html]
 [test_bug968148.html]
--- a/testing/specialpowers/content/specialpowersAPI.js
+++ b/testing/specialpowers/content/specialpowersAPI.js
@@ -704,24 +704,41 @@ SpecialPowersAPI.prototype = {
     };
     var crashDumpFiles = this._sendSyncMessage("SPProcessCrashService", message)[0];
     crashDumpFiles.forEach(function(aFilename) {
       self._unexpectedCrashDumpFiles[aFilename] = true;
     });
     return crashDumpFiles;
   },
 
+  _setTimeout: function(callback) {
+    // for mochitest-browser
+    if (typeof window != 'undefined')
+      setTimeout(callback, 0);
+    // for mochitest-plain
+    else
+      content.window.setTimeout(callback, 0);
+  },
+
   _delayCallbackTwice: function(callback) {
-    function delayedCallback() {
-      function delayAgain() {
-	content.window.setTimeout(callback, 0);
-      }
-      content.window.setTimeout(delayAgain, 0);
-    }
-    return delayedCallback;
+     function delayedCallback() {
+       function delayAgain(aCallback) {
+         // Using this._setTimeout doesn't work here
+         // It causes failures in mochtests that use
+         // multiple pushPrefEnv calls
+         // For chrome/browser-chrome mochitests
+         if (typeof window != 'undefined')
+           setTimeout(aCallback, 0);
+         // For mochitest-plain
+         else
+           content.window.setTimeout(aCallback, 0);
+       }
+       delayAgain(delayAgain(callback));
+     }
+     return delayedCallback;
   },
 
   /* apply permissions to the system and when the test case is finished (SimpleTest.finish())
      we will revert the permission back to the original.
 
      inPermissions is an array of objects where each object has a type, action, context, ex:
      [{'type': 'SystemXHR', 'allow': 1, 'context': document}, 
       {'type': 'SystemXHR', 'allow': Ci.nsIPermissionManager.PROMPT_ACTION, 'context': document}]
@@ -794,53 +811,54 @@ SpecialPowersAPI.prototype = {
       // that the callback checks for. The second delay is because pref
       // observers often defer making their changes by posting an event to the
       // event loop.
       this._permissionsUndoStack.push(cleanupPermissions);
       this._pendingPermissions.push([pendingPermissions,
 				     this._delayCallbackTwice(callback)]);
       this._applyPermissions();
     } else {
-      content.window.setTimeout(callback, 0);
+      this._setTimeout(callback);
     }
   },
 
   popPermissions: function(callback) {
     if (this._permissionsUndoStack.length > 0) {
       // See pushPermissions comment regarding delay.
       let cb = callback ? this._delayCallbackTwice(callback) : null;
       /* Each pop from the stack will yield an object {op/type/permission/value/url/appid/isInBrowserElement} or null */
       this._pendingPermissions.push([this._permissionsUndoStack.pop(), cb]);
       this._applyPermissions();
     } else {
-      content.window.setTimeout(callback, 0);
+       this._setTimeout(callback);
     }
   },
 
   flushPermissions: function(callback) {
     while (this._permissionsUndoStack.length > 1)
       this.popPermissions(null);
 
     this.popPermissions(callback);
   },
 
 
   _permissionObserver: {
+    _self: null,
     _lastPermission: {},
     _callBack: null,
     _nextCallback: null,
 
     observe: function (aSubject, aTopic, aData)
     {
       if (aTopic == "perm-changed") {
         var permission = aSubject.QueryInterface(Ci.nsIPermission);
         if (permission.type == this._lastPermission.type) {
           Services.obs.removeObserver(this, "perm-changed");
-          content.window.setTimeout(this._callback, 0);
-          content.window.setTimeout(this._nextCallback, 0);
+          this._self._setTimeout(this._callback);
+          this._self._setTimeout(this._nextCallback);
         }
       }
     }
   },
 
   /*
     Iterate through one atomic set of permissions actions and perform allow/deny as appropriate.
     All actions performed must modify the relevant permission.
@@ -853,16 +871,17 @@ SpecialPowersAPI.prototype = {
     /* Set lock and get prefs from the _pendingPrefs queue */
     this._applyingPermissions = true;
     var transaction = this._pendingPermissions.shift();
     var pendingActions = transaction[0];
     var callback = transaction[1];
     var lastPermission = pendingActions[pendingActions.length-1];
 
     var self = this;
+    this._permissionObserver._self = self;
     this._permissionObserver._lastPermission = lastPermission;
     this._permissionObserver._callback = callback;
     this._permissionObserver._nextCallback = function () {
         self._applyingPermissions = false;
         // Now apply any permissions that may have been queued while we were applying
         self._applyPermissions();
     }
 
@@ -979,29 +998,29 @@ SpecialPowersAPI.prototype = {
       // that the callback checks for. The second delay is because pref
       // observers often defer making their changes by posting an event to the
       // event loop.
       this._prefEnvUndoStack.push(cleanupActions);
       this._pendingPrefs.push([pendingActions,
 			       this._delayCallbackTwice(callback)]);
       this._applyPrefs();
     } else {
-      content.window.setTimeout(callback, 0);
+      this._setTimeout(callback);
     }
   },
 
   popPrefEnv: function(callback) {
     if (this._prefEnvUndoStack.length > 0) {
       // See pushPrefEnv comment regarding delay.
       let cb = callback ? this._delayCallbackTwice(callback) : null;
       /* Each pop will have a valid block of preferences */
       this._pendingPrefs.push([this._prefEnvUndoStack.pop(), cb]);
       this._applyPrefs();
     } else {
-      content.window.setTimeout(callback, 0);
+      this._setTimeout(callback);
     }
   },
 
   flushPrefEnv: function(callback) {
     while (this._prefEnvUndoStack.length > 1)
       this.popPrefEnv(null);
 
     this.popPrefEnv(callback);
@@ -1024,22 +1043,22 @@ SpecialPowersAPI.prototype = {
 
     var lastPref = pendingActions[pendingActions.length-1];
 
     var pb = Services.prefs;
     var self = this;
     pb.addObserver(lastPref.name, function prefObs(subject, topic, data) {
       pb.removeObserver(lastPref.name, prefObs);
 
-      content.window.setTimeout(callback, 0);
-      content.window.setTimeout(function () {
+      self._setTimeout(callback);
+      self._setTimeout(function () {
         self._applyingPrefs = false;
         // Now apply any prefs that may have been queued while we were applying
         self._applyPrefs();
-      }, 0);
+      });
     }, false);
 
     for (var idx in pendingActions) {
       var pref = pendingActions[idx];
       if (pref.action == 'set') {
         this._setPref(pref.name, pref.type, pref.value, pref.Iid);
       } else if (pref.action == 'clear') {
         this.clearUserPref(pref.name);