Merge m-i to m-c.
authorKyle Huey <khuey@kylehuey.com>
Mon, 22 Aug 2011 07:39:22 -0400
changeset 75640 b7c8af20e4009560b86cb6b84d7025b62ceaaa25
parent 75629 f41df039db034120c9cf999f362cadff885b76b1 (current diff)
parent 75639 ea0fb4946b29fd4aaa4eec45934a604cbe248a7c (diff)
child 75642 3d32e28b81a0ad2abd4271244921ee8ee1153390
child 75648 7b7109b4bfb722b984e7e0869612000dfdc8bda7
child 75730 2a9fb4f365011f1d6e3949df5ecda28ddc8bcee7
child 75802 06defc1b425097d4a95bb28f0ee254d38b186c36
child 75879 f8fbf62f31e8e5b1c63f6c3d19d4bc0dc9f0ec7f
push id3
push userfelipc@gmail.com
push dateFri, 30 Sep 2011 20:09:13 +0000
milestone9.0a1
Merge m-i to m-c.
--- a/browser/components/feeds/src/FeedWriter.js
+++ b/browser/components/feeds/src/FeedWriter.js
@@ -251,17 +251,18 @@ FeedWriter.prototype = {
 
   /**
    * Use this sandbox to run any dom manipulation code on nodes which
    * are already inserted into the content document.
    */
   __contentSandbox: null,
   get _contentSandbox() {
     if (!this.__contentSandbox)
-      this.__contentSandbox = new Cu.Sandbox(this._window);
+      this.__contentSandbox = new Cu.Sandbox(this._window, 
+                                             {sandboxName: 'FeedWriter'});
 
     return this.__contentSandbox;
   },
 
   /**
    * Calls doCommand for a given XUL element within the context of the
    * content document.
    *
--- a/browser/components/sessionstore/content/aboutSessionRestore.js
+++ b/browser/components/sessionstore/content/aboutSessionRestore.js
@@ -54,17 +54,17 @@ window.onload = function() {
 
   // remove unneeded braces (added for compatibility with Firefox 2.0 and 3.0)
   if (sessionData.value.charAt(0) == '(')
     sessionData.value = sessionData.value.slice(1, -1);
   try {
     gStateObject = JSON.parse(sessionData.value);
   }
   catch (exJSON) {
-    var s = new Cu.Sandbox("about:blank");
+    var s = new Cu.Sandbox("about:blank", {sandboxName: 'aboutSessionRestore'});
     gStateObject = Cu.evalInSandbox("(" + sessionData.value + ")", s);
     // If we couldn't parse the string with JSON.parse originally, make sure
     // that the value in the textbox will be parsable.
     sessionData.value = JSON.stringify(gStateObject);
   }
 
   // make sure the data is tracked to be restored in case of a subsequent crash
   var event = document.createEvent("UIEvents");
--- a/browser/components/sessionstore/src/nsSessionStartup.js
+++ b/browser/components/sessionstore/src/nsSessionStartup.js
@@ -130,17 +130,17 @@ SessionStartup.prototype = {
     try {
       // remove unneeded braces (added for compatibility with Firefox 2.0 and 3.0)
       if (iniString.charAt(0) == '(')
         iniString = iniString.slice(1, -1);
       try {
         this._initialState = JSON.parse(iniString);
       }
       catch (exJSON) {
-        var s = new Cu.Sandbox("about:blank");
+        var s = new Cu.Sandbox("about:blank", {sandboxName: 'nsSessionStartup'});
         this._initialState = Cu.evalInSandbox("(" + iniString + ")", s);
       }
 
       // If this is a normal restore then throw away any previous session
       if (!doResumeSessionOnce)
         delete this._initialState.lastSessionState;
     }
     catch (ex) { debug("The session file is invalid: " + ex); }
--- a/browser/devtools/scratchpad/scratchpad.js
+++ b/browser/devtools/scratchpad/scratchpad.js
@@ -173,17 +173,18 @@ var Scratchpad = {
     }
 
     if (!this._contentSandbox ||
         this.browserWindow != this._previousBrowserWindow ||
         this._previousBrowser != this.gBrowser.selectedBrowser ||
         this._previousLocation != this.gBrowser.contentWindow.location.href) {
       let contentWindow = this.gBrowser.selectedBrowser.contentWindow;
       this._contentSandbox = new Cu.Sandbox(contentWindow,
-        { sandboxPrototype: contentWindow, wantXrays: false });
+        { sandboxPrototype: contentWindow, wantXrays: false, 
+          sandboxName: 'scratchpad-content'});
 
       this._previousBrowserWindow = this.browserWindow;
       this._previousBrowser = this.gBrowser.selectedBrowser;
       this._previousLocation = contentWindow.location.href;
     }
 
     return this._contentSandbox;
   },
@@ -206,17 +207,18 @@ var Scratchpad = {
       Cu.reportError(this.strings.
                      GetStringFromName("browserWindow.unavailable"));
       return;
     }
 
     if (!this._chromeSandbox ||
         this.browserWindow != this._previousBrowserWindow) {
       this._chromeSandbox = new Cu.Sandbox(this.browserWindow,
-        { sandboxPrototype: this.browserWindow, wantXrays: false });
+        { sandboxPrototype: this.browserWindow, wantXrays: false, 
+          sandboxName: 'scratchpad-chrome'});
 
       this._previousBrowserWindow = this.browserWindow;
     }
 
     return this._chromeSandbox;
   },
 
   /**
--- a/build/mobile/devicemanagerADB.py
+++ b/build/mobile/devicemanagerADB.py
@@ -1,38 +1,47 @@
 import subprocess
 from devicemanager import DeviceManager, DMError
 import re
 import os
 
 class DeviceManagerADB(DeviceManager):
 
-  def __init__(self, host = None, port = 20701, retrylimit = 5, packageName = "org.mozilla.fennec_unofficial"):
+  def __init__(self, host = None, port = 20701, retrylimit = 5, packageName = None):
     self.host = host
     self.port = port
     self.retrylimit = retrylimit
     self.retries = 0
     self._sock = None
+    if packageName == None:
+      if os.getenv('USER'):
+        packageName = 'org.mozilla.fennec_' + os.getenv('USER')
+      else:
+        packageName = 'org.mozilla.fennec_'
     self.Init(packageName)
 
   def Init(self, packageName):
     # Initialization code that may fail: Catch exceptions here to allow
     # successful initialization even if, for example, adb is not installed.
     try:
       root = self.getDeviceRoot()
       self.verifyPackage(packageName)
       self.tmpDir = root + "/tmp"
       if (not self.dirExists(self.tmpDir)):
         self.mkDir(self.tmpDir)
     except:
       self.packageName = None
       self.tmpDir = None
     try:
       # a test to see if we have root privs
-      self.checkCmd(["shell", "ls", "/sbin"])
+      files = self.listFiles("/data/data")
+      if (len(files) == 1):
+        if (files[0].find("Permission denied") != -1):
+          print "NOT running as root"
+          raise Exception("not running as root")
     except:
       try:
         self.checkCmd(["root"])
       except:
         print "restarting as root failed"
 
   # external function
   # returns:
@@ -93,17 +102,17 @@ class DeviceManagerADB(DeviceManager):
   #  failure: None
   def pushDir(self, localDir, remoteDir):
     # adb "push" accepts a directory as an argument, but if the directory
     # contains symbolic links, the links are pushed, rather than the linked
     # files; we push file-by-file to get around this limitation
     try:
       if (not self.dirExists(remoteDir)):
         self.mkDirs(remoteDir+"/x")
-      for root, dirs, files in os.walk(localDir):
+      for root, dirs, files in os.walk(localDir, followlinks='true'):
         relRoot = os.path.relpath(root, localDir)
         for file in files:
           localFile = os.path.join(root, file)
           remoteFile = remoteDir + "/"
           if (relRoot!="."):
             remoteFile = remoteFile + relRoot + "/"
           remoteFile = remoteFile + file
           self.pushFile(localFile, remoteFile)
@@ -129,18 +138,22 @@ class DeviceManagerADB(DeviceManager):
 
   # Because we always have / style paths we make this a lot easier with some
   # assumptions
   # external function
   # returns:
   #  success: True
   #  failure: False
   def fileExists(self, filepath):
-    self.checkCmd(["shell", "ls", filepath])
-    return True
+    p = self.runCmd(["shell", "ls", "-a", filepath])
+    data = p.stdout.readlines()
+    if (len(data) == 1):
+      if (data[0].rstrip() == filepath):
+        return True
+    return False
 
   def removeFile(self, filename):
     return self.runCmd(["shell", "rm", filename]).stdout.read()
 
   # does a recursive delete of directory on the device: rm -Rf remoteDir
   # external function
   # returns:
   #  success: output of telnet, i.e. "removing file: /mnt/sdcard/tests/test.txt"
@@ -376,28 +389,21 @@ class DeviceManagerADB(DeviceManager):
     devroot = self.getDeviceRoot()
     if (devroot == None):
       return None
 
     if (self.dirExists(devroot + '/fennec')):
       return devroot + '/fennec'
     elif (self.dirExists(devroot + '/firefox')):
       return devroot + '/firefox'
-    elif (self.dirExists('/data/data/org.mozilla.fennec')):
-      return '/data/data/org.mozilla.fennec'
-    elif (self.dirExists('/data/data/org.mozilla.firefox')):
-      return '/data/data/org.mozilla.firefox'
-    elif (self.dirExists('/data/data/org.mozilla.fennec_unofficial')):
-      return '/data/data/org.mozilla.fennec_unofficial'
-    elif (self.dirExists('/data/data/org.mozilla.fennec_aurora')):
-      return '/data/data/org.mozilla.fennec_aurora'
-    elif (self.dirExists('/data/data/org.mozilla.firefox_beta')):
-      return '/data/data/org.mozilla.firefox_beta'
+    elif (self.packageName and self.dirExists('/data/data/' + self.packageName)):
+      return '/data/data/' + self.packageName
 
     # Failure (either not installed or not a recognized platform)
+    print "devicemanagerADB: getAppRoot failed"
     return None
 
   # Gets the directory location on the device for a specific test type
   # Type is one of: xpcshell|reftest|mochitest
   # external function
   # returns:
   #  success: path for test root
   #  failure: None
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -148,16 +148,30 @@ xpcshell-tests:
 	  -I$(topsrcdir)/build \
 	  $(testxpcsrcdir)/runxpcshelltests.py \
 	  --symbols-path=$(DIST)/crashreporter-symbols \
 	  --build-info-json=$(DEPTH)/mozinfo.json \
 	  $(EXTRA_TEST_ARGS) \
 	  $(LIBXUL_DIST)/bin/xpcshell \
 	  $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir))
 
+xpcshell-tests-remote: DM_TRANS?=adb
+xpcshell-tests-remote:
+	$(PYTHON) -u $(topsrcdir)/config/pythonpath.py \
+	  -I$(topsrcdir)/build \
+	  -I$(topsrcdir)/build/mobile \
+	  $(topsrcdir)/testing/xpcshell/remotexpcshelltests.py \
+	  --symbols-path=$(DIST)/crashreporter-symbols \
+	  --build-info-json=$(DEPTH)/mozinfo.json \
+	  $(EXTRA_TEST_ARGS) \
+	  --dm_trans=$(DM_TRANS) \
+	  --deviceIP=${TEST_DEVICE} \
+	  --objdir=$(DEPTH) \
+	  $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir))
+
 # Execute a single test, specified in $(SOLO_FILE), but don't automatically
 # start the test. Instead, present the xpcshell prompt so the user can
 # attach a debugger and then start the test.
 check-interactive:
 	$(PYTHON) -u $(topsrcdir)/config/pythonpath.py \
 	  -I$(topsrcdir)/build \
 	  $(testxpcsrcdir)/runxpcshelltests.py \
 	  --symbols-path=$(DIST)/crashreporter-symbols \
@@ -177,16 +191,33 @@ check-one:
 	  --build-info-json=$(DEPTH)/mozinfo.json \
 	  --test-path=$(SOLO_FILE) \
 	  --profile-name=$(MOZ_APP_NAME) \
 	  --verbose \
 	  $(EXTRA_TEST_ARGS) \
 	  $(LIBXUL_DIST)/bin/xpcshell \
 	  $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir))
 
+check-one-remote: DM_TRANS?=adb
+check-one-remote:
+	$(PYTHON) -u $(topsrcdir)/config/pythonpath.py \
+	  -I$(topsrcdir)/build \
+	  -I$(topsrcdir)/build/mobile \
+	  $(testxpcsrcdir)/remotexpcshelltests.py \
+	  --symbols-path=$(DIST)/crashreporter-symbols \
+	  --build-info-json=$(DEPTH)/mozinfo.json \
+	  --test-path=$(SOLO_FILE) \
+	  --profile-name=$(MOZ_APP_NAME) \
+	  --verbose \
+	  $(EXTRA_TEST_ARGS) \
+	  --dm_trans=$(DM_TRANS) \
+	  --deviceIP=${TEST_DEVICE} \
+	  --objdir=$(DEPTH) \
+          --noSetup \
+	  $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir))
 endif # XPCSHELL_TESTS
 
 ifdef CPP_UNIT_TESTS
 
 # Compile the tests to $(DIST)/bin.  Make lots of niceties available by default
 # through TestHarness.h, by modifying the list of includes and the libs against
 # which stuff links.
 CPPSRCS += $(CPP_UNIT_TESTS)
--- a/dom/plugins/test/unit/xpcshell.ini
+++ b/dom/plugins/test/unit/xpcshell.ini
@@ -1,6 +1,10 @@
 [DEFAULT]
 head = head_plugins.js
 tail = 
 
 [test_bug455213.js]
+# Bug 676953: test fails consistently on Android
+fail-if = os == "android"
 [test_bug471245.js]
+# Bug 676953: test fails consistently on Android
+fail-if = os == "android"
--- a/embedding/android/GeckoApp.java
+++ b/embedding/android/GeckoApp.java
@@ -416,16 +416,17 @@ abstract public class GeckoApp
         GeckoAppShell.putChildInForeground();
         super.onRestart();
     }
 
     @Override
     public void onStart()
     {
         Log.i(LOG_FILE_NAME, "start");
+        GeckoAppShell.sendEventToGecko(new GeckoEvent(GeckoEvent.ACTIVITY_START));
         super.onStart();
     }
 
     @Override
     public void onDestroy()
     {
         Log.i(LOG_FILE_NAME, "destroy");
         // Tell Gecko to shutting down; we'll end up calling System.exit()
--- a/embedding/android/GeckoEvent.java
+++ b/embedding/android/GeckoEvent.java
@@ -67,16 +67,17 @@ public class GeckoEvent {
     public static final int SIZE_CHANGED = 8;
     public static final int ACTIVITY_STOPPING = 9;
     public static final int ACTIVITY_PAUSING = 10;
     public static final int ACTIVITY_SHUTDOWN = 11;
     public static final int LOAD_URI = 12;
     public static final int SURFACE_CREATED = 13;
     public static final int SURFACE_DESTROYED = 14;
     public static final int GECKO_EVENT_SYNC = 15;
+    public static final int ACTIVITY_START = 17;
 
     public static final int IME_COMPOSITION_END = 0;
     public static final int IME_COMPOSITION_BEGIN = 1;
     public static final int IME_SET_TEXT = 2;
     public static final int IME_GET_TEXT = 3;
     public static final int IME_DELETE_TEXT = 4;
     public static final int IME_SET_SELECTION = 5;
     public static final int IME_GET_SELECTION = 6;
--- a/embedding/tests/unit/xpcshell.ini
+++ b/embedding/tests/unit/xpcshell.ini
@@ -1,6 +1,10 @@
 [DEFAULT]
 head = 
 tail = 
 
 [test_wwauthpromptfactory.js]
+# Bug 676955: test fails consistently on Android
+fail-if = os == "android"
 [test_wwpromptfactory.js]
+# Bug 676955: test fails consistently on Android
+fail-if = os == "android"
--- a/intl/uconv/tests/unit/xpcshell.ini
+++ b/intl/uconv/tests/unit/xpcshell.ini
@@ -106,16 +106,18 @@ tail =
 [test_encode_CP1255.js]
 [test_encode_CP1256.js]
 [test_encode_CP1257.js]
 [test_encode_CP1258.js]
 [test_encode_CP850.js]
 [test_encode_CP852.js]
 [test_encode_CP855.js]
 [test_encode_CP857.js]
+# Bug 676958: test consistently hangs on Android
+skip-if = os == "android"
 [test_encode_CP862.js]
 [test_encode_CP864.js]
 [test_encode_CP874.js]
 [test_encode_armscii.js]
 [test_encode_geostd8.js]
 [test_encode_gbk.js]
 [test_encode_tcvn5712.js]
 [test_encode_utf-7_internal.js]
--- a/ipc/testshell/tests/xpcshell.ini
+++ b/ipc/testshell/tests/xpcshell.ini
@@ -1,6 +1,8 @@
 [DEFAULT]
 head = 
 tail = 
 
 [test_ipcshell.js]
+# Bug 676963: test fails consistently on Android
+fail-if = os == "android"
 [test_ipcshell_child.js]
--- a/js/src/config/rules.mk
+++ b/js/src/config/rules.mk
@@ -148,16 +148,30 @@ xpcshell-tests:
 	  -I$(topsrcdir)/build \
 	  $(testxpcsrcdir)/runxpcshelltests.py \
 	  --symbols-path=$(DIST)/crashreporter-symbols \
 	  --build-info-json=$(DEPTH)/mozinfo.json \
 	  $(EXTRA_TEST_ARGS) \
 	  $(LIBXUL_DIST)/bin/xpcshell \
 	  $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir))
 
+xpcshell-tests-remote: DM_TRANS?=adb
+xpcshell-tests-remote:
+	$(PYTHON) -u $(topsrcdir)/config/pythonpath.py \
+	  -I$(topsrcdir)/build \
+	  -I$(topsrcdir)/build/mobile \
+	  $(topsrcdir)/testing/xpcshell/remotexpcshelltests.py \
+	  --symbols-path=$(DIST)/crashreporter-symbols \
+	  --build-info-json=$(DEPTH)/mozinfo.json \
+	  $(EXTRA_TEST_ARGS) \
+	  --dm_trans=$(DM_TRANS) \
+	  --deviceIP=${TEST_DEVICE} \
+	  --objdir=$(DEPTH) \
+	  $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir))
+
 # Execute a single test, specified in $(SOLO_FILE), but don't automatically
 # start the test. Instead, present the xpcshell prompt so the user can
 # attach a debugger and then start the test.
 check-interactive:
 	$(PYTHON) -u $(topsrcdir)/config/pythonpath.py \
 	  -I$(topsrcdir)/build \
 	  $(testxpcsrcdir)/runxpcshelltests.py \
 	  --symbols-path=$(DIST)/crashreporter-symbols \
@@ -177,16 +191,33 @@ check-one:
 	  --build-info-json=$(DEPTH)/mozinfo.json \
 	  --test-path=$(SOLO_FILE) \
 	  --profile-name=$(MOZ_APP_NAME) \
 	  --verbose \
 	  $(EXTRA_TEST_ARGS) \
 	  $(LIBXUL_DIST)/bin/xpcshell \
 	  $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir))
 
+check-one-remote: DM_TRANS?=adb
+check-one-remote:
+	$(PYTHON) -u $(topsrcdir)/config/pythonpath.py \
+	  -I$(topsrcdir)/build \
+	  -I$(topsrcdir)/build/mobile \
+	  $(testxpcsrcdir)/remotexpcshelltests.py \
+	  --symbols-path=$(DIST)/crashreporter-symbols \
+	  --build-info-json=$(DEPTH)/mozinfo.json \
+	  --test-path=$(SOLO_FILE) \
+	  --profile-name=$(MOZ_APP_NAME) \
+	  --verbose \
+	  $(EXTRA_TEST_ARGS) \
+	  --dm_trans=$(DM_TRANS) \
+	  --deviceIP=${TEST_DEVICE} \
+	  --objdir=$(DEPTH) \
+          --noSetup \
+	  $(foreach dir,$(XPCSHELL_TESTS),$(testxpcobjdir)/$(relativesrcdir)/$(dir))
 endif # XPCSHELL_TESTS
 
 ifdef CPP_UNIT_TESTS
 
 # Compile the tests to $(DIST)/bin.  Make lots of niceties available by default
 # through TestHarness.h, by modifying the list of includes and the libs against
 # which stuff links.
 CPPSRCS += $(CPP_UNIT_TESTS)
--- a/js/src/xpconnect/shell/xpcshell.cpp
+++ b/js/src/xpconnect/shell/xpcshell.cpp
@@ -1832,17 +1832,19 @@ main(int argc, char **argv, char **envp)
         if (argc > 1 && !strcmp(argv[1], "--greomni")) {
             nsCOMPtr<nsILocalFile> greOmni;
             nsCOMPtr<nsILocalFile> appOmni;
             XRE_GetFileFromPath(argv[2], getter_AddRefs(greOmni));
             if (argc > 3 && !strcmp(argv[3], "--appomni")) {
                 XRE_GetFileFromPath(argv[4], getter_AddRefs(appOmni));
                 argc-=2;
                 argv+=2;
-            } 
+            } else {
+                appOmni = greOmni;
+            }
             
             XRE_InitOmnijar(greOmni, appOmni);
             argc-=2;
             argv+=2;
         }
 
         nsCOMPtr<nsIServiceManager> servMan;
         rv = NS_InitXPCOM2(getter_AddRefs(servMan), appDir, &dirprovider);
--- a/js/src/xpconnect/src/nsXPConnect.cpp
+++ b/js/src/xpconnect/src/nsXPConnect.cpp
@@ -2068,17 +2068,18 @@ nsXPConnect::CreateSandbox(JSContext *cx
     if(!ccx.IsValid())
         return UnexpectedFailure(NS_ERROR_FAILURE);
 
     *_retval = nsnull;
 
     jsval rval = JSVAL_VOID;
     AUTO_MARK_JSVAL(ccx, &rval);
 
-    nsresult rv = xpc_CreateSandboxObject(cx, &rval, principal, NULL, false);
+    nsresult rv = xpc_CreateSandboxObject(cx, &rval, principal, NULL, false, 
+                                          EmptyCString());
     NS_ASSERTION(NS_FAILED(rv) || !JSVAL_IS_PRIMITIVE(rval),
                  "Bad return value from xpc_CreateSandboxObject()!");
 
     if (NS_SUCCEEDED(rv) && !JSVAL_IS_PRIMITIVE(rval)) {
         *_retval = XPCJSObjectHolder::newHolder(ccx, JSVAL_TO_OBJECT(rval));
         NS_ENSURE_TRUE(*_retval, NS_ERROR_OUT_OF_MEMORY);
 
         NS_ADDREF(*_retval);
--- a/js/src/xpconnect/src/xpccomponents.cpp
+++ b/js/src/xpconnect/src/xpccomponents.cpp
@@ -3148,17 +3148,17 @@ class Identity : public nsISupports
 {
     NS_DECL_ISUPPORTS
 };
 
 NS_IMPL_ISUPPORTS0(Identity)
 
 nsresult
 xpc_CreateSandboxObject(JSContext * cx, jsval * vp, nsISupports *prinOrSop, JSObject *proto,
-                        bool wantXrays)
+                        bool wantXrays, const nsACString &sandboxName)
 {
     // Create the sandbox global object
     nsresult rv;
     nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID(), &rv));
     if(NS_FAILED(rv))
         return NS_ERROR_XPC_UNEXPECTED;
 
     nsCOMPtr<nsIScriptObjectPrincipal> sop(do_QueryInterface(prinOrSop));
@@ -3235,16 +3235,20 @@ xpc_CreateSandboxObject(JSContext * cx, 
 
     if (vp) {
         *vp = OBJECT_TO_JSVAL(sandbox);
         if (!WrapForSandbox(cx, wantXrays, vp)) {
             return NS_ERROR_UNEXPECTED;
         }
     }
 
+    xpc::CompartmentPrivate *compartmentPrivate =
+        static_cast<xpc::CompartmentPrivate*>(JS_GetCompartmentPrivate(cx, compartment));
+    compartmentPrivate->location = sandboxName;
+
     return NS_OK;
 }
 
 /* PRBool call(in nsIXPConnectWrappedNative wrapper,
                in JSContextPtr cx,
                in JSObjectPtr obj,
                in PRUint32 argc,
                in JSValPtr argv,
@@ -3346,16 +3350,18 @@ nsXPCComponents_utils_Sandbox::CallOrCon
         }
 
         if (!prinOrSop)
             return ThrowAndFail(NS_ERROR_INVALID_ARG, cx, _retval);
     }
 
     JSObject *proto = nsnull;
     bool wantXrays = true;
+    nsCString sandboxName;
+
     if (argc > 1) {
         if (!JSVAL_IS_OBJECT(argv[1]))
             return ThrowAndFail(NS_ERROR_INVALID_ARG, cx, _retval);
 
         JSObject *optionsObject = JSVAL_TO_OBJECT(argv[1]);
         jsval option;
 
         JSBool found;
@@ -3377,19 +3383,36 @@ nsXPCComponents_utils_Sandbox::CallOrCon
         if (found) {
             if (!JS_GetProperty(cx, optionsObject, "wantXrays", &option) ||
                 !JSVAL_IS_BOOLEAN(option)) {
                 return ThrowAndFail(NS_ERROR_INVALID_ARG, cx, _retval);
             }
 
             wantXrays = JSVAL_TO_BOOLEAN(option);
         }
+
+        if (!JS_HasProperty(cx, optionsObject, "sandboxName", &found))
+            return NS_ERROR_INVALID_ARG;
+
+        if (found) {
+            if (!JS_GetProperty(cx, optionsObject, "sandboxName", &option) ||
+                !JSVAL_IS_STRING(option)) {
+                return ThrowAndFail(NS_ERROR_INVALID_ARG, cx, _retval);
+            }
+
+            char *tmp = JS_EncodeString(cx, JSVAL_TO_STRING(option));
+            if (!tmp) {
+                return ThrowAndFail(NS_ERROR_INVALID_ARG, cx, _retval);
+            }
+
+            sandboxName.Adopt(tmp, strlen(tmp));
+        }
     }
 
-    rv = xpc_CreateSandboxObject(cx, vp, prinOrSop, proto, wantXrays);
+    rv = xpc_CreateSandboxObject(cx, vp, prinOrSop, proto, wantXrays, sandboxName);
 
     if (NS_FAILED(rv)) {
         return ThrowAndFail(rv, cx, _retval);
     }
 
     *_retval = PR_TRUE;
 
     return rv;
--- a/js/src/xpconnect/src/xpcjsruntime.cpp
+++ b/js/src/xpconnect/src/xpcjsruntime.cpp
@@ -1573,32 +1573,40 @@ CompartmentStats::CompartmentStats(JSCon
     if(c == cx->runtime->atomsCompartment)
     {
         name.AssignLiteral("atoms");
     }
     else if(c->principals)
     {
         if(c->principals->codebase)
         {
-            // A hack: replace forward slashes with '\\' so they aren't
-            // treated as path separators.  Users of the reporters
-            // (such as about:memory) have to undo this change.
             name.Assign(c->principals->codebase);
-            name.ReplaceChar('/', '\\');
 
             // If it's the system compartment, append the address.
             // This means that multiple system compartments (and there
             // can be many) can be distinguished.
             if(c->isSystemCompartment)
             {
+                if (c->data && 
+                    !((xpc::CompartmentPrivate*)c->data)->location.IsEmpty())
+                {
+                    name.AppendLiteral(", ");
+                    name.Append(((xpc::CompartmentPrivate*)c->data)->location);
+                }
+
                 // ample; 64-bit address max is 18 chars
                 static const int maxLength = 31;
                 nsPrintfCString address(maxLength, ", 0x%llx", PRUint64(c));
                 name.Append(address);
             }
+
+            // A hack: replace forward slashes with '\\' so they aren't
+            // treated as path separators.  Users of the reporters
+            // (such as about:memory) have to undo this change.
+            name.ReplaceChar('/', '\\');
         }
         else
         {
             name.AssignLiteral("null-codebase");
         }
     }
     else
     {
--- a/js/src/xpconnect/src/xpcprivate.h
+++ b/js/src/xpconnect/src/xpcprivate.h
@@ -4310,17 +4310,17 @@ xpc_GetJSPrivate(JSObject *obj)
 // do setup etc on, puts the sandbox object in *vp (which must be
 // rooted by the caller), and uses the principal that's either
 // directly passed in prinOrSop or indirectly as an
 // nsIScriptObjectPrincipal holding the principal. If no principal is
 // reachable through prinOrSop, a new null principal will be created
 // and used.
 nsresult
 xpc_CreateSandboxObject(JSContext * cx, jsval * vp, nsISupports *prinOrSop,
-                        JSObject *proto, bool preferXray);
+                        JSObject *proto, bool preferXray, const nsACString &sandboxName);
 
 // Helper for evaluating scripts in a sandbox object created with
 // xpc_CreateSandboxObject(). The caller is responsible of ensuring
 // that *rval doesn't get collected during the call or usage after the
 // call. This helper will use filename and lineNo for error reporting,
 // and if no filename is provided it will use the codebase from the
 // principal and line number 1 as a fallback. if returnStringOnly is
 // true, then the result in *rval, or the exception in cx->exception
@@ -4389,16 +4389,17 @@ struct CompartmentPrivate
     // NB: key and ptr are mutually exclusive.
     nsAutoPtr<PtrAndPrincipalHashKey> key;
     nsCOMPtr<nsISupports> ptr;
     bool wantXrays;
     bool cycleCollectionEnabled;
     JSObject2JSObjectMap *waiverWrapperMap;
     // NB: we don't want this map to hold a strong reference to the wrapper.
     nsDataHashtable<nsPtrHashKey<XPCWrappedNative>, JSObject *> *expandoMap;
+    nsCString location;
 
     bool RegisterExpandoObject(XPCWrappedNative *wn, JSObject *expando) {
         if (!expandoMap) {
             expandoMap = new nsDataHashtable<nsPtrHashKey<XPCWrappedNative>, JSObject *>();
             if (!expandoMap->Init(8))
                 return false;
         }
         return expandoMap->Put(wn, expando);
--- a/js/src/xpconnect/tests/unit/xpcshell.ini
+++ b/js/src/xpconnect/tests/unit/xpcshell.ini
@@ -10,11 +10,13 @@ tail =
 [test_bug608142.js]
 [test_bug641378.js]
 [test_bug677864.js]
 [test_bug_442086.js]
 [test_file.js]
 [test_import.js]
 [test_js_weak_references.js]
 [test_localeCompare.js]
+# Bug 676965: test fails consistently on Android
+fail-if = os == "android"
 [test_recursive_import.js]
 [test_xpcomutils.js]
 [test_unload.js]
--- a/layout/base/nsPresArena.cpp
+++ b/layout/base/nsPresArena.cpp
@@ -78,21 +78,17 @@
 #   define MAP_ANON MAP_ANONYMOUS
 #  else
 #   error "Don't know how to get anonymous memory"
 #  endif
 # endif
 #endif
 
 // Size to use for PLArena block allocations.
-// XXX: This should be 8192;  the subtracted elements are a hack that's
-// required to ensure the allocation requests are power-of-two-sized and thus
-// avoid lots of wasted memory caused by the heap allocator rounding up request
-// sizes.  Bug 676457 will fix it properly.
-static const size_t ARENA_PAGE_SIZE = 8192 - sizeof(PLArena) - PL_ARENA_CONST_ALIGN_MASK;
+static const size_t ARENA_PAGE_SIZE = 8192;
 
 // Freed memory is filled with a poison value, which we arrange to
 // form a pointer either to an always-unmapped region of the address
 // space, or to a page that has been reserved and rendered
 // inaccessible via OS primitives.  See tests/TestPoisonArea.cpp for
 // extensive discussion of the requirements for this page.  The code
 // from here to 'class FreeList' needs to be kept in sync with that
 // file.
--- a/mobile/chrome/content/browser.js
+++ b/mobile/chrome/content/browser.js
@@ -317,16 +317,22 @@ var Browser = {
     window.controllers.appendController(BrowserUI);
 
     var os = Services.obs;
     os.addObserver(XPInstallObserver, "addon-install-blocked", false);
     os.addObserver(XPInstallObserver, "addon-install-started", false);
     os.addObserver(SessionHistoryObserver, "browser:purge-session-history", false);
     os.addObserver(ContentCrashObserver, "ipc:content-shutdown", false);
     os.addObserver(MemoryObserver, "memory-pressure", false);
+    os.addObserver(ActivityObserver, "application-background", false);
+    os.addObserver(ActivityObserver, "application-foreground", false);
+    os.addObserver(ActivityObserver, "system-active", false);
+    os.addObserver(ActivityObserver, "system-idle", false);
+    os.addObserver(ActivityObserver, "system-display-on", false);
+    os.addObserver(ActivityObserver, "system-display-off", false);
 
     // Listens for change in the viewable area
 #if MOZ_PLATFORM_MAEMO == 6
     os.addObserver(ViewableAreaObserver, "softkb-change", false);
 #endif
    messageManager.addMessageListener("Content:IsKeyboardOpened", ViewableAreaObserver);
 
     window.QueryInterface(Ci.nsIDOMChromeWindow).browserDOMWindow = new nsBrowserAccess();
@@ -481,16 +487,22 @@ var Browser = {
     messageManager.removeMessageListener("Browser:ErrorPage", this);
 
     var os = Services.obs;
     os.removeObserver(XPInstallObserver, "addon-install-blocked");
     os.removeObserver(XPInstallObserver, "addon-install-started");
     os.removeObserver(SessionHistoryObserver, "browser:purge-session-history");
     os.removeObserver(ContentCrashObserver, "ipc:content-shutdown");
     os.removeObserver(MemoryObserver, "memory-pressure");
+    os.removeObserver(ActivityObserver, "application-background", false);
+    os.removeObserver(ActivityObserver, "application-foreground", false);
+    os.removeObserver(ActivityObserver, "system-active", false);
+    os.removeObserver(ActivityObserver, "system-idle", false);
+    os.removeObserver(ActivityObserver, "system-display-on", false);
+    os.removeObserver(ActivityObserver, "system-display-off", false);
 
     window.controllers.removeController(this);
     window.controllers.removeController(BrowserUI);
   },
 
   getHomePage: function getHomePage(aOptions) {
     aOptions = aOptions || { useDefault: false };
 
@@ -2580,16 +2592,44 @@ var MemoryObserver = {
     // Bug 637582 - The low memory condition throws out some stuff that we still
     // need, re-selecting the active tab gets us back to where we need to be.
     let sTab = Browser.selectedTab;
     Browser._selectedTab = null;
     Browser.selectedTab = sTab;
   }
 };
 
+var ActivityObserver = {
+  _inBackground : false,
+  _notActive : false,
+  _isDisplayOff : false,
+  observe: function ao_observe(aSubject, aTopic, aData) {
+    if (aTopic == "application-background") {
+      this._inBackground = true;
+    } else if (aTopic == "application-foreground") {
+      this._inBackground = false;
+    } else if (aTopic == "system-idle") {
+      this._notActive = true;
+    } else if (aTopic == "system-active") {
+      this._notActive = false;
+    } else if (aTopic == "system-display-on") {
+      this._isDisplayOff = false;
+    } else if (aTopic == "system-display-off") {
+      this._isDisplayOff = true;
+    }
+    let activeTabState = !this._inBackground && !this._notActive && !this._isDisplayOff;
+    if (Browser.selectedTab.active != activeTabState) {
+      // On Maemo all backgrounded applications getting portrait orientation
+      // so if browser had landscape mode then we need timeout in order
+      // to finish last rotate/paint operation and have nice lookine browser in TS
+      setTimeout(function() { Browser.selectedTab.active = activeTabState; }, 0);
+    }
+  }
+};
+
 function getNotificationBox(aBrowser) {
   return Browser.getNotificationBox(aBrowser);
 }
 
 function importDialog(aParent, aSrc, aArguments) {
   // load the dialog with a synchronous XHR
   let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance();
   xhr.open("GET", aSrc, false);
--- a/mobile/installer/Makefile.in
+++ b/mobile/installer/Makefile.in
@@ -174,26 +174,23 @@ PP_DEB_FILES =	debian/control \
 		debian/compat \
 		debian/files \
 		debian/menu \
 		debian/fennec.preinst \
 		debian/fennec.prerm \
 		debian/fennec.postinst \
 		$(NULL)
 
-ifdef MOZ_ENABLE_CONTENTMANAGER
+ifeq ($(MOZ_PLATFORM_MAEMO),6)
 PP_DEB_FILES += debian/fennec.aegis \
-               $(NULL)
-endif
-ifeq ($(MOZ_PLATFORM_MAEMO),6)
-PP_DEB_FILES += debian/backup \
-                debian/restore \
-		 debian/fennec.conf \
-		 debian/fennec-cud.sh \
-		 debian/fennec-rfs.sh \
+		debian/backup \
+		debian/restore \
+		debian/fennec.conf \
+		debian/fennec-cud.sh \
+		debian/fennec-rfs.sh \
 		 debian/fennec.policy \
                 $(NULL)
 endif
 
 $(PP_DEB_FILES):
 	@$(EXIT_ON_ERROR) \
 	for f in $(PP_DEB_FILES); do \
            src=$(srcdir)/debian/`basename $$f`.in; \
@@ -237,17 +234,17 @@ else
 	cp $(DIST)/branding/$(MOZ_APP_NAME)_26x26.png $(DEBDESTDIR)/usr/share/icons/hicolor/26x26/hildon/$(MOZ_APP_NAME).png
 	$(NSINSTALL) -D $(DEBDESTDIR)/usr/share/icons/hicolor/40x40/hildon/
 	cp $(DIST)/branding/$(MOZ_APP_NAME)_40x40.png $(DEBDESTDIR)/usr/share/icons/hicolor/40x40/hildon/$(MOZ_APP_NAME).png
 endif
 	fakeroot dh_link; fakeroot dh_fixperms; fakeroot dh_installdeb; fakeroot dh_shlibdeps; fakeroot dh_gencontrol; fakeroot dh_md5sums; fakeroot dh_builddeb;
 
 # a defined CONTENTMANAGER implicitly means MOZ_PLATFORM_MAEMO is equals 6
 # in case you use CONTENTMANGER you need to sign your package to gain tracker access.
-ifdef MOZ_ENABLE_CONTENTMANAGER
+ifeq ($(MOZ_PLATFORM_MAEMO),6)
 	if test -e "/usr/bin/aegis-deb-add"; then \
 	   fakeroot aegis-deb-add -control $(DEBDESTDIR)/DEBIAN/control .. debian/fennec.aegis=_aegis; \
 	else \
 	   echo aegis-builder not found, security signing failed!; \
 	fi
 endif
 
 	echo $(DEB_PKG_NAME) > $(DIST)/deb_name.txt
--- a/mobile/installer/debian/fennec.aegis.in
+++ b/mobile/installer/debian/fennec.aegis.in
@@ -1,8 +1,9 @@
+#filter substitution
 <aegis>
   <request>
     <credential name="TrackerReadAccess" />
     <credential name="TrackerWriteAccess" />
     <credential name="Location" />
     <for path="@installdir@/@MOZ_APP_NAME@" />
     <for path="@installdir@/plugin-container" />
   </request>
--- a/modules/libpr0n/test/unit/xpcshell.ini
+++ b/modules/libpr0n/test/unit/xpcshell.ini
@@ -3,9 +3,11 @@ head =
 tail = 
 
 [test_async_notification.js]
 [test_async_notification_404.js]
 [test_async_notification_animated.js]
 [test_encoder_apng.js]
 [test_encoder_png.js]
 [test_imgtools.js]
+# Bug 676968: test fails consistently on Android
+fail-if = os == "android"
 [test_moz_icon_uri.js]
--- a/netwerk/base/src/nsProxyAutoConfig.js
+++ b/netwerk/base/src/nsProxyAutoConfig.js
@@ -70,17 +70,18 @@ nsProxyAutoConfig.prototype = {
     init: function(pacURI, pacText) {
         // remove PAC configuration if requested
         if (pacURI == "" || pacText == "") {
             this._sandBox = null;
             return;
         }
 
         // allocate a fresh Sandbox to clear global scope for new PAC script
-        this._sandBox = new Components.utils.Sandbox(pacURI);
+        this._sandBox = new Components.utils.Sandbox(pacURI, 
+                                                     {sandboxName: 'nsProxyAutoConfig'});
         Components.utils.evalInSandbox(pacUtils, this._sandBox);
 
         // add predefined functions to pac
         this._sandBox.importFunction(myIpAddress);
         this._sandBox.importFunction(dnsResolve);
         this._sandBox.importFunction(proxyAlert, "alert");
 
         // evaluate loaded js file
--- a/netwerk/test/unit/xpcshell.ini
+++ b/netwerk/test/unit/xpcshell.ini
@@ -3,16 +3,18 @@ head = head_channels.js
 tail = 
 
 [test_307_redirect.js]
 [test_NetUtil.js]
 [test_URIs.js]
 [test_aboutblank.js]
 [test_auth_proxy.js]
 [test_authentication.js]
+# Bug 675039: test hangs consistently on Android
+skip-if = os == "android"
 [test_authpromptwrapper.js]
 [test_bug203271.js]
 [test_bug248970_cache.js]
 [test_bug248970_cookie.js]
 [test_bug261425.js]
 [test_bug263127.js]
 [test_bug321706.js]
 [test_bug331825.js]
@@ -33,44 +35,58 @@ tail =
 [test_bug412945.js]
 [test_bug414122.js]
 [test_bug419157.js]
 [test_bug427957.js]
 [test_bug429347.js]
 [test_bug455311.js]
 [test_bug455598.js]
 [test_bug468426.js]
+# Bug 675039: test hangs consistently on Android 
+skip-if = os == "android"
 [test_bug468594.js]
 [test_bug470716.js]
 [test_bug479413.js]
 [test_bug479485.js]
 [test_bug482601.js]
 [test_bug484684.js]
 [test_bug490095.js]
 [test_bug504014.js]
 [test_bug510359.js]
+# Bug 675039: test hangs consistently on Android 
+skip-if = os == "android"
 [test_bug515583.js]
 [test_bug528292.js]
 [test_bug540566.js]
 [test_bug543805.js]
 [test_bug553970.js]
 [test_bug561042.js]
 [test_bug561276.js]
 [test_bug580508.js]
 [test_bug586908.js]
 [test_bug588389.js]
 [test_bug596443.js]
 [test_bug618835.js]
 [test_bug633743.js]
 [test_bug650955.js]
+# Bug 677427: test fails consistently on Android
+fail-if = os == "android"
 [test_bug652761.js]
 [test_bug651100.js]
+# Bug 675044: test fails consistently on Android
+fail-if = os == "android"  
 [test_bug654926.js]
+# Bug 675049: test fails consistently on Android
+fail-if = os == "android"  
 [test_bug654926_doom_and_read.js]
+# Bug 675049: test fails consistently on Android
+fail-if = os == "android"  
 [test_bug654926_test_seek.js]
+# Bug 675049: test fails consistently on Android
+fail-if = os == "android"  
 [test_bug659569.js]
 [test_bug660066.js]
 [test_bug651185.js]
 [test_bug667907.js]
 [test_bug670333.js]
 [test_bug667818.js]
 [test_cacheflags.js]
 [test_channel_close.js]
@@ -78,23 +94,39 @@ tail =
 [test_content_sniffer.js]
 [test_cookie_header.js]
 [test_data_protocol.js]
 [test_dns_service.js]
 [test_duplicate_headers.js]
 [test_event_sink.js]
 [test_extract_charset_from_content_type.js]
 [test_fallback_no-cache-entry_canceled.js]
+# Bug 675039: test hangs consistently on Android 
+skip-if = os == "android"
 [test_fallback_no-cache-entry_passing.js]
+# Bug 675039: test hangs consistently on Android 
+skip-if = os == "android"
 [test_fallback_redirect-to-different-origin_canceled.js]
+# Bug 675039: test hangs consistently on Android 
+skip-if = os == "android"
 [test_fallback_redirect-to-different-origin_passing.js]
+# Bug 675039: test hangs consistently on Android 
+skip-if = os == "android"
 [test_fallback_request-error_canceled.js]
+# Bug 675039: test hangs consistently on Android 
+skip-if = os == "android"
 [test_fallback_request-error_passing.js]
+# Bug 675039: test hangs consistently on Android 
+skip-if = os == "android"
 [test_fallback_response-error_canceled.js]
+# Bug 675039: test hangs consistently on Android 
+skip-if = os == "android"
 [test_fallback_response-error_passing.js]
+# Bug 675039: test hangs consistently on Android 
+skip-if = os == "android"
 [test_file_partial_inputstream.js]
 [test_file_protocol.js]
 [test_filestreams.js]
 [test_gre_resources.js]
 [test_gzipped_206.js]
 [test_head.js]
 [test_http_headers.js]
 [test_httpcancel.js]
@@ -126,14 +158,16 @@ tail =
 [test_reentrancy.js]
 [test_reopen.js]
 [test_resumable_channel.js]
 [test_resumable_truncate.js]
 [test_safeoutputstream.js]
 [test_simple.js]
 [test_sockettransportsvc_available.js]
 [test_socks.js]
+# Bug 675039: test hangs consistently on Android
+skip-if = os == "android"
 [test_standardurl.js]
 [test_standardurl_port.js]
 [test_streamcopier.js]
 [test_traceable_channel.js]
 [test_unescapestring.js]
 [test_xmlhttprequest.js]
--- a/security/manager/ssl/tests/unit/xpcshell.ini
+++ b/security/manager/ssl/tests/unit/xpcshell.ini
@@ -1,7 +1,13 @@
 [DEFAULT]
 head = 
 tail = 
 
 [test_datasignatureverifier.js]
+# Bug 676972: test hangs consistently on Android
+skip-if = os == "android"
 [test_hash_algorithms.js]
+# Bug 676972: test hangs consistently on Android
+skip-if = os == "android"
 [test_hmac.js]
+# Bug 676972: test hangs consistently on Android
+skip-if = os == "android"
--- a/services/crypto/tests/unit/xpcshell.ini
+++ b/services/crypto/tests/unit/xpcshell.ini
@@ -1,7 +1,9 @@
 [DEFAULT]
 head = head_helpers.js
 tail = 
 
 [test_crypto_crypt.js]
 [test_crypto_deriveKey.js]
 [test_crypto_random.js]
+# Bug 676977: test hangs consistently on Android
+skip-if = os == "android"
--- a/services/sync/tests/unit/xpcshell.ini
+++ b/services/sync/tests/unit/xpcshell.ini
@@ -29,17 +29,18 @@ tail =
 [test_forms_tracker.js]
 [test_history_engine.js]
 [test_history_store.js]
 [test_history_tracker.js]
 [test_hmac_error.js]
 [test_interval_triggers.js]
 [test_jpakeclient.js]
 # Bug 618233: this test produces random failures on Windows 7.
-skip-if = os == "win"
+# Bug 676978: test hangs on Android (see also testing/xpcshell/xpcshell.ini)
+skip-if = os == "win" || os == "android"
 [test_keys.js]
 [test_load_modules.js]
 [test_log4moz.js]
 [test_notifications.js]
 [test_password_store.js]
 [test_password_tracker.js]
 [test_places_guid_downgrade.js]
 [test_prefs_store.js]
@@ -55,44 +56,49 @@ skip-if = os == "win"
 [test_service_attributes.js]
 [test_service_changePassword.js]
 [test_service_checkAccount.js]
 [test_service_cluster.js]
 [test_service_createAccount.js]
 [test_service_detect_upgrade.js]
 [test_service_filelog.js]
 # Bug 664090: this test persistently fails on Windows opt builds.
-skip-if = os == "win" && !debug
+# Bug 676978: test hangs on Android (see also testing/xpcshell/xpcshell.ini)
+skip-if = (os == "win" && !debug) || os == "android"
 [test_service_getStorageInfo.js]
 [test_service_login.js]
 [test_service_migratePrefs.js]
 [test_service_passwordUTF8.js]
 [test_service_persistLogin.js]
 [test_service_startOver.js]
 [test_service_startup.js]
 [test_service_sync_401.js]
 [test_service_sync_checkServerError.js]
 # Bug 604565: this test intermittently hangs on OS X debug builds.
-skip-if = os == "mac" && debug
+# Bug 676978: test hangs on Android (see also testing/xpcshell/xpcshell.ini)
+skip-if = (os == "mac" && debug) || os == "android"
 [test_service_sync_locked.js]
 [test_service_sync_remoteSetup.js]
 # Bug 604565: this test intermittently hangs on OS X debug builds.
-skip-if = os == "mac" && debug
+# Bug 676978: test hangs on Android (see also testing/xpcshell/xpcshell.ini)
+skip-if = (os == "mac" && debug) || os == "android"
 [test_service_sync_updateEnabledEngines.js]
 # Bug 604565: this test intermittently hangs on OS X debug builds.
-skip-if = os == "mac" && debug
+# Bug 676978: test hangs on Android (see also testing/xpcshell/xpcshell.ini)
+skip-if = (os == "mac" && debug) || os == "android"
 [test_service_verifyLogin.js]
 [test_service_wipeClient.js]
 [test_service_wipeServer.js]
 [test_status.js]
 [test_status_checkSetup.js]
 [test_syncengine.js]
 [test_syncengine_sync.js]
 # Bug 604565: this test intermittently hangs on OS X debug builds.
-skip-if = os == "mac" && debug
+# Bug 676978: test hangs on Android (see also testing/xpcshell/xpcshell.ini)
+skip-if = (os == "mac" && debug) || os == "android"
 [test_syncscheduler.js]
 [test_syncstoragerequest.js]
 [test_tab_engine.js]
 [test_tab_store.js]
 [test_tab_tracker.js]
 [test_tracker_addChanged.js]
 [test_upgrade_old_sync_key.js]
 [test_utils_asyncChain.js]
--- a/storage/test/unit/xpcshell.ini
+++ b/storage/test/unit/xpcshell.ini
@@ -2,16 +2,18 @@
 head = head_storage.js
 tail = 
 
 [test_bug-365166.js]
 [test_bug-393952.js]
 [test_bug-429521.js]
 [test_bug-444233.js]
 [test_chunk_growth.js]
+# Bug 676981: test fails consistently on Android
+fail-if = os == "android"
 [test_connection_executeAsync.js]
 [test_js_helpers.js]
 [test_levenshtein.js]
 [test_like.js]
 [test_like_escape.js]
 [test_locale_collation.js]
 [test_page_size_is_32k.js]
 [test_sqlite_secure_delete.js]
@@ -25,8 +27,10 @@ tail =
 [test_storage_service.js]
 [test_storage_service_unshared.js]
 [test_storage_statement.js]
 [test_storage_statement_wrapper.js]
 [test_storage_value_array.js]
 [test_unicode.js]
 [test_vacuum.js]
 [test_telemetry_vfs.js]
+# Bug 676981: test fails consistently on Android
+# fail-if = os == "android"
--- a/testing/testsuite-targets.mk
+++ b/testing/testsuite-targets.mk
@@ -196,16 +196,39 @@ xpcshell-tests:
 	  $(topsrcdir)/testing/xpcshell/runxpcshelltests.py \
 	  --manifest=$(DEPTH)/_tests/xpcshell/xpcshell.ini \
 	  --build-info-json=$(DEPTH)/mozinfo.json \
 	  --no-logfiles \
           $(SYMBOLS_PATH) \
 	  $(TEST_PATH_ARG) $(EXTRA_TEST_ARGS) \
 	  $(LIBXUL_DIST)/bin/xpcshell
 
+REMOTE_XPCSHELL = \
+	rm -f ./$@.log && \
+	$(PYTHON) -u $(topsrcdir)/config/pythonpath.py \
+	  -I$(topsrcdir)/build \
+	  -I$(topsrcdir)/build/mobile \
+	  $(topsrcdir)/testing/xpcshell/remotexpcshelltests.py \
+	  --manifest=$(DEPTH)/_tests/xpcshell/xpcshell.ini \
+	  --build-info-json=$(DEPTH)/mozinfo.json \
+	  --no-logfiles \
+	  --dm_trans=$(DM_TRANS) \
+	  --deviceIP=${TEST_DEVICE} \
+	  --objdir=$(DEPTH) \
+	  $(SYMBOLS_PATH) \
+	  $(TEST_PATH_ARG) $(EXTRA_TEST_ARGS)
+
+xpcshell-tests-remote: DM_TRANS?=adb
+xpcshell-tests-remote:
+	@if [ "${TEST_DEVICE}" != "" -o "$(DM_TRANS)" = "adb" ]; \
+          then $(call REMOTE_XPCSHELL); $(CHECK_TEST_ERROR); \
+        else \
+          echo "please prepare your host with environment variables for TEST_DEVICE"; \
+        fi
+
 # install and run the mozmill tests
 $(DEPTH)/_tests/mozmill:
 	$(MAKE) -C $(DEPTH)/testing/mozmill install-develop PKG_STAGE=../../_tests
 	$(PYTHON) $(topsrcdir)/testing/mozmill/installmozmill.py --develop $(DEPTH)/_tests/mozmill
 
 MOZMILL_TEST_PATH = $(DEPTH)/_tests/mozmill/tests/firefox
 mozmill: TEST_PATH?=$(MOZMILL_TEST_PATH)
 mozmill: $(DEPTH)/_tests/mozmill
--- a/testing/xpcshell/remotexpcshelltests.py
+++ b/testing/xpcshell/remotexpcshelltests.py
@@ -31,270 +31,307 @@
 # use your version of this file under the terms of the MPL, indicate your
 # decision by deleting the provisions above and replace them with the notice
 # and other provisions required by the GPL or the LGPL. If you do not delete
 # the provisions above, a recipient may use your version of this file under
 # the terms of any one of the MPL, the GPL or the LGPL.
 #
 # ***** END LICENSE BLOCK ***** */
 
-import re, sys, os, os.path, logging, shutil, signal
-from glob import glob
-from optparse import OptionParser
-from subprocess import Popen, PIPE, STDOUT
-from tempfile import mkdtemp
-
+import re, sys, os
 import runxpcshelltests as xpcshell
 from automationutils import *
-import devicemanager
+import devicemanager, devicemanagerADB, devicemanagerSUT
 
+# A specialization of XPCShellTests that runs tests on an Android device
+# via devicemanager.
 class XPCShellRemote(xpcshell.XPCShellTests, object):
 
-    def __init__(self, devmgr):
+    def __init__(self, devmgr, options, args):
+        xpcshell.XPCShellTests.__init__(self)
+        self.options = options
         self.device = devmgr
-        self.testRoot = "/tests/xpcshell"
-        xpcshell.XPCShellTests.__init__(self)
-        self.profileDir = self.testRoot + '/profile'
-        self.device.mkDir(self.profileDir)
+        self.pathMapping = []
+        self.remoteTestRoot = self.device.getTestRoot("xpcshell")
+        # Terse directory names are used here ("b" for a binaries directory)
+        # to minimize the length of the command line used to execute
+        # xpcshell on the remote device. adb has a limit to the number
+        # of characters used in a shell command, and the xpcshell command
+        # line can be quite complex.
+        self.remoteBinDir = self.remoteJoin(self.remoteTestRoot, "b")
+        self.remoteScriptsDir = self.remoteTestRoot
+        self.remoteComponentsDir = self.remoteJoin(self.remoteTestRoot, "c")
+        self.profileDir = self.remoteJoin(self.remoteTestRoot, "p")
+        if options.setup:
+          self.setupUtilities()
+          self.setupTestDir()
+        self.remoteAPK = self.remoteJoin(self.remoteBinDir, os.path.basename(options.localAPK))
+        self.remoteDebugger = options.debugger
+        self.remoteDebuggerArgs = options.debuggerArgs  
 
-    #todo: figure out the remote version of this, only used for debuggerInfo
-    def getcwd(self):
-        return "/tests/"
-        
-    def readManifest(self, manifest):
-        """Given a manifest file containing a list of test directories,
-        return a list of absolute paths to the directories contained within."""
+    def remoteJoin(self, path1, path2):
+        joined = os.path.join(path1, path2)
+        joined = joined.replace('\\', '/')
+        return joined
+
+    def remoteForLocal(self, local):
+        for mapping in self.pathMapping:
+          if (os.path.abspath(mapping.local) == os.path.abspath(local)):
+            return mapping.remote
+        return local
 
-        manifestdir = self.testRoot + '/tests'
-        testdirs = []
-        try:
-            f = self.device.getFile(manifest, "temp.txt")
-            for line in f.split():
-                dir = line.rstrip()
-                path = manifestdir + '/' + dir
-                testdirs.append(path)
-            f.close()
-        except:
-            pass # just eat exceptions
-        return testdirs
+    def setupUtilities(self):
+        remotePrefDir = self.remoteJoin(self.remoteBinDir, "defaults/pref")
+        if (not self.device.dirExists(remotePrefDir)):
+          self.device.mkDirs(self.remoteJoin(remotePrefDir, "extra"))
+        if (not self.device.dirExists(self.remoteScriptsDir)):
+          self.device.mkDir(self.remoteScriptsDir)
+        if (not self.device.dirExists(self.remoteComponentsDir)):
+          self.device.mkDir(self.remoteComponentsDir)
+
+        local = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'head.js')
+        self.device.pushFile(local, self.remoteScriptsDir)
 
-    def verifyFilePath(self, fileName):
-        # approot - path to root of application - firefox or fennec
-        # xreroot - path to xulrunner binaries - firefox or fennec/xulrunner
-        # xpcshell - full or relative path to xpcshell binary
-        #given fileName, returns full path of existing file
-        if (self.device.fileExists(fileName)):
-            return fileName
-        
-        fileName = self.device.getAppRoot() + '/xulrunner/' + fileName.split('/')[-1]
-        if (self.device.fileExists(fileName)):
-            return fileName
-        
-        fileName = self.device.getAppRoot() + '/' + fileName.split('/')[-1]
-        if (not self.device.fileExists(fileName)):
-            raise devicemanager.FileError("No File found for: " + str(fileName))
+        localBin = os.path.join(self.options.objdir, "dist/bin")
+        if not os.path.exists(localBin):
+          localBin = os.path.join(self.options.objdir, "bin")
+          if not os.path.exists(localBin):
+            print >>sys.stderr, "Error: could not find bin in objdir"
+            sys.exit(1)
+
+        local = os.path.join(localBin, "xpcshell")
+        self.device.pushFile(local, self.remoteBinDir)
 
-        return fileName
+        local = os.path.join(localBin, "plugin-container")
+        self.device.pushFile(local, self.remoteBinDir)
+
+        local = os.path.join(localBin, "components/httpd.js")
+        self.device.pushFile(local, self.remoteComponentsDir)
+
+        local = os.path.join(localBin, "components/httpd.manifest")
+        self.device.pushFile(local, self.remoteComponentsDir)
+
+        local = os.path.join(localBin, "components/test_necko.xpt")
+        self.device.pushFile(local, self.remoteComponentsDir)
+
+        self.device.pushFile(self.options.localAPK, self.remoteBinDir)
 
-    def verifyDirPath(self, fileName):
-        # approot - path to root of application - firefox or fennec
-        # xreroot - path to xulrunner binaries - firefox or fennec/xulrunner
-        # xpcshell - full or relative path to xpcshell binary
-        #given fileName, returns full path of existing file
-        if (self.device.dirExists(fileName)):
-            return fileName
-        
-        fileName = self.device.getAppRoot() + '/' + fileName.split('/')[-1]
-        if (self.device.dirExists(fileName)):
-            return fileName
-        
-        fileName = self.device.getDeviceRoot() + '/' + fileName.split('/')[-1]
-        if (not self.device.dirExists(fileName)):
-            raise devicemanager.FileError("No Dir found for: " + str(fileName))
-        return fileName
+        localLib = os.path.join(self.options.objdir, "dist/fennec")
+        if not os.path.exists(localLib):
+          localLib = os.path.join(self.options.objdir, "fennec/lib")
+          if not os.path.exists(localLib):
+            print >>sys.stderr, "Error: could not find libs in objdir"
+            sys.exit(1)
+
+        for file in os.listdir(localLib):
+          if (file.endswith(".so")):
+            self.device.pushFile(os.path.join(localLib, file), self.remoteBinDir)
 
-    def setAbsPath(self):
-        #testharnessdir is used for head.js
-        self.testharnessdir = "/tests/xpcshell/"
+    def setupTestDir(self):
+        xpcDir = os.path.join(self.options.objdir, "_tests/xpcshell")
+        self.device.pushDir(xpcDir, self.remoteScriptsDir)
 
-        # If the file exists then we have a full path (no notion of cwd)
-        self.xpcshell = self.verifyFilePath(self.xpcshell)
-        if self.xrePath is None:
-            # If no xrePath, assume it is the directory containing xpcshell
-            self.xrePath = '/'.join(self.xpcshell.split('/')[:-1])
-        else:
-            self.xrePath = self.verifyDirPath(self.xrePath)
-
-        # we assume that httpd.js lives in components/ relative to xpcshell
-        self.httpdJSPath = self.xrePath + '/components/httpd.js'
+    def buildTestList(self):
+        xpcshell.XPCShellTests.buildTestList(self)
+        uniqueTestPaths = set([])
+        for test in self.alltests:
+          uniqueTestPaths.add(test['here'])
+        for testdir in uniqueTestPaths:
+          xpcDir = os.path.join(self.options.objdir, "_tests/xpcshell")
+          abbrevTestDir = os.path.relpath(testdir, xpcDir)
+          remoteScriptDir = self.remoteJoin(self.remoteScriptsDir, abbrevTestDir)
+          self.pathMapping.append(PathMapping(testdir, remoteScriptDir))
 
     def buildXpcsCmd(self, testdir):
-        # <head.js> has to be loaded by xpchell: it can't load itself.
-        self.env["XPCSHELL_TEST_PROFILE_DIR"] = self.profileDir
-        self.xpcsCmd = [self.xpcshell, '-g', self.xrePath, '-v', '170', '-j', '-s', \
-                        "--environ:CWD='" + testdir + "'", \
-                        "--environ:XPCSHELL_TEST_PROFILE_DIR='" + self.env["XPCSHELL_TEST_PROFILE_DIR"] + "'", \
-                        '-e', 'const _HTTPD_JS_PATH = \'%s\';' % self.httpdJSPath,
-                        '-f', self.testharnessdir + '/head.js']
+        self.xpcsCmd = [
+           self.remoteJoin(self.remoteBinDir, "xpcshell"),
+           '-r', self.remoteJoin(self.remoteComponentsDir, 'httpd.manifest'),
+           '--greomni', self.remoteAPK,
+           '-j', '-s',
+           '-e', 'const _HTTPD_JS_PATH = "%s";' % self.remoteJoin(self.remoteComponentsDir, 'httpd.js'),
+           '-e', 'const _HEAD_JS_PATH = "%s";' % self.remoteJoin(self.remoteScriptsDir, 'head.js'),
+           '-f', self.remoteScriptsDir+'/head.js']
 
-        if self.debuggerInfo:
-            self.xpcsCmd = [self.debuggerInfo["path"]] + self.debuggerInfo["args"] + self.xpcsCmd
+        if self.remoteDebugger:
+          # for example, "/data/local/gdbserver" "localhost:12345"
+          self.xpcsCmd = [
+            self.remoteDebugger, 
+            self.remoteDebuggerArgs, 
+            self.xpcsCmd]
 
-    def getHeadFiles(self, testdir):
-        # get the list of head and tail files from the directory
-        testHeadFiles = []
-        for f in self.device.listFiles(testdir):
-            hdmtch = re.compile("head_.*\.js")
-            if (hdmtch.match(f)):
-                testHeadFiles += [(testdir + '/' + f).replace('/', '//')]
-                
-        return sorted(testHeadFiles)
-                
-    def getTailFiles(self, testdir):
-        testTailFiles = []
-        # Tails are executed in the reverse order, to "match" heads order,
-        # as in "h1-h2-h3 then t3-t2-t1".
-        for f in self.device.listFiles(testdir):
-            tlmtch = re.compile("tail_.*\.js")
-            if (tlmtch.match(f)):
-                testTailFiles += [(testdir + '/' + f).replace('/', '//')]
-        return reversed(sorted(testTailFiles))
+    def getHeadFiles(self, test):
+        self.remoteHere = self.remoteForLocal(test['here'])
+        return [f.strip() for f in sorted(test['head'].split(' ')) if self.device.fileExists(self.remoteJoin(self.remoteHere, f))]
+    
+    def getTailFiles(self, test):
+        return [f.strip() for f in sorted(test['tail'].split(' ')) if self.device.fileExists(self.remoteJoin(self.remoteHere, f))]
         
-    def getTestFiles(self, testdir):
-        testfiles = []
-        # if a single test file was specified, we only want to execute that test
-        for f in self.device.listFiles(testdir):
-            tstmtch = re.compile("test_.*\.js")
-            if (tstmtch.match(f)):
-                testfiles += [(testdir + '/' + f).replace('/', '//')]
-        
-        for f in testfiles:
-            if (self.singleFile == f.split('/')[-1]):
-                return [(testdir + '/' + f).replace('/', '//')]
-            else:
-                pass
-        return testfiles
+    def buildCmdTestFile(self, name):
+        remoteDir = self.remoteForLocal(os.path.dirname(name))
+        if remoteDir == self.remoteHere:
+          remoteName = os.path.basename(name)
+        else:
+          remoteName = self.remoteJoin(remoteDir, os.path.basename(name))
+        return ['-e', 'const _TEST_FILE = ["%s"];' %
+                 replaceBackSlashes(remoteName)]
 
     def setupProfileDir(self):
         self.device.removeDir(self.profileDir)
         self.device.mkDir(self.profileDir)
-        self.env["XPCSHELL_TEST_PROFILE_DIR"] = self.profileDir
+        if self.interactive or self.singleFile:
+          self.log.info("TEST-INFO | profile dir is %s" % self.profileDir)
         return self.profileDir
 
-    def setupLeakLogging(self):
-        filename = "runxpcshelltests_leaks.log"
-        
-        # Enable leaks (only) detection to its own log file.
-        leakLogFile = self.profileDir + '/' + filename
-        self.env["XPCOM_MEM_LEAK_LOG"] = leakLogFile
-        return leakLogFile
+    def launchProcess(self, cmd, stdout, stderr, env, cwd):
+        # Some xpcshell arguments contain characters that are interpretted
+        # by the adb shell; enclose these arguments in quotes.
+        index = 0
+        for part in cmd:
+          if (part.find(" ")>=0 or part.find("(")>=0 or part.find(")")>=0 or part.find("\"")>=0):
+            part = '\''+part+'\''
+            cmd[index] = part
+          index = index + 1
+
+        xpcshell = self.remoteJoin(self.remoteBinDir, "xpcshell")
 
-    def launchProcess(self, cmd, stdout, stderr, env, cwd):
-        print "launching : " + " ".join(cmd)
-        proc = self.device.launchProcess(cmd, cwd=cwd)
+        shellArgs = "cd "+self.remoteHere
+        shellArgs += "; LD_LIBRARY_PATH="+self.remoteBinDir
+        shellArgs += "; export CACHE_PATH="+self.remoteBinDir
+        shellArgs += "; export GRE_HOME="+self.device.getAppRoot()
+        shellArgs += "; export XPCSHELL_TEST_PROFILE_DIR="+self.profileDir
+        shellArgs += "; "+xpcshell+" "
+        shellArgs += " ".join(cmd[1:])
+
+        if self.verbose:
+          self.log.info(shellArgs)
+
+        # If the adb version of devicemanager is used and the arguments passed
+        # to adb exceed ~1024 characters, the command may not execute.
+        if len(shellArgs) > 1000:
+          self.log.info("adb command length is excessive and may cause failure")
+
+        proc = self.device.runCmd(["shell", shellArgs])
         return proc
 
-    def setSignal(self, proc, sig1, sig2):
-        self.device.signal(proc, sig1, sig2)
-
     def communicate(self, proc):
-        return self.device.communicate(proc)
+        return proc.communicate()
 
     def removeDir(self, dirname):
         self.device.removeDir(dirname)
 
     def getReturnCode(self, proc):
-        return self.device.getReturnCode(proc)
+        return proc.returncode
 
     #TODO: consider creating a separate log dir.  We don't have the test file structure,
     #      so we use filename.log.  Would rather see ./logs/filename.log
-    def createLogFile(self, test, stdout):
+    def createLogFile(self, test, stdout, leakLogs):
         try:
             f = None
             filename = test.replace('\\', '/').split('/')[-1] + ".log"
             f = open(filename, "w")
             f.write(stdout)
 
-            if os.path.exists(self.leakLogFile):
-                leaks = open(self.leakLogFile, "r")
+            for leakLog in leakLogs:
+              if os.path.exists(leakLog):
+                leaks = open(leakLog, "r")
                 f.write(leaks.read())
                 leaks.close()
         finally:
             if f <> None:
                 f.close()
 
-    #NOTE: the only difference between this and parent is the " vs ' arond the filename
-    def buildCmdHead(self, headfiles, tailfiles, xpcscmd):
-        cmdH = ", ".join(['\'' + f.replace('\\', '/') + '\''
-                       for f in headfiles])
-        cmdT = ", ".join(['\'' + f.replace('\\', '/') + '\''
-                       for f in tailfiles])
-        cmdH = xpcscmd + \
-                ['-e', 'const _HEAD_FILES = [%s];' % cmdH] + \
-                ['-e', 'const _TAIL_FILES = [%s];' % cmdT]
-        return cmdH
-
 class RemoteXPCShellOptions(xpcshell.XPCShellOptions):
 
-  def __init__(self):
-    xpcshell.XPCShellOptions.__init__(self)
-    self.add_option("--device",
-                    type="string", dest="device", default='',
-                    help="ip address for the device")
+    def __init__(self):
+        xpcshell.XPCShellOptions.__init__(self)
+        defaults = {}
+
+        self.add_option("--deviceIP", action="store",
+                        type = "string", dest = "deviceIP",
+                        help = "ip address of remote device to test")
+        defaults["deviceIP"] = None
+ 
+        self.add_option("--devicePort", action="store",
+                        type = "string", dest = "devicePort",
+                        help = "port of remote device to test")
+        defaults["devicePort"] = 20701
 
+        self.add_option("--dm_trans", action="store",
+                        type = "string", dest = "dm_trans",
+                        help = "the transport to use to communicate with device: [adb|sut]; default=sut")
+        defaults["dm_trans"] = "sut"
+ 
+        self.add_option("--objdir", action="store",
+                        type = "string", dest = "objdir",
+                        help = "local objdir, containing xpcshell binaries")
+        defaults["objdir"] = None
+ 
+        self.add_option("--apk", action="store",
+                        type = "string", dest = "localAPK",
+                        help = "local path to Fennec APK")
+        defaults["localAPK"] = None
+
+        self.add_option("--noSetup", action="store_false",
+                        dest = "setup",
+                        help = "do not copy any files to device (to be used only if device is already setup)")
+        defaults["setup"] = True
+
+        self.set_defaults(**defaults)
+
+class PathMapping:
+
+    def __init__(self, localDir, remoteDir):
+        self.local = localDir
+        self.remote = remoteDir
 
 def main():
 
-  parser = RemoteXPCShellOptions()
-  options, args = parser.parse_args()
+    dm_none = devicemanagerADB.DeviceManagerADB(None, None)
+    parser = RemoteXPCShellOptions()
+    options, args = parser.parse_args()
 
-  if len(args) < 2 and options.manifest is None or \
-     (len(args) < 1 and options.manifest is not None):
-     print "len(args): " + str(len(args))
-     print >>sys.stderr, """Usage: %s <path to xpcshell> <test dirs>
-           or: %s --manifest=test.manifest <path to xpcshell>""" % (sys.argv[0],
-                                                           sys.argv[0])
-     sys.exit(1)
+    if len(args) < 1 and options.manifest is None:
+      print >>sys.stderr, """Usage: %s <test dirs>
+           or: %s --manifest=test.manifest """ % (sys.argv[0], sys.argv[0])
+      sys.exit(1)
 
-  if (options.device == ''):
-    print >>sys.stderr, "Error: Please provide an ip address for the remote device with the --device option"
-    sys.exit(1)
-
+    if (options.dm_trans == "adb"):
+      if (options.deviceIP):
+        dm = devicemanagerADB.DeviceManagerADB(options.deviceIP, options.devicePort)
+      else:
+        dm = dm_none
+    else:
+      dm = devicemanagerSUT.DeviceManagerSUT(options.deviceIP, options.devicePort)
+      if (options.deviceIP == None):
+        print "Error: you must provide a device IP to connect to via the --device option"
+        sys.exit(1)
 
-  dm = devicemanager.DeviceManager(options.device, 20701)
-  xpcsh = XPCShellRemote(dm)
-  debuggerInfo = getDebuggerInfo(xpcsh.oldcwd, options.debugger, options.debuggerArgs,
-    options.debuggerInteractive);
-
-  if options.interactive and not options.testPath:
-    print >>sys.stderr, "Error: You must specify a test filename in interactive mode!"
-    sys.exit(1)
+    if options.interactive and not options.testPath:
+      print >>sys.stderr, "Error: You must specify a test filename in interactive mode!"
+      sys.exit(1)
 
-  # Zip up the xpcshell directory: 7z a <zipName> xpcshell/*, assuming we are in the xpcshell directory
-  # TODO: ensure the system has 7z, this is adding a new dependency to the overall system
-  zipName = 'xpcshell.7z'
-  try:
-    Popen(['7z', 'a', zipName, '../xpcshell']).wait()
-  except:
-    print "to run these tests remotely, we require 7z to be installed and in your path"
-    sys.exit(1)
+    if not options.objdir:
+      print >>sys.stderr, "Error: You must specify an objdir"
+      sys.exit(1)
 
-  if dm.pushFile(zipName, '/tests/xpcshell.7z') == None:
-     raise devicemanager.FileError("failed to copy xpcshell.7z to device")
-  if dm.unpackFile('xpcshell.7z') == None:
-     raise devicemanager.FileError("failed to unpack xpcshell.7z on the device")
+    if not options.localAPK:
+      for file in os.listdir(os.path.join(options.objdir, "dist")):
+        if (file.endswith(".apk") and file.startswith("fennec")):
+          options.localAPK = os.path.join(options.objdir, "dist")
+          options.localAPK = os.path.join(options.localAPK, file)
+          print >>sys.stderr, "using APK: " + options.localAPK
+          break
+      
+    if not options.localAPK:
+      print >>sys.stderr, "Error: please specify an APK"
+      sys.exit(1)
 
-  if not xpcsh.runTests(args[0],
-                        xrePath=options.xrePath,
-                        symbolsPath=options.symbolsPath,
-                        manifest=options.manifest,
-                        testdirs=args[1:],
-                        testPath=options.testPath,
-                        interactive=options.interactive,
-                        logfiles=options.logfiles,
-                        debuggerInfo=debuggerInfo):
-    sys.exit(1)
+    xpcsh = XPCShellRemote(dm, options, args)
+
+    if not xpcsh.runTests(xpcshell='xpcshell', 
+                          testdirs=args[0:], 
+                          **options.__dict__):
+      sys.exit(1)
+
 
 if __name__ == '__main__':
   main()
 
-
-
--- a/testing/xpcshell/runxpcshelltests.py
+++ b/testing/xpcshell/runxpcshelltests.py
@@ -256,36 +256,36 @@ class XPCShellTests(object):
         self.testPath = self.testPath.rstrip("/")
 
 
   def getHeadFiles(self, test):
     """
       test['head'] is a whitespace delimited list of head files.
       return the list of head files as paths including the subdir if the head file exists
 
-      On a remote system, this is overloaded to list files in a remote directory structure.
+      On a remote system, this may be overloaded to list files in a remote directory structure.
     """
     return [os.path.join(test['here'], f).strip() for f in sorted(test['head'].split(' ')) if os.path.isfile(os.path.join(test['here'], f))]
 
   def getTailFiles(self, test):
     """
       test['tail'] is a whitespace delimited list of head files.
       return the list of tail files as paths including the subdir if the tail file exists
 
-      On a remote system, this is overloaded to list files in a remote directory structure.
+      On a remote system, this may be overloaded to list files in a remote directory structure.
     """
     return [os.path.join(test['here'], f).strip() for f in sorted(test['tail'].split(' ')) if os.path.isfile(os.path.join(test['here'], f))]
 
   def setupProfileDir(self):
     """
       Create a temporary folder for the profile and set appropriate environment variables.
       When running check-interactive and check-one, the directory is well-defined and
       retained for inspection once the tests complete.
 
-      On a remote system, we overload this to use a remote path structure.
+      On a remote system, this may be overloaded to use a remote path structure.
     """
     if self.interactive or self.singleFile:
       profileDir = os.path.join(gettempdir(), self.profileName, "xpcshellprofile")
       try:
         # This could be left over from previous runs
         self.removeDir(profileDir)
       except:
         pass
@@ -296,17 +296,17 @@ class XPCShellTests(object):
     if self.interactive or self.singleFile:
       self.log.info("TEST-INFO | profile dir is %s" % profileDir)
     return profileDir
 
   def setupLeakLogging(self):
     """
       Enable leaks (only) detection to its own log file and set environment variables.
 
-      On a remote system, we overload this to use a remote filename and path structure
+      On a remote system, this may be overloaded to use a remote filename and path structure
     """
     filename = "runxpcshelltests_leaks.log"
 
     leakLogFile = os.path.join(self.profileDir,  filename)
     self.env["XPCOM_MEM_LEAK_LOG"] = leakLogFile
     return leakLogFile
 
   def launchProcess(self, cmd, stdout, stderr, env, cwd):
@@ -376,22 +376,30 @@ class XPCShellTests(object):
                    for f in headfiles])
     cmdT = ", ".join(['"' + replaceBackSlashes(f) + '"'
                    for f in tailfiles])
     return xpcscmd + \
             ['-e', 'const _SERVER_ADDR = "localhost"',
              '-e', 'const _HEAD_FILES = [%s];' % cmdH,
              '-e', 'const _TAIL_FILES = [%s];' % cmdT]
 
+  def buildCmdTestFile(self, name):
+    """
+      Build the command line arguments for the test file.
+      On a remote system, this may be overloaded to use a remote path structure.
+    """
+    return ['-e', 'const _TEST_FILE = ["%s"];' %
+              replaceBackSlashes(name)]
+
   def runTests(self, xpcshell, xrePath=None, appPath=None, symbolsPath=None,
                manifest=None, testdirs=[], testPath=None,
                interactive=False, verbose=False, keepGoing=False, logfiles=True,
                thisChunk=1, totalChunks=1, debugger=None,
                debuggerArgs=None, debuggerInteractive=False,
-               profileName=None, mozInfo=None):
+               profileName=None, mozInfo=None, **otherOptions):
     """Run xpcshell tests.
 
     |xpcshell|, is the xpcshell executable to use to run the tests.
     |xrePath|, if provided, is the path to the XRE to use.
     |appPath|, if provided, is the path to an application directory.
     |symbolsPath|, if provided is the path to a directory containing
       breakpad symbols for processing crashes in tests.
     |manifest|, if provided, is a file containing a list of
@@ -405,16 +413,17 @@ class XPCShellTests(object):
       be printed always
     |logfiles|, if set to False, indicates not to save output to log files.
       Non-interactive only option.
     |debuggerInfo|, if set, specifies the debugger and debugger arguments
       that will be used to launch xpcshell.
     |profileName|, if set, specifies the name of the application for the profile
       directory if running only a subset of tests.
     |mozInfo|, if set, specifies specifies build configuration information, either as a filename containing JSON, or a dict.
+    |otherOptions| may be present for the convenience of subclasses
     """
 
     global gotSIGINT 
 
     self.xpcshell = xpcshell
     self.xrePath = xrePath
     self.appPath = appPath
     self.symbolsPath = symbolsPath
@@ -486,18 +495,17 @@ class XPCShellTests(object):
       testTailFiles = self.getTailFiles(test)
       cmdH = self.buildCmdHead(testHeadFiles, testTailFiles, self.xpcsCmd)
 
       # create a temp dir that the JS harness can stick a profile in
       self.profileDir = self.setupProfileDir()
       self.leakLogFile = self.setupLeakLogging()
 
       # The test file will have to be loaded after the head files.
-      cmdT = ['-e', 'const _TEST_FILE = ["%s"];' %
-                replaceBackSlashes(name)]
+      cmdT = self.buildCmdTestFile(name)
 
       try:
         self.log.info("TEST-INFO | %s | running test ..." % name)
         startTime = time.time()
 
         proc = self.launchProcess(cmdH + cmdT + self.xpcsRunArgs,
                     stdout=pStdout, stderr=pStderr, env=self.env, cwd=testdir)
 
@@ -510,18 +518,19 @@ class XPCShellTests(object):
 
         if interactive:
           # Not sure what else to do here...
           return True
 
         def print_stdout(stdout):
           """Print stdout line-by-line to avoid overflowing buffers."""
           self.log.info(">>>>>>>")
-          for line in stdout.splitlines():
-            self.log.info(line)
+          if (stdout):
+            for line in stdout.splitlines():
+              self.log.info(line)
           self.log.info("<<<<<<<")
 
         result = not ((self.getReturnCode(proc) != 0) or
                       (stdout and re.search("^((parent|child): )?TEST-UNEXPECTED-",
                                             stdout, re.MULTILINE)) or
                       (stdout and re.search(": SyntaxError:", stdout,
                                             re.MULTILINE)))
 
--- a/testing/xpcshell/xpcshell.ini
+++ b/testing/xpcshell/xpcshell.ini
@@ -10,16 +10,18 @@
 [include:dom/src/json/test/unit/xpcshell.ini]
 [include:dom/tests/unit/xpcshell.ini]
 [include:content/xtf/test/unit/xpcshell.ini]
 [include:docshell/test/unit/xpcshell.ini]
 [include:embedding/tests/unit/xpcshell.ini]
 [include:toolkit/components/commandlines/test/unit/xpcshell.ini]
 [include:toolkit/components/contentprefs/tests/unit/xpcshell.ini]
 [include:toolkit/components/passwordmgr/test/unit/xpcshell.ini]
+# Bug 676989: tests hang on Android
+skip-if = os == "android"
 [include:toolkit/components/places/tests/migration/xpcshell.ini]
 [include:toolkit/components/places/tests/autocomplete/xpcshell.ini]
 [include:toolkit/components/places/tests/expiration/xpcshell.ini]
 [include:toolkit/components/places/tests/sync/xpcshell.ini]
 [include:toolkit/components/places/tests/bookmarks/xpcshell.ini]
 [include:toolkit/components/places/tests/queries/xpcshell.ini]
 [include:toolkit/components/places/tests/unit/xpcshell.ini]
 [include:toolkit/components/places/tests/network/xpcshell.ini]
@@ -54,16 +56,18 @@
 [include:gfx/tests/unit/xpcshell.ini]
 [include:widget/tests/unit/xpcshell.ini]
 [include:content/base/test/unit/xpcshell.ini]
 [include:content/test/unit/xpcshell.ini]
 [include:toolkit/components/url-classifier/tests/unit/xpcshell.ini]
 [include:services/crypto/tests/unit/xpcshell.ini]
 [include:services/crypto/components/tests/unit/xpcshell.ini]
 [include:services/sync/tests/unit/xpcshell.ini]
+# Bug 676978: tests hang on Android 
+skip-if = os == "android"
 [include:browser/components/dirprovider/tests/unit/xpcshell.ini]
 [include:browser/components/feeds/test/unit/xpcshell.ini]
 [include:browser/components/places/tests/unit/xpcshell.ini]
 [include:browser/components/privatebrowsing/test/unit/xpcshell.ini]
 [include:browser/components/shell/test/unit/xpcshell.ini]
 [include:extensions/spellcheck/hunspell/tests/unit/xpcshell.ini]
 [include:toolkit/components/search/tests/xpcshell/xpcshell.ini]
 [include:toolkit/mozapps/shared/test/unit/xpcshell.ini]
--- a/toolkit/components/ctypes/tests/unit/xpcshell.ini
+++ b/toolkit/components/ctypes/tests/unit/xpcshell.ini
@@ -1,5 +1,7 @@
 [DEFAULT]
 head = 
 tail = 
 
 [test_jsctypes.js]
+# Bug 676989: test fails consistently on Android
+fail-if = os == "android"
--- a/toolkit/components/downloads/test/unit/xpcshell.ini
+++ b/toolkit/components/downloads/test/unit/xpcshell.ini
@@ -6,18 +6,22 @@ tail =
 [test_bug_384744.js]
 [test_bug_395092.js]
 [test_bug_401430.js]
 [test_bug_401582.js]
 [test_bug_406857.js]
 [test_bug_409179.js]
 [test_bug_420230.js]
 [test_cancel_download_files_removed.js]
+# Bug 676989: test hangs consistently on Android
+skip-if = os == "android"
 [test_download_manager.js]
 [test_download_samename.js]
+# Bug 676989: test hangs consistently on Android
+skip-if = os == "android" 
 [test_history_expiration.js]
 [test_memory_db_support.js]
 [test_offline_support.js]
 [test_old_download_files_removed.js]
 [test_privatebrowsing.js]
 [test_privatebrowsing_cancel.js]
 [test_removeDownloadsByTimeframe.js]
 [test_resume.js]
--- a/toolkit/components/places/tests/autocomplete/xpcshell.ini
+++ b/toolkit/components/places/tests/autocomplete/xpcshell.ini
@@ -3,18 +3,24 @@ head = head_autocomplete.js
 tail = 
 
 [test_416211.js]
 [test_416214.js]
 [test_417798.js]
 [test_418257.js]
 [test_422277.js]
 [test_autocomplete_on_value_removed_479089.js]
+# Bug 676989: test fails consistently on Android
+fail-if = os == "android"
 [test_download_embed_bookmarks.js]
+# Bug 676989: test fails consistently on Android
+fail-if = os == "android"
 [test_empty_search.js]
+# Bug 676989: test fails consistently on Android
+fail-if = os == "android"
 [test_enabled.js]
 [test_escape_self.js]
 [test_ignore_protocol.js]
 [test_keyword_search.js]
 [test_livemarks.js]
 [test_match_beginning.js]
 [test_multi_word_search.js]
 [test_special_search.js]
--- a/toolkit/components/places/tests/expiration/xpcshell.ini
+++ b/toolkit/components/places/tests/expiration/xpcshell.ini
@@ -1,16 +1,26 @@
 [DEFAULT]
 head = head_expiration.js
 tail = 
 
 [test_analyze_runs.js]
+# Bug 676989: test hangs consistently on Android
+skip-if = os == "android"
 [test_annos_expire_history.js]
 [test_annos_expire_never.js]
 [test_annos_expire_policy.js]
 [test_annos_expire_session.js]
+# Bug 676989: test fails consistently on Android
+fail-if = os == "android"
 [test_notifications.js]
+# Bug 676989: test fails consistently on Android
+fail-if = os == "android"
 [test_notifications_onDeleteURI.js]
 [test_notifications_onDeleteVisits.js]
 [test_pref_interval.js]
+# Bug 676989: test fails consistently on Android
+fail-if = os == "android"
 [test_pref_maxpages.js]
+# Bug 676989: test fails consistently on Android
+fail-if = os == "android" 
 [test_removeAllPages.js]
 [test_debug_expiration.js]
--- a/toolkit/components/places/tests/queries/xpcshell.ini
+++ b/toolkit/components/places/tests/queries/xpcshell.ini
@@ -8,17 +8,25 @@ tail =
 [test_async.js]
 [test_containersQueries_sorting.js]
 [test_excludeReadOnlyFolders.js]
 [test_history_queries_tags_liveUpdate.js]
 [test_history_queries_titles_liveUpdate.js]
 [test_onlyBookmarked.js]
 [test_querySerialization.js]
 [test_redirectsMode.js]
+# Bug 676989: test hangs consistently on Android
+skip-if = os == "android"
 [test_results-as-tag-contents-query.js]
 [test_results-as-visit.js]
 [test_searchterms-domain.js]
 [test_searchterms-uri.js]
 [test_searchterms-bookmarklets.js]
 [test_sort-date-site-grouping.js]
 [test_sorting.js]
+# Bug 676989: test hangs consistently on Android
+skip-if = os == "android" 
 [test_tags.js]
+# Bug 676989: test hangs consistently on Android
+skip-if = os == "android"
 [test_transitions.js]
+# Bug 676989: test hangs consistently on Android
+skip-if = os == "android"
--- a/toolkit/components/places/tests/unit/xpcshell.ini
+++ b/toolkit/components/places/tests/unit/xpcshell.ini
@@ -1,26 +1,30 @@
 [DEFAULT]
 head = head_bookmarks.js
 tail = 
 
 [test_000_frecency.js]
 [test_248970.js]
 [test_317472.js]
+# Bug 676989: test hangs consistently on Android
+skip-if = os == "android"
 [test_331487.js]
 [test_385397.js]
 [test_399264_query_to_string.js]
 [test_399264_string_to_query.js]
 [test_399266.js]
 [test_399606.js]
 [test_402799.js]
 [test_404630.js]
 [test_405497.js]
 [test_408221.js]
 [test_412132.js]
+# Bug 676989: test hangs consistently on Android
+skip-if = os == "android"
 [test_413784.js]
 [test_415460.js]
 [test_415757.js]
 [test_418643_removeFolderChildren.js]
 [test_419731.js]
 [test_419792_node_tags_property.js]
 [test_420331_wyciwyg.js]
 [test_421180.js]
@@ -32,64 +36,86 @@ tail =
 [test_452777.js]
 [test_454977.js]
 [test_457698_crash.js]
 [test_463863.js]
 [test_485442_crash_bug_nsNavHistoryQuery_GetUri.js]
 [test_486978_sort_by_date_queries.js]
 [test_536081.js]
 [test_adaptive.js]
+# Bug 676989: test hangs consistently on Android
+skip-if = os == "android"
 [test_adaptive_bug527311.js]
 [test_annotations.js]
 [test_asyncExecuteLegacyQueries.js]
+# Bug 676989: test hangs consistently on Android
+skip-if = os == "android"
 [test_async_history_api.js]
 [test_autocomplete_stopSearch_no_throw.js]
 [test_bookmark_catobs.js]
 [test_bookmarks_setNullTitle.js]
 [test_broken_folderShortcut_result.js]
 [test_browserhistory.js]
 [test_bug636917_isLivemark.js]
 [test_childlessTags.js]
 [test_crash_476292.js]
 [test_database_replaceOnStartup.js]
 [test_doSetAndLoadFaviconForPage.js]
 [test_doSetAndLoadFaviconForPage_failures.js]
+# Bug 676989: test fails consistently on Android
+fail-if = os == "android"
 [test_download_history.js]
+# Bug 676989: test fails consistently on Android
+fail-if = os == "android"
 [test_dynamic_containers.js]
 [test_exclude_livemarks.js]
 [test_faviconService_expireAllFavicons.js]
 [test_favicons.js]
+# Bug 676989: test fails consistently on Android
+fail-if = os == "android"
 [test_frecency.js]
+# Bug 676989: test hangs consistently on Android
+skip-if = os == "android"
 [test_getChildIndex.js]
 [test_history.js]
 [test_history_autocomplete_tags.js]
 [test_history_catobs.js]
 [test_history_notifications.js]
 [test_history_observer.js]
 [test_history_removeAllPages.js]
+# Bug 676989: test hangs consistently on Android
+skip-if = os == "android"
 [test_history_sidebar.js]
 [test_isvisited.js]
 [test_lastModified.js]
 [test_livemarkService_getLivemarkIdForFeedURI.js]
 [test_markpageas.js]
 [test_moz-anno_favicon_mime_type.js]
 [test_multi_queries.js]
 [test_multi_word_tags.js]
 [test_nsINavHistoryViewer.js]
 [test_null_interfaces.js]
 [test_onBeforeDeleteURI_observer.js]
 [test_onItemChanged_tags.js]
 [test_placeURIs.js]
 [test_preventive_maintenance.js]
+# Bug 676989: test hangs consistently on Android
+skip-if = os == "android"
 [test_preventive_maintenance_checkAndFixDatabase.js]
+# Bug 676989: test hangs consistently on Android
+skip-if = os == "android"
 [test_preventive_maintenance_console.js]
 [test_removeVisitsByTimeframe.js]
+# Bug 676989: test hangs consistently on Android
+skip-if = os == "android"
 [test_resolveNullBookmarkTitles.js]
 [test_result_sort.js]
 [test_sql_guid_functions.js]
 [test_tag_autocomplete_search.js]
 [test_tagging.js]
 [test_update_frecency_after_delete.js]
+# Bug 676989: test hangs consistently on Android
+skip-if = os == "android"
 [test_utils_backups_create.js]
 [test_utils_getURLsForContainerNode.js]
 [test_utils_setAnnotationsFor.js]
 [test_PlacesUtils_asyncGetBookmarkIds.js]
 [test_telemetry.js]
--- a/toolkit/components/satchel/test/unit/xpcshell.ini
+++ b/toolkit/components/satchel/test/unit/xpcshell.ini
@@ -1,14 +1,16 @@
 [DEFAULT]
 head = head_satchel.js
 tail = 
 
 [test_autocomplete.js]
 [test_bug_248970.js]
+# Bug 676989: test hangs on Android
+skip-if = os == "android"
 [test_db_corrupt.js]
 [test_db_update_v1.js]
 [test_db_update_v1b.js]
 [test_db_update_v2.js]
 [test_db_update_v2b.js]
 [test_db_update_v3.js]
 [test_db_update_v3b.js]
 [test_db_update_v999a.js]
--- a/toolkit/components/telemetry/tests/unit/xpcshell.ini
+++ b/toolkit/components/telemetry/tests/unit/xpcshell.ini
@@ -1,6 +1,8 @@
 [DEFAULT]
 head = 
 tail = 
 
 [test_nsITelemetry.js]
 [test_TelemetryPing.js]
+# Bug 676989: test fails consistently on Android
+# fail-if = os == "android"
--- a/toolkit/mozapps/extensions/XPIProvider.jsm
+++ b/toolkit/mozapps/extensions/XPIProvider.jsm
@@ -3456,32 +3456,36 @@ var XPIProvider = {
     this.bootstrappedAddons[aId] = {
       version: aVersion,
       descriptor: aFile.persistentDescriptor
     };
     this.addAddonsToCrashReporter();
 
     let principal = Cc["@mozilla.org/systemprincipal;1"].
                     createInstance(Ci.nsIPrincipal);
-    this.bootstrapScopes[aId] = new Components.utils.Sandbox(principal);
 
     if (!aFile.exists()) {
+      this.bootstrapScopes[aId] = new Components.utils.Sandbox(principal,
+                                                               {sandboxName: aFile.path});
       ERROR("Attempted to load bootstrap scope from missing directory " + bootstrap.path);
       return;
     }
 
+    let uri = getURIForResourceInFile(aFile, "bootstrap.js").spec;
+    this.bootstrapScopes[aId] = new Components.utils.Sandbox(principal,
+                                                             {sandboxName: uri});
+
     let loader = Cc["@mozilla.org/moz/jssubscript-loader;1"].
                  createInstance(Ci.mozIJSSubScriptLoader);
 
     try {
       // As we don't want our caller to control the JS version used for the
       // bootstrap file, we run loadSubScript within the context of the
       // sandbox with the latest JS version set explicitly.
-      this.bootstrapScopes[aId].__SCRIPT_URI_SPEC__ =
-          getURIForResourceInFile(aFile, "bootstrap.js").spec;
+      this.bootstrapScopes[aId].__SCRIPT_URI_SPEC__ = uri;
       Components.utils.evalInSandbox(
         "Components.classes['@mozilla.org/moz/jssubscript-loader;1'] \
                    .createInstance(Components.interfaces.mozIJSSubScriptLoader) \
                    .loadSubScript(__SCRIPT_URI_SPEC__);", this.bootstrapScopes[aId], "ECMAv5");
     }
     catch (e) {
       WARN("Error loading bootstrap.js for " + aId, e);
     }
--- a/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini
+++ b/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini
@@ -1,76 +1,142 @@
 [DEFAULT]
 head = head_addons.js
 tail = 
 
 [test_AddonRepository.js]
+# Bug 676992: test consistently hangs on Android
+skip-if = os == "android"
 [test_AddonRepository_cache.js]
+# Bug 676992: test consistently hangs on Android
+skip-if = os == "android"
 [test_LightweightThemeManager.js]
 [test_badschema.js]
 [test_blocklistchange.js]
+# Bug 676992: test consistently hangs on Android
+skip-if = os == "android"
 [test_bootstrap.js]
+# Bug 676992: test consistently hangs on Android
+skip-if = os == "android"
 [test_bug299716.js]
+# Bug 676992: test consistently hangs on Android
+skip-if = os == "android"
 [test_bug299716_2.js]
+# Bug 676992: test consistently hangs on Android
+skip-if = os == "android"
 [test_bug324121.js]
+# Bug 676992: test consistently hangs on Android
+skip-if = os == "android"
 [test_bug335238.js]
+# Bug 676992: test consistently hangs on Android
+skip-if = os == "android"
 [test_bug371495.js]
+# Bug 676992: test consistently hangs on Android
+skip-if = os == "android"
 [test_bug384052.js]
+# Bug 676992: test consistently hangs on Android
+skip-if = os == "android"
 [test_bug393285.js]
+# Bug 676992: test consistently hangs on Android
+skip-if = os == "android"
 [test_bug394300.js]
+# Bug 676992: test consistently hangs on Android
+skip-if = os == "android"
 [test_bug397778.js]
+# Bug 676992: test consistently hangs on Android
+skip-if = os == "android"
 [test_bug406118.js]
+# Bug 676992: test consistently hangs on Android
+skip-if = os == "android"
 [test_bug424262.js]
+# Bug 676992: test consistently hangs on Android
+skip-if = os == "android"
 [test_bug425657.js]
+# Bug 676992: test consistently hangs on Android
+skip-if = os == "android"
 [test_bug430120.js]
+# Bug 676992: test consistently hangs on Android
+skip-if = os == "android"
 [test_bug449027.js]
+# Bug 676992: test consistently hangs on Android
+skip-if = os == "android"
 [test_bug455906.js]
+# Bug 676992: test consistently hangs on Android
+skip-if = os == "android"
 [test_bug465190.js]
+# Bug 676992: test consistently hangs on Android
+skip-if = os == "android"
 [test_bug468528.js]
+# Bug 676992: test consistently hangs on Android
+skip-if = os == "android"
 [test_bug470377_1.js]
+# Bug 676992: test consistently hangs on Android
+skip-if = os == "android"
 [test_bug470377_2.js]
+# Bug 676992: test consistently hangs on Android
+skip-if = os == "android"
 [test_bug470377_3.js]
+# Bug 676992: test consistently hangs on Android
+skip-if = os == "android"
 [test_bug470377_4.js]
+# Bug 676992: test consistently hangs on Android
+skip-if = os == "android"
 [test_bug514327_1.js]
+# Bug 676992: test consistently hangs on Android
+skip-if = os == "android"
 [test_bug514327_2.js]
+# Bug 676992: test consistently hangs on Android
+skip-if = os == "android"
 [test_bug514327_3.js]
+# Bug 676992: test consistently hangs on Android
+skip-if = os == "android"
 [test_bug521905.js]
 [test_bug526598.js]
 [test_bug541420.js]
 [test_bug542391.js]
 [test_bug554133.js]
 [test_bug559800.js]
 [test_bug563256.js]
+# Bug 676992: test consistently fails on Android
+fail-if = os == "android"
 [test_bug564030.js]
 [test_bug566626.js]
 [test_bug567184.js]
 [test_bug569138.js]
 [test_bug570173.js]
 [test_bug576735.js]
 [test_bug578467.js]
 [test_bug587088.js]
 [test_bug594058.js]
 [test_bug595081.js]
 [test_bug595573.js]
 [test_bug596343.js]
 [test_bug596607.js]
 [test_bug616841.js]
+# Bug 676992: test consistently fails on Android
+fail-if = os == "android"
 [test_bug619730.js]
 [test_bug620837.js]
 [test_bug655254.js]
 [test_bug659772.js]
 [test_cacheflush.js]
 [test_checkcompatibility.js]
 [test_corrupt.js]
 [test_disable.js]
 [test_distribution.js]
 [test_dss.js]
+# Bug 676992: test consistently fails on Android
+fail-if = os == "android"
 [test_duplicateplugins.js]
+# Bug 676992: test consistently hangs on Android
+skip-if = os == "android"
 [test_error.js]
 [test_filepointer.js]
+# Bug 676992: test consistently hangs on Android
+skip-if = os == "android"
 [test_fuel.js]
 [test_general.js]
 [test_getresource.js]
 [test_gfxBlacklist_AllOS1.js]
 [test_gfxBlacklist_AllOS2.js]
 [test_gfxBlacklist_Device.js]
 [test_gfxBlacklist_DriverNew.js]
 [test_gfxBlacklist_Equal_DriverNew.js]
@@ -78,28 +144,44 @@ tail =
 [test_gfxBlacklist_Equal_OK.js]
 [test_gfxBlacklist_GTE_DriverOld.js]
 [test_gfxBlacklist_GTE_OK.js]
 [test_gfxBlacklist_OK.js]
 [test_gfxBlacklist_OS.js]
 [test_gfxBlacklist_Vendor.js]
 [test_gfxBlacklist_prefs.js]
 [test_install.js]
+# Bug 676992: test consistently hangs on Android
+skip-if = os == "android"
 [test_locale.js]
 [test_locked.js]
 [test_manifest.js]
 [test_migrate1.js]
 [test_migrate2.js]
 [test_migrate3.js]
 [test_permissions.js]
 [test_plugins.js]
+# Bug 676992: test consistently fails on Android
+fail-if = os == "android"
 [test_registry.js]
 [test_safemode.js]
 [test_startup.js]
+# Bug 676992: test consistently fails on Android
+fail-if = os == "android"
 [test_targetPlatforms.js]
 [test_theme.js]
+# Bug 676992: test consistently fails on Android
+fail-if = os == "android"
 [test_types.js]
 [test_uninstall.js]
 [test_update.js]
+# Bug 676992: test consistently hangs on Android
+skip-if = os == "android"
 [test_updatecheck.js]
+# Bug 676992: test consistently hangs on Android
+skip-if = os == "android"
 [test_updateid.js]
+# Bug 676992: test consistently hangs on Android
+skip-if = os == "android"
 [test_upgrade.js]
+# Bug 676992: test consistently hangs on Android
+skip-if = os == "android"
 
--- a/toolkit/mozapps/update/test_timermanager/unit/xpcshell.ini
+++ b/toolkit/mozapps/update/test_timermanager/unit/xpcshell.ini
@@ -1,5 +1,7 @@
 [DEFAULT]
 head = 
 tail = 
 
 [test_0010_timermanager.js]
+# Bug 676992: test consistently fails on Android
+fail-if = os == "android"
--- a/toolkit/xre/Makefile.in
+++ b/toolkit/xre/Makefile.in
@@ -97,16 +97,19 @@ CMMSRCS = nsNativeAppSupportCocoa.mm
 else
 ifeq ($(MOZ_WIDGET_TOOLKIT),os2)
 CPPSRCS += nsNativeAppSupportOS2.cpp
 else
 ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
 CPPSRCS += nsNativeAppSupportUnix.cpp
 else
 ifeq ($(MOZ_WIDGET_TOOLKIT),qt)
+MOCSRCS += moc_nsNativeAppSupportQt.cpp
+  $(NULL)
+CPPSRCS += $(MOCSRCS)
 CPPSRCS += nsNativeAppSupportQt.cpp
 CPPSRCS += nsQAppInstance.cpp
 EXPORTS += nsQAppInstance.h
 else
 CPPSRCS += nsNativeAppSupportDefault.cpp
 endif
 endif
 endif
--- a/toolkit/xre/nsNativeAppSupportQt.cpp
+++ b/toolkit/xre/nsNativeAppSupportQt.cpp
@@ -32,43 +32,102 @@
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include <stdlib.h>
-#include "nsNativeAppSupportBase.h"
-#include "nsString.h"
+#include <QTimer>
+#include "mozilla/ipc/GeckoChildProcessHost.h"
+#include "nsNativeAppSupportQt.h"
+#include "nsCOMPtr.h"
+#include "nsIObserverService.h"
+#include "mozilla/Services.h"
 
-#ifdef MOZ_ENABLE_LIBCONIC
-#include <glib-object.h>
-#endif
+#ifdef MOZ_ENABLE_QMSYSTEM2
+void
+nsNativeAppSupportQt::activityChanged(MeeGo::QmActivity::Activity activity)
+{
+    nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
+    if (!os)
+        return;
 
-#if (MOZ_PLATFORM_MAEMO == 5)
-#include <libosso.h>
-#endif
+    if (MeeGo::QmActivity::Inactive == activity) {
+        os->NotifyObservers(nsnull, "system-idle", nsnull);
+    } else {
+        os->NotifyObservers(nsnull, "system-active", nsnull);
+    }
+}
+
+void
+nsNativeAppSupportQt::displayStateChanged(MeeGo::QmDisplayState::DisplayState state)
+{
+    nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
+    if (!os)
+        return;
 
-class nsNativeAppSupportQt : public nsNativeAppSupportBase
+    switch (state) {
+    case MeeGo::QmDisplayState::On:
+        os->NotifyObservers(nsnull, "system-display-on", nsnull);
+        break;
+    case MeeGo::QmDisplayState::Off:
+        os->NotifyObservers(nsnull, "system-display-dimmed", nsnull);
+        break;
+    case MeeGo::QmDisplayState::Dimmed:
+        os->NotifyObservers(nsnull, "system-display-off", nsnull);
+        break;
+    default:
+        NS_WARNING("Unknown display state");
+        break;
+    }
+}
+
+void nsNativeAppSupportQt::deviceModeChanged(MeeGo::QmDeviceMode::DeviceMode mode)
 {
-public:
-  NS_IMETHOD Start(PRBool* aRetVal);
-  NS_IMETHOD Stop(PRBool* aResult);
-#if (MOZ_PLATFORM_MAEMO == 5)
-  // Osso context must be initialized for maemo5 otherwise we will be killed in ~20 seconds
-  osso_context_t *m_osso_context;
+    nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
+    if (!os)
+        return;
+
+    switch (mode) {
+    case MeeGo::QmDeviceMode::DeviceMode::Normal:
+        os->NotifyObservers(nsnull, "profile-change-net-restore", nsnull);
+        break;
+    case MeeGo::QmDeviceMode::DeviceMode::Flight:
+        os->NotifyObservers(nsnull, "profile-change-net-teardown", nsnull);
+        break;
+    case MeeGo::QmDeviceMode::DeviceMode::Error:
+    default:
+        NS_WARNING("Unknown DeviceMode");
+        break;
+    }
+}
+
+void nsNativeAppSupportQt::RefreshStates()
+{
+  activityChanged(mActivity.get());
+  displayStateChanged(mDisplayState.get());
+  deviceModeChanged(mDeviceMode.getMode());
+}
 #endif
-};
 
 NS_IMETHODIMP
 nsNativeAppSupportQt::Start(PRBool* aRetVal)
 {
   NS_ASSERTION(gAppData, "gAppData must not be null.");
 
+#ifdef MOZ_ENABLE_QMSYSTEM2
+  connect(&mActivity, SIGNAL(activityChanged(MeeGo::QmActivity::Activity)), this, SLOT(activityChanged(MeeGo::QmActivity::Activity)));
+  connect(&mDeviceMode, SIGNAL(deviceModeChanged(MeeGo::QmDeviceMode::DeviceMode)), this, SLOT(deviceModeChanged(MeeGo::QmDeviceMode::DeviceMode)));
+  connect(&mDisplayState, SIGNAL(displayStateChanged(MeeGo::QmDisplayState::DisplayState)), this, SLOT(displayStateChanged(MeeGo::QmDisplayState::DisplayState)));
+  // Init states withing next event loop iteration
+  QTimer::singleShot(0, this, SLOT(RefreshStates()));
+#endif
+
   *aRetVal = PR_TRUE;
 #ifdef MOZ_ENABLE_LIBCONIC
   g_type_init();
 #endif
 
 #if (MOZ_PLATFORM_MAEMO == 5)
   /* Initialize maemo application
 
new file mode 100644
--- /dev/null
+++ b/toolkit/xre/nsNativeAppSupportQt.h
@@ -0,0 +1,80 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 et sw=2 tw=80: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Corporation code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Oleg Romashin <romaxa@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include <stdlib.h>
+#include <QObject>
+#ifdef MOZ_ENABLE_QMSYSTEM2
+#include "qmdevicemode.h"
+#include "qmdisplaystate.h"
+#include "qmactivity.h"
+#endif
+#include "nsNativeAppSupportBase.h"
+#include "nsString.h"
+
+#ifdef MOZ_ENABLE_LIBCONIC
+#include <glib-object.h>
+#endif
+
+#if (MOZ_PLATFORM_MAEMO == 5)
+#include <libosso.h>
+#endif
+
+class nsNativeAppSupportQt : public QObject, public nsNativeAppSupportBase
+{
+  Q_OBJECT
+public:
+  NS_IMETHOD Start(PRBool* aRetVal);
+  NS_IMETHOD Stop(PRBool* aResult);
+#if (MOZ_PLATFORM_MAEMO == 5)
+  // Osso context must be initialized for maemo5 otherwise we will be killed in ~20 seconds
+  osso_context_t *m_osso_context;
+#endif
+#ifdef MOZ_ENABLE_QMSYSTEM2
+public Q_SLOTS:
+  void activityChanged(MeeGo::QmActivity::Activity activity);
+  void deviceModeChanged(MeeGo::QmDeviceMode::DeviceMode mode);
+  void displayStateChanged(MeeGo::QmDisplayState::DisplayState state);
+  void RefreshStates();
+
+private:
+  MeeGo::QmDeviceMode mDeviceMode;
+  MeeGo::QmDisplayState mDisplayState;
+  MeeGo::QmActivity mActivity;
+#endif
+};
+
--- a/uriloader/exthandler/tests/unit/xpcshell.ini
+++ b/uriloader/exthandler/tests/unit/xpcshell.ini
@@ -1,8 +1,10 @@
 [DEFAULT]
 head = head_handlerService.js
 tail = tail_handlerService.js
 
 [test_getTypeFromExtension_ext_to_type_mapping.js]
 [test_getTypeFromExtension_with_empty_Content_Type.js]
 [test_handlerService.js]
+# Bug 676997: test consistently fails on Android
+fail-if = os == "android"
 [test_punycodeURIs.js]
--- a/uriloader/exthandler/tests/unit_ipc/xpcshell.ini
+++ b/uriloader/exthandler/tests/unit_ipc/xpcshell.ini
@@ -1,5 +1,7 @@
 [DEFAULT]
 head = 
 tail = 
 
 [test_encoding.js]
+# Bug 676995: test hangs consistently on Android
+skip-if = os == "android"
--- a/widget/src/android/AndroidJavaWrappers.h
+++ b/widget/src/android/AndroidJavaWrappers.h
@@ -487,16 +487,17 @@ public:
         ACTIVITY_STOPPING = 9,
         ACTIVITY_PAUSING = 10,
         ACTIVITY_SHUTDOWN = 11,
         LOAD_URI = 12,
         SURFACE_CREATED = 13,
         SURFACE_DESTROYED = 14,
         GECKO_EVENT_SYNC = 15,
         FORCED_RESIZE = 16,
+        ACTIVITY_START = 17,
         dummy_java_enum_list_end
     };
 
     enum {
         IME_COMPOSITION_END = 0,
         IME_COMPOSITION_BEGIN = 1,
         IME_SET_TEXT = 2,
         IME_GET_TEXT = 3,
--- a/widget/src/android/nsAppShell.cpp
+++ b/widget/src/android/nsAppShell.cpp
@@ -323,16 +323,17 @@ nsAppShell::ProcessNextNativeEvent(PRBoo
         break;
     }
 
     case AndroidGeckoEvent::ACTIVITY_STOPPING: {
         nsCOMPtr<nsIObserverService> obsServ =
             mozilla::services::GetObserverService();
         NS_NAMED_LITERAL_STRING(minimize, "heap-minimize");
         obsServ->NotifyObservers(nsnull, "memory-pressure", minimize.get());
+        obsServ->NotifyObservers(nsnull, "application-background", nsnull);
 
         break;
     }
 
     case AndroidGeckoEvent::ACTIVITY_SHUTDOWN: {
         nsCOMPtr<nsIObserverService> obsServ =
             mozilla::services::GetObserverService();
         NS_NAMED_LITERAL_STRING(context, "shutdown-persist");
@@ -354,16 +355,24 @@ nsAppShell::ProcessNextNativeEvent(PRBoo
         nsIPrefService* prefs = Preferences::GetService();
         if (prefs) {
             prefs->SavePrefFile(nsnull);
         }
 
         break;
     }
 
+    case AndroidGeckoEvent::ACTIVITY_START: {
+        nsCOMPtr<nsIObserverService> obsServ =
+            mozilla::services::GetObserverService();
+        obsServ->NotifyObservers(nsnull, "application-foreground", nsnull);
+
+        break;
+    }
+
     case AndroidGeckoEvent::LOAD_URI: {
         nsCOMPtr<nsICommandLineRunner> cmdline
             (do_CreateInstance("@mozilla.org/toolkit/command-line;1"));
         if (!cmdline)
             break;
 
         char *uri = ToNewUTF8String(curEvent->Characters());
         if (!uri)
--- a/widget/src/qt/mozqwidget.h
+++ b/widget/src/qt/mozqwidget.h
@@ -316,25 +316,41 @@ private:
 
 /**
   This is a helper class to synchronize the MWindow window with
   its contained QGraphicsWidget for things like resizing and closing
   by the user.
 */
 class MozMGraphicsView : public MWindow
 {
-
+    Q_OBJECT
 public:
     MozMGraphicsView(MozQWidget* aTopLevel, QWidget* aParent = nsnull)
      : MWindow(aParent)
      , mEventHandler(this)
      , mTopLevelWidget(aTopLevel)
     {
         MozMSceneWindow* page = new MozMSceneWindow(aTopLevel);
         page->appear(this);
+        QObject::connect(this, SIGNAL(switcherEntered()), this, SLOT(onSwitcherEntered()));
+        QObject::connect(this, SIGNAL(switcherExited()), this, SLOT(onSwitcherExited()));
+    }
+
+public Q_SLOTS:
+    void onSwitcherEntered() {
+        nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
+        if (!os)
+            return;
+        os->NotifyObservers(nsnull, "application-background", nsnull);
+    }
+    void onSwitcherExited() {
+        nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
+        if (!os)
+            return;
+        os->NotifyObservers(nsnull, "application-foreground", nsnull);
     }
 
 protected:
     virtual bool event(QEvent* aEvent) {
         mEventHandler.handleEvent(aEvent, mTopLevelWidget);
         return MWindow::event(aEvent);
     }
 
--- a/xpcom/tests/unit/xpcshell.ini
+++ b/xpcom/tests/unit/xpcshell.ini
@@ -1,32 +1,42 @@
 [DEFAULT]
 head = head_xpcom.js
 tail = 
 
 [test_bug121341.js]
 [test_bug332389.js]
 [test_bug333505.js]
 [test_bug364285-1.js]
+# Bug 676998: test fails consistently on Android
+fail-if = os == "android"
 [test_bug374754.js]
 [test_bug476919.js]
+# Bug 676998: test fails consistently on Android
+fail-if = os == "android"
 [test_bug478086.js]
 [test_bug656331.js]
 [test_compmgr_warnings.js]
 [test_file_createUnique.js]
 [test_file_equality.js]
 [test_hidden_files.js]
 [test_home.js]
+# Bug 676998: test fails consistently on Android
+fail-if = os == "android"
 [test_iniProcessor.js]
 [test_ioutil.js]
 [test_localfile.js]
 [test_mac_bundle.js]
 [test_nsIMutableArray.js]
 [test_nsIProcess.js]
 [test_nsIProcess_stress.js]
 skip-if = os == "win" # See bug: 676412
 [test_pipe.js]
 [test_storagestream.js]
 [test_streams.js]
 [test_stringstream.js]
 [test_symlinks.js]
+# Bug 676998: test fails consistently on Android
+fail-if = os == "android"
 [test_systemInfo.js]
+# Bug 676998: test fails consistently on Android
+fail-if = os == "android"
 [test_versioncomparator.js]