Merge m-c to inbound.
authorRyan VanderMeulen <ryanvm@gmail.com>
Mon, 06 May 2013 11:20:45 -0400
changeset 130979 b842d26dd5f0b8a0777adbb48e7a852abcdcd3ab
parent 130968 9fedd4a2170e9d28dec4863729fe4b9d1a60a7c6 (current diff)
parent 130978 c50f597b1e6afc8291d52f15c4d31d56cf12beb5 (diff)
child 130980 f51b726ef31dfba6fb2e865e34c0424fbdc2aa50
child 131062 8922af45886ec5c41b9f2cb8e77a61ab55b58315
child 131074 9ab1dc62148c1a9146d4cdedc2ac339ec629c373
child 155307 d596461354b268b8048d510e63d28898fdbf99d4
push id27611
push userryanvm@gmail.com
push dateMon, 06 May 2013 15:20:52 +0000
treeherdermozilla-inbound@b842d26dd5f0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone23.0a1
first release with
nightly linux32
b842d26dd5f0 / 23.0a1 / 20130507030948 / files
nightly linux64
b842d26dd5f0 / 23.0a1 / 20130507030948 / files
nightly mac
b842d26dd5f0 / 23.0a1 / 20130507030948 / files
nightly win32
b842d26dd5f0 / 23.0a1 / 20130507030948 / files
nightly win64
b842d26dd5f0 / 23.0a1 / 20130507030948 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge m-c to inbound.
--- a/b2g/app/Makefile.in
+++ b/b2g/app/Makefile.in
@@ -151,14 +151,18 @@ ifndef SKIP_COPY_XULRUNNER
 ifdef LIBXUL_SDK
 	$(NSINSTALL) -D $(DIST)/bin/xulrunner
 	(cd $(LIBXUL_SDK)/bin && tar $(TAR_CREATE_FLAGS) - .) | (cd $(DIST)/bin/xulrunner && tar -xf -)
 endif
 endif # SKIP_COPY_XULRUNNER
 
 	$(NSINSTALL) -D $(DIST)/bin/chrome/icons/default
 
+# Copy the app icon for b2g-desktop
 ifeq ($(OS_ARCH),WINNT)
 	cp $(srcdir)/$(APP_ICON).ico $(DIST)/bin/chrome/icons/default/$(APP_ICON).ico
 	$(REDIT_PATH)/redit$(HOST_BIN_SUFFIX) $(DIST)/bin/$(APP_BINARY) $(srcdir)/$(APP_ICON).ico
+	cp $(srcdir)/$(APP_ICON).ico $(DIST)/bin/chrome/icons/default/default.ico
+else ifneq (gonk,$(MOZ_WIDGET_TOOLKIT))
+	cp $(srcdir)/default.png $(DIST)/bin/chrome/icons/default/default.png
 endif
 
 endif
index 38312abac42830818edef700470cf1c59b25bb81..5d4a61dc92ba5b08b2ff0587fb2877e7007c940e
GIT binary patch
literal 4286
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
E1?Jf~jsO4v
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -376,17 +376,16 @@ pref("dom.mozBrowserFramesEnabled", true
 // We'll run out of PIDs on UNIX-y systems before we hit this limit.
 pref("dom.ipc.processCount", 100000);
 
 pref("dom.ipc.browser_frames.oop_by_default", false);
 
 // Temporary permission hack for WebSMS
 pref("dom.sms.enabled", true);
 pref("dom.sms.strict7BitEncoding", false); // Disabled by default.
-pref("dom.sms.requestStatusReport", false); // Disabled by default.
 
 // Temporary permission hack for WebContacts
 pref("dom.mozContacts.enabled", true);
 
 // WebAlarms
 pref("dom.mozAlarms.enabled", true);
 
 // SimplePush
new file mode 100644
index 0000000000000000000000000000000000000000..c4307fc8418436bb6b2fd3a6afc702c2db28aa77
GIT binary patch
literal 4762
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
--- a/b2g/chrome/content/dbg-webapps-actors.js
+++ b/b2g/chrome/content/dbg-webapps-actors.js
@@ -3,16 +3,22 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 let Cu = Components.utils;
 let Cc = Components.classes;
 let Ci = Components.interfaces;
 
+Cu.import("resource://gre/modules/Webapps.jsm");
+Cu.import("resource://gre/modules/AppsUtils.jsm");
+Cu.import("resource://gre/modules/FileUtils.jsm");
+Cu.import('resource://gre/modules/Services.jsm');
+Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js");
+
 function debug(aMsg) {
   /*
   Cc["@mozilla.org/consoleservice;1"]
     .getService(Ci.nsIConsoleService)
     .logStringMessage("--*-- WebappsActor : " + aMsg);
   */
 }
 
@@ -27,16 +33,17 @@ function debug(aMsg) {
  * install apps.
  */
 function WebappsActor(aConnection) { debug("init"); }
 
 WebappsActor.prototype = {
   actorPrefix: "webapps",
 
   _registerApp: function wa_actorRegisterApp(aApp, aId, aDir) {
+    debug("registerApp");
     let reg = DOMApplicationRegistry;
     let self = this;
 
     aApp.installTime = Date.now();
     aApp.installState = "installed";
     aApp.removable = true;
     aApp.id = aId;
     aApp.basePath = FileUtils.getDir(DIRECTORY_NAME, ["webapps"], true).path;
@@ -44,18 +51,22 @@ WebappsActor.prototype = {
                                         : reg._nextLocalId();
 
     reg.webapps[aId] = aApp;
     reg.updatePermissionsForApp(aId);
 
     reg._readManifests([{ id: aId }], function(aResult) {
       let manifest = aResult[0].manifest;
       aApp.name = manifest.name;
-      reg._registerSystemMessages(manifest, aApp);
-      reg._registerActivities(manifest, aApp, true);
+      if ("_registerSystemMessages" in reg) {
+        reg._registerSystemMessages(manifest, aApp);
+      }
+      if ("_registerActivities" in reg) {
+        reg._registerActivities(manifest, aApp, true);
+      }
       reg._saveApps(function() {
         aApp.manifest = manifest;
         reg.broadcastMessage("Webapps:AddApp", { id: aId, app: aApp });
         reg.broadcastMessage("Webapps:Install:Return:OK",
                              { app: aApp,
                                oid: "foo",
                                requestID: "bar"
                              });
@@ -232,20 +243,16 @@ WebappsActor.prototype = {
     * @param appId   : The id of the app we want to install. We will look for
     *                  the files for the app in $TMP/b2g/$appId :
     *                  For packaged apps: application.zip
     *                  For hosted apps:   metadata.json and manifest.webapp
     */
   install: function wa_actorInstall(aRequest) {
     debug("install");
 
-    Cu.import("resource://gre/modules/Webapps.jsm");
-    Cu.import("resource://gre/modules/AppsUtils.jsm");
-    Cu.import("resource://gre/modules/FileUtils.jsm");
-
     let appId = aRequest.appId;
     if (!appId) {
       return { error: "missingParameter",
                message: "missing parameter appId" }
     }
 
     // Check that we are not overriding a preinstalled application.
     let reg = DOMApplicationRegistry;
@@ -284,19 +291,105 @@ WebappsActor.prototype = {
         return { error: "badParameterType",
                  message: "hosted app file is missing" }
       }
 
       this.installHostedApp(appDir, appId);
     }
 
     return { appId: appId, path: appDir.path }
+  },
+
+  getAll: function wa_actorGetAll(aRequest) {
+    debug("getAll");
+
+    let defer = Promise.defer();
+    let reg = DOMApplicationRegistry;
+    reg.getAll(function onsuccess(apps) {
+      defer.resolve({ apps: apps });
+    });
+
+    return defer.promise;
+  },
+
+  uninstall: function wa_actorUninstall(aRequest) {
+    debug("uninstall");
+
+    let manifestURL = aRequest.manifestURL;
+    if (!manifestURL) {
+      return { error: "missingParameter",
+               message: "missing parameter manifestURL" };
+    }
+
+    let defer = Promise.defer();
+    let reg = DOMApplicationRegistry;
+    reg.uninstall(
+      manifestURL,
+      function onsuccess() {
+        defer.resolve({});
+      },
+      function onfailure(reason) {
+        defer.resolve({ error: reason });
+      }
+    );
+
+    return defer.promise;
+  },
+
+  launch: function wa_actorLaunch(aRequest) {
+    debug("launch");
+
+    let manifestURL = aRequest.manifestURL;
+    if (!manifestURL) {
+      return { error: "missingParameter",
+               message: "missing parameter manifestURL" };
+    }
+
+    let defer = Promise.defer();
+    let reg = DOMApplicationRegistry;
+    reg.launch(
+      aRequest.manifestURL,
+      aRequest.startPoint || "",
+      function onsuccess() {
+        defer.resolve({});
+      },
+      function onfailure(reason) {
+        defer.resolve({ error: reason });
+      });
+
+    return defer.promise;
+  },
+
+  close: function wa_actorLaunch(aRequest) {
+    debug("close");
+
+    let manifestURL = aRequest.manifestURL;
+    if (!manifestURL) {
+      return { error: "missingParameter",
+               message: "missing parameter manifestURL" };
+    }
+
+    let reg = DOMApplicationRegistry;
+    let app = reg.getAppByManifestURL(manifestURL);
+    if (!app) {
+      return { error: "missingParameter",
+               message: "No application for " + manifestURL };
+    }
+
+    reg.close(app);
+
+    return {};
   }
 };
 
 /**
  * The request types this actor can handle.
  */
 WebappsActor.prototype.requestTypes = {
-  "install": WebappsActor.prototype.install
+  "install": WebappsActor.prototype.install,
+  "getAll": WebappsActor.prototype.getAll,
+  "launch": WebappsActor.prototype.launch,
+  "close": WebappsActor.prototype.close,
+  "uninstall": WebappsActor.prototype.uninstall
 };
 
 DebuggerServer.addGlobalActor(WebappsActor, "webappsActor");
+
--- a/b2g/chrome/content/settings.js
+++ b/b2g/chrome/content/settings.js
@@ -159,21 +159,16 @@ SettingsListener.observe('language.curre
     function(value) {
       Services.prefs.setCharPref('dom.mms.retrieval_mode', value);
   });
 
   SettingsListener.observe('ril.sms.strict7BitEncoding.enabled', false,
     function(value) {
       Services.prefs.setBoolPref('dom.sms.strict7BitEncoding', value);
   });
-
-  SettingsListener.observe('ril.sms.requestStatusReport.enabled', false,
-    function(value) {
-      Services.prefs.setBoolPref('dom.sms.requestStatusReport', value);
-  });
 })();
 
 //=================== DeviceInfo ====================
 Components.utils.import('resource://gre/modules/XPCOMUtils.jsm');
 Components.utils.import('resource://gre/modules/ctypes.jsm');
 (function DeviceInfoToSettings() {
   XPCOMUtils.defineLazyServiceGetter(this, 'gSettingsService',
                                      '@mozilla.org/settingsService;1',
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -871,16 +871,17 @@ var AlertsHelper = {
 
 var WebappsHelper = {
   _installers: {},
   _count: 0,
 
   init: function webapps_init() {
     Services.obs.addObserver(this, "webapps-launch", false);
     Services.obs.addObserver(this, "webapps-ask-install", false);
+    Services.obs.addObserver(this, "webapps-close", false);
   },
 
   registerInstaller: function webapps_registerInstaller(data) {
     let id = "installer" + this._count++;
     this._installers[id] = data;
     return id;
   },
 
@@ -922,16 +923,22 @@ var WebappsHelper = {
       case "webapps-ask-install":
         let id = this.registerInstaller(json);
         shell.sendChromeEvent({
           type: "webapps-ask-install",
           id: id,
           app: json.app
         });
         break;
+      case "webapps-close":
+        shell.sendChromeEvent({
+          "type": "webapps-close",
+          "manifestURL": json.manifestURL
+        });
+        break;
     }
   }
 }
 
 let IndexedDBPromptHelper = {
   _quotaPrompt: "indexedDB-quota-prompt",
   _quotaResponse: "indexedDB-quota-response",
 
--- a/b2g/components/SignInToWebsite.jsm
+++ b/b2g/components/SignInToWebsite.jsm
@@ -79,16 +79,28 @@ Cu.import("resource://gre/modules/XPCOMU
 Cu.import("resource://gre/modules/identity/IdentityUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "IdentityService",
                                   "resource://gre/modules/identity/MinimalIdentity.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "Logger",
                                   "resource://gre/modules/identity/LogUtils.jsm");
 
+// The default persona uri; can be overwritten with toolkit.identity.uri pref.
+// Do this if you want to repoint to a different service for testing.
+// There's no point in setting up an observer to monitor the pref, as b2g prefs
+// can only be overwritten when the profie is recreated.  So just get the value
+// on start-up.
+let kPersonaUri = "https://firefoxos.persona.org";
+try {
+  kPersonaUri = Services.prefs.getCharPref("toolkit.identity.uri");
+} catch(noSuchPref) {
+  // stick with the default value
+}
+
 // JS shim that contains the callback functions that
 // live within the identity UI provisioning frame.
 const kIdentityShimFile = "chrome://browser/content/identity.js";
 
 // Type of MozChromeEvents to handle id dialogs.
 const kOpenIdentityDialog = "id-dialog-open";
 const kDoneIdentityDialog = "id-dialog-done";
 const kCloseIdentityDialog = "id-dialog-close-iframe";
@@ -101,32 +113,35 @@ const kIdentityDelegateFinished = "ident
 const kIdentityDelegateReady = "identity-delegate-ready";
 
 const kIdentityControllerDoMethod = "identity-controller-doMethod";
 
 function log(...aMessageArgs) {
   Logger.log.apply(Logger, ["SignInToWebsiteController"].concat(aMessageArgs));
 }
 
+log("persona uri =", kPersonaUri);
+
 /*
  * ContentInterface encapsulates the our content functions.  There are only two:
  *
  * getContent       - return the current content window
  * sendChromeEvent  - send a chromeEvent from the browser shell
  */
 let ContentInterface = {
   _getBrowser: function SignInToWebsiteController__getBrowser() {
     return Services.wm.getMostRecentWindow("navigator:browser");
   },
 
   getContent: function SignInToWebsiteController_getContent() {
     return this._getBrowser().getContentWindow();
   },
 
   sendChromeEvent: function SignInToWebsiteController_sendChromeEvent(detail) {
+    detail.uri = kPersonaUri;
     this._getBrowser().shell.sendChromeEvent(detail);
   }
 };
 
 function Pipe() {
   this._watchers = [];
 }
 
@@ -266,19 +281,19 @@ Pipe.prototype = {
             // the callbacks in the content script.  This could be either the
             // visible popup that the user interacts with, or it could be an
             // invisible frame.
             let frame = evt.detail.frame;
             let frameLoader = frame.QueryInterface(Ci.nsIFrameLoaderOwner).frameLoader;
             mm = frameLoader.messageManager;
             try {
               mm.loadFrameScript(kIdentityShimFile, true);
-              log("Loaded shim " + kIdentityShimFile + "\n");
+              log("Loaded shim", kIdentityShimFile);
             } catch (e) {
-              log("Error loading ", kIdentityShimFile, " as a frame script: ", e);
+              log("Error loading", kIdentityShimFile, "as a frame script:", e);
             }
 
             // There are two messages that the delegate can send back: a "do
             // method" event, and a "finished" event.  We pass the do-method
             // events straight to the caller for interpretation and handling.
             // If we receive a "finished" event, then the delegate is done, so
             // we shut down the pipe and clean up.
             mm.addMessageListener(kIdentityControllerDoMethod, aMessageCallback);
--- a/content/html/content/test/forms/test_input_typing_sanitization.html
+++ b/content/html/content/test/forms/test_input_typing_sanitization.html
@@ -89,17 +89,17 @@ function checkValueSubmittedIsInvalid()
     submitMethod = sendKeyEventToSubmitForm;
     submitFrame.onload = checkValueSubmittedIsValid;
     testData = gValidData;
   }
   testSubmissions();
 }
 
 function testSubmissions() {
-  SpecialPowers.focus(input);
+  input.focus();
   sendString(testData[valueIndex]);
   submitMethod();
 }
 
 var valueIndex = 0;
 var submitMethod = submitForm;
 
 SimpleTest.waitForExplicitFinish();
@@ -181,25 +181,25 @@ function runTest()
     }
 
     input.type = test.type;
     gValidData = test.validData;
     gInvalidData = test.invalidData;
 
     for (data of gValidData) {
       input.value = "";
-      SpecialPowers.focus(input);
+      input.focus();
       sendString(data);
       input.blur();
       is(input.value, data, "valid user input should not be sanitized");
     }
 
     for (data of gInvalidData) {
       input.value = "";
-      SpecialPowers.focus(input);
+      input.focus();
       sendString(data);
       input.blur();
       is(input.value, "", "invalid user input should be sanitized");
     }
 
     input.value = '';
 
     testData = gValidData;
--- a/content/media/omx/OmxDecoder.cpp
+++ b/content/media/omx/OmxDecoder.cpp
@@ -7,16 +7,17 @@
 #include <fcntl.h>
 
 #include "base/basictypes.h"
 #include <cutils/properties.h>
 #include <stagefright/MediaExtractor.h>
 #include <stagefright/MetaData.h>
 #include <stagefright/OMXClient.h>
 #include <stagefright/OMXCodec.h>
+#include <OMX.h>
 
 #include "mozilla/Preferences.h"
 #include "mozilla/Types.h"
 #include "MPAPI.h"
 #include "prlog.h"
 
 #include "GonkNativeWindow.h"
 #include "GonkNativeWindowClient.h"
@@ -166,16 +167,24 @@ public:
   AutoStopMediaSource(const sp<MediaSource>& aMediaSource) : mMediaSource(aMediaSource) {
   }
 
   ~AutoStopMediaSource() {
     mMediaSource->stop();
   }
 };
 
+static sp<IOMX> sOMX = nullptr;
+static sp<IOMX> GetOMX() {
+  if(sOMX.get() == nullptr) {
+    sOMX = new OMX;
+    }
+  return sOMX;
+}
+
 bool OmxDecoder::Init() {
 #ifdef PR_LOGGING
   if (!gOmxDecoderLog) {
     gOmxDecoderLog = PR_NewLogModule("OmxDecoder");
   }
 #endif
 
   //register sniffers, if they are not registered in this process.
@@ -292,24 +301,38 @@ bool OmxDecoder::Init() {
 
   sp<MediaSource> audioTrack;
   sp<MediaSource> audioSource;
   if (audioTrackIndex != -1 && (audioTrack = extractor->getTrack(audioTrackIndex)) != nullptr)
   {
     if (!strcasecmp(audioMime, "audio/raw")) {
       audioSource = audioTrack;
     } else {
+      // try to load hardware codec in mediaserver process.
+      int flags = kHardwareCodecsOnly;
       audioSource = OMXCodec::Create(omx,
                                      audioTrack->getFormat(),
                                      false, // decoder
-                                     audioTrack);
+                                     audioTrack,
+                                     nullptr,
+                                     flags);
     }
     if (audioSource == nullptr) {
-      NS_WARNING("Couldn't create OMX audio source");
-      return false;
+      // try to load software codec in this process.
+      int flags = kSoftwareCodecsOnly;
+      audioSource = OMXCodec::Create(GetOMX(),
+                                     audioTrack->getFormat(),
+                                     false, // decoder
+                                     audioTrack,
+                                     nullptr,
+                                     flags);
+      if (audioSource == nullptr) {
+        NS_WARNING("Couldn't create OMX audio source");
+        return false;
+      }
     }
     if (audioSource->start() != OK) {
       NS_WARNING("Couldn't start OMX audio source");
       return false;
     }
 
     int64_t durationUs;
     if (audioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
--- a/dom/apps/src/Webapps.js
+++ b/dom/apps/src/Webapps.js
@@ -682,16 +682,17 @@ WebappsApplicationMgmt.prototype = {
     cpmm.sendAsyncMessage("Webapps:ApplyDownload",
                           { manifestURL: aApp.manifestURL });
   },
 
   uninstall: function(aApp) {
     dump("-- webapps.js uninstall " + aApp.manifestURL + "\n");
     let request = this.createRequest();
     cpmm.sendAsyncMessage("Webapps:Uninstall", { origin: aApp.origin,
+                                                 manifestURL: aApp.manifestURL,
                                                  oid: this._id,
                                                  requestID: this.getRequestId(request) });
     return request;
   },
 
   getAll: function() {
     let request = this.createRequest();
     cpmm.sendAsyncMessage("Webapps:GetAll", { oid: this._id,
--- a/dom/apps/src/Webapps.jsm
+++ b/dom/apps/src/Webapps.jsm
@@ -815,32 +815,32 @@ this.DOMApplicationRegistry = {
     switch (aMessage.name) {
       case "Webapps:Install":
         this.doInstall(msg, mm);
         break;
       case "Webapps:GetSelf":
         this.getSelf(msg, mm);
         break;
       case "Webapps:Uninstall":
-        this.uninstall(msg, mm);
+        this.doUninstall(msg, mm);
         break;
       case "Webapps:Launch":
-        this.launchApp(msg, mm);
+        this.doLaunch(msg, mm);
         break;
       case "Webapps:CheckInstalled":
         this.checkInstalled(msg, mm);
         break;
       case "Webapps:GetInstalled":
         this.getInstalled(msg, mm);
         break;
       case "Webapps:GetNotInstalled":
         this.getNotInstalled(msg, mm);
         break;
       case "Webapps:GetAll":
-        this.getAll(msg, mm);
+        this.doGetAll(msg, mm);
         break;
       case "Webapps:InstallPackage":
         this.doInstallPackage(msg, mm);
         break;
       case "Webapps:RegisterForMessages":
         this.addMessageListener(msg, mm);
         break;
       case "Webapps:UnregisterForMessages":
@@ -912,31 +912,58 @@ this.DOMApplicationRegistry = {
     // Asynchronously copy the data to the file.
     let istream = converter.convertToInputStream(aData);
     NetUtil.asyncCopy(istream, ostream, function(rc) {
       if (aCallbak)
         aCallbak();
     });
   },
 
-  launchApp: function launchApp(aData, aMm) {
-    let app = this.getAppByManifestURL(aData.manifestURL);
+  doLaunch: function (aData, aMm) {
+    this.launch(
+      aData.manifestURL,
+      aData.startPoint,
+      function onsuccess() {
+        aMm.sendAsyncMessage("Webapps:Launch:Return:OK", aData);
+      },
+      function onfailure(reason) {
+        aMm.sendAsyncMessage("Webapps:Launch:Return:KO", aData);
+      }
+    );
+  },
+
+  launch: function launch(aManifestURL, aStartPoint, aOnSuccess, aOnFailure) {
+    let app = this.getAppByManifestURL(aManifestURL);
     if (!app) {
-      aMm.sendAsyncMessage("Webapps:Launch:Return:KO", aData);
+      aOnFailure("NO_SUCH_APP");
       return;
     }
 
     // Fire an error when trying to launch an app that is not
     // yet fully installed.
     if (app.installState == "pending") {
-      aMm.sendAsyncMessage("Webapps:Launch:Return:KO", aData);
+      aOnFailure("PENDING_APP_NOT_LAUNCHABLE");
       return;
     }
 
-    Services.obs.notifyObservers(aMm, "webapps-launch", JSON.stringify(aData));
+    // We have to clone the app object as nsIDOMApplication objects are
+    // stringified as an empty object. (see bug 830376)
+    let appClone = AppsUtils.cloneAppObject(app);
+    appClone.startPoint = aStartPoint;
+    Services.obs.notifyObservers(null, "webapps-launch", JSON.stringify(appClone));
+    aOnSuccess();
+  },
+
+  close: function close(aApp) {
+    debug("close");
+
+    // We have to clone the app object as nsIDOMApplication objects are
+    // stringified as an empty object. (see bug 830376)
+    let appClone = AppsUtils.cloneAppObject(aApp);
+    Services.obs.notifyObservers(null, "webapps-close", JSON.stringify(appClone));
   },
 
   cancelDownload: function cancelDownload(aManifestURL, aError) {
     debug("cancelDownload " + aManifestURL);
     let error = aError || "DOWNLOAD_CANCELED";
     let download = AppDownloadManager.get(aManifestURL);
     if (!download) {
       debug("Could not find a download for " + aManifestURL);
@@ -2521,77 +2548,89 @@ this.DOMApplicationRegistry = {
         // If disk space information isn't available, we'll end up here.
         // We should either proceed anyway, otherwise devices that support neither
         // deviceStorage nor diskSpaceAvailable will never be able to install packaged apps.
         download();
       }
     }
   },
 
-  uninstall: function(aData, aMm) {
-    debug("uninstall " + aData.origin);
-    for (let id in this.webapps) {
-      let app = this.webapps[id];
-      if (app.origin != aData.origin) {
-        continue;
-      }
-
-      dump("-- webapps.js uninstall " + app.manifestURL + "\n");
-
-      if (!app.removable) {
-        debug("Error: cannot unintall a non-removable app.");
-        break;
-      }
-
-      // Check if we are downloading something for this app, and cancel the
-      // download if needed.
-      this.cancelDownload(app.manifestURL);
-
-      // Clean up the deprecated manifest cache if needed.
-      if (id in this._manifestCache) {
-        delete this._manifestCache[id];
+  doUninstall: function(aData, aMm) {
+    this.uninstall(aData.manifestURL,
+      function onsuccess() {
+        aMm.sendAsyncMessage("Webapps:Uninstall:Return:OK", aData);
+      },
+      function onfailure() {
+        // Fall-through, fails to uninstall the desired app because:
+        //   - we cannot find the app to be uninstalled.
+        //   - the app to be uninstalled is not removable.
+        aMm.sendAsyncMessage("Webapps:Uninstall:Return:KO", aData);
       }
-
-      // Clear private data first.
-      this._clearPrivateData(app.localId, false);
-
-      // Then notify observers.
-      Services.obs.notifyObservers(aMm, "webapps-uninstall", JSON.stringify(aData));
-
-      let appNote = JSON.stringify(AppsUtils.cloneAppObject(app));
-      appNote.id = id;
-
-      if (supportSystemMessages()) {
-        this._readManifests([{ id: id }], (function unregisterManifest(aResult) {
-          this._unregisterActivities(aResult[0].manifest, app);
-        }).bind(this));
-      }
-
-      let dir = this._getAppDir(id);
-      try {
-        dir.remove(true);
-      } catch (e) {}
-
-      delete this.webapps[id];
-
-      this._saveApps((function() {
-        aData.manifestURL = app.manifestURL;
-        this.broadcastMessage("Webapps:Uninstall:Broadcast:Return:OK", aData);
-        aMm.sendAsyncMessage("Webapps:Uninstall:Return:OK", aData);
-        Services.obs.notifyObservers(this, "webapps-sync-uninstall", appNote);
-        this.broadcastMessage("Webapps:RemoveApp", { id: id });
-      }).bind(this));
-
+    );
+  },
+
+  uninstall: function(aManifestURL, aOnSuccess, aOnFailure) {
+    debug("uninstall " + aManifestURL);
+
+    let app = this.getAppByManifestURL(aManifestURL);
+    if (!app) {
+      aOnFailure("NO_SUCH_APP");
+      return;
+    }
+    let id = app.id;
+
+    if (!app.removable) {
+      debug("Error: cannot uninstall a non-removable app.");
+      aOnFailure("NON_REMOVABLE_APP");
       return;
     }
 
-    // Fall-through, fails to uninstall the desired app because:
-    //   - we cannot find the app to be uninstalled.
-    //   - the app to be uninstalled is not removable.
-    aMm.sendAsyncMessage("Webapps:Uninstall:Return:KO", aData);
+    // Check if we are downloading something for this app, and cancel the
+    // download if needed.
+    this.cancelDownload(app.manifestURL);
+
+    // Clean up the deprecated manifest cache if needed.
+    if (id in this._manifestCache) {
+      delete this._manifestCache[id];
+    }
+
+    // Clear private data first.
+    this._clearPrivateData(app.localId, false);
+
+    // Then notify observers.
+    // We have to clone the app object as nsIDOMApplication objects are
+    // stringified as an empty object. (see bug 830376)
+    let appClone = AppsUtils.cloneAppObject(app);
+    Services.obs.notifyObservers(null, "webapps-uninstall", JSON.stringify(appClone));
+
+    if (supportSystemMessages()) {
+      this._readManifests([{ id: id }], (function unregisterManifest(aResult) {
+        this._unregisterActivities(aResult[0].manifest, app);
+      }).bind(this));
+    }
+
+    let dir = this._getAppDir(id);
+    try {
+      dir.remove(true);
+    } catch (e) {}
+
+    delete this.webapps[id];
+
+    this._saveApps((function() {
+      this.broadcastMessage("Webapps:Uninstall:Broadcast:Return:OK", appClone);
+      // Catch exception on callback call to ensure notifying observers after
+      try {
+        aOnSuccess();
+      } catch(e) {
+        Cu.reportError("DOMApplicationRegistry: Exception on app uninstall: " +
+                       ex + "\n" + ex.stack);
+      }
+      Services.obs.notifyObservers(this, "webapps-sync-uninstall", JSON.stringify(appClone));
+      this.broadcastMessage("Webapps:RemoveApp", { id: id });
+    }).bind(this));
   },
 
   getSelf: function(aData, aMm) {
     aData.apps = [];
 
     if (aData.appId == Ci.nsIScriptSecurityManager.NO_APP_ID ||
         aData.appId == Ci.nsIScriptSecurityManager.UNKNOWN_APP_ID) {
       aMm.sendAsyncMessage("Webapps:GetSelf:Return:OK", aData);
@@ -2676,33 +2715,41 @@ this.DOMApplicationRegistry = {
 
     this._readManifests(tmp, (function(aResult) {
       for (let i = 0; i < aResult.length; i++)
         aData.apps[i].manifest = aResult[i].manifest;
       aMm.sendAsyncMessage("Webapps:GetNotInstalled:Return:OK", aData);
     }).bind(this));
   },
 
-  getAll: function(aData, aMm) {
-    aData.apps = [];
+  doGetAll: function(aData, aMm) {
+    this.getAll(function (apps) {
+      aData.apps = apps;
+      aMm.sendAsyncMessage("Webapps:GetAll:Return:OK", aData);
+    });
+  },
+
+  getAll: function(aCallback) {
+    debug("getAll");
+    let apps = [];
     let tmp = [];
 
     for (let id in this.webapps) {
       let app = AppsUtils.cloneAppObject(this.webapps[id]);
       if (!this._isLaunchable(app.origin))
         continue;
 
-      aData.apps.push(app);
+      apps.push(app);
       tmp.push({ id: id });
     }
 
     this._readManifests(tmp, (function(aResult) {
       for (let i = 0; i < aResult.length; i++)
-        aData.apps[i].manifest = aResult[i].manifest;
-      aMm.sendAsyncMessage("Webapps:GetAll:Return:OK", aData);
+        apps[i].manifest = aResult[i].manifest;
+      aCallback(apps);
     }).bind(this));
   },
 
   getManifestFor: function(aOrigin, aCallback) {
     if (!aCallback)
       return;
 
     let id = this._appId(aOrigin);
new file mode 100644
index 0000000000000000000000000000000000000000..511025975f9e0a5e759090086991504e9b9d9b83
GIT binary patch
literal 484
zc$^FHW@Zs#U|`^2IFdTgi7D`)iaU@O3&dOuG7On{DXA5D86~+np&^_M%pVri2ZC^E
z1vdjD%L`@(1~9QX(C4JT-bx*h&=VRb&u)CYsWEV6r)HU%>P%J3m1SnX45V~UrB0qQ
zKPdC~(ghD@#7v4`5-=$$X3>O*fCa}>7xPbK)MA;<#1H^?%2J?Hu0<ZY7z*Si12I3)
zDY=PxnQ5uTC3@wlNr?poVE1eVx@9Y-dsaUS3J5smea1I*Q&0exr><V0hmJ<TCC1KW
zOT^U0Q^lsFJbQjn#rX3j(Nn>b8@#$ig(iD{>Q>My7V`c)$@meskhhV8)>q@tK|$JI
zjJ%49r|ihu33MGJlN>Xyppsw!0Y)I+(g<Q92OKLT;Lse2Y#ye6k<IG{k{G^ch4>!B
TP*ygOMkXL!3ZykbCNKa1gKmxC
new file mode 100644
--- /dev/null
+++ b/dom/apps/tests/unit/test_webappsActor.js
@@ -0,0 +1,189 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+Components.utils.import("resource://gre/modules/devtools/dbg-server.jsm");
+Components.utils.import("resource://gre/modules/devtools/dbg-client.jsm");
+
+Components.utils.import("resource://gre/modules/FileUtils.jsm");
+Components.utils.import("resource://gre/modules/Services.jsm");
+
+let gClient, gActor;
+let gAppId = "actor-test";
+
+add_test(function testSetup() {
+  // Initialize a loopback remote protocol connection
+  DebuggerServer.init(function () { return true; });
+  // We need to register browser actors to have `listTabs` working
+  // and also have a root actor
+  DebuggerServer.addBrowserActors();
+  DebuggerServer.addActors("chrome://browser/content/dbg-webapps-actors.js");
+
+  // Setup client and actor used in all tests
+  gClient = new DebuggerClient(DebuggerServer.connectPipe());
+  gClient.connect(function onConnect() {
+    gClient.listTabs(function onListTabs(aResponse) {
+      gActor = aResponse.webappsActor;
+      run_next_test();
+    });
+  });
+});
+
+add_test(function testLaunchInexistantApp() {
+  let request = {to: gActor, type: "launch", manifestURL: "http://foo.com"};
+  gClient.request(request, function (aResponse) {
+    do_check_eq(aResponse.error, "NO_SUCH_APP");
+    run_next_test();
+  });
+});
+
+add_test(function testCloseInexistantApp() {
+  let request = {to: gActor, type: "close", manifestURL: "http://foo.com"};
+  gClient.request(request, function (aResponse) {
+    do_check_eq(aResponse.error, "missingParameter");
+    do_check_eq(aResponse.message, "No application for http://foo.com");
+    run_next_test();
+  });
+});
+
+// Install a test app
+add_test(function testInstallPackaged() {
+  // Copy our test webapp to tmp folder, where the actor retrieves it
+  let zip = do_get_file("data/app.zip");
+  let appDir = FileUtils.getDir("TmpD", ["b2g", gAppId], true, true);
+  zip.copyTo(appDir, "application.zip");
+
+  let request = {to: gActor, type: "install", appId: gAppId};
+  gClient.request(request, function (aResponse) {
+    do_check_eq(aResponse.appId, gAppId);
+  });
+
+  // The install request is asynchronous and send back an event to tell
+  // if the installation succeed or failed
+  gClient.addListener("webappsEvent", function (aState, aType, aPacket) {
+    do_check_eq(aType.appId, gAppId);
+    do_check_eq("error" in aType, false);
+
+    run_next_test();
+  });
+});
+
+
+// Now check that the app appear in getAll
+add_test(function testGetAll() {
+  let request = {to: gActor, type: "getAll"};
+  gClient.request(request, function (aResponse) {
+    do_check_true("apps" in aResponse);
+    let apps = aResponse.apps;
+    do_check_true(apps.length > 0);
+    for (let i = 0; i < apps.length; i++) {
+      let app = apps[i];
+      if (app.id == gAppId) {
+        do_check_eq(app.name, "Test app");
+        do_check_eq(app.manifest.description, "Testing webapps actor");
+        do_check_eq(app.manifest.launch_path, "/index.html");
+        do_check_eq(app.origin, "app://" + gAppId);
+        do_check_eq(app.installOrigin, app.origin);
+        do_check_eq(app.manifestURL, app.origin + "/manifest.webapp");
+        run_next_test();
+        return;
+      }
+    }
+    do_throw("Unable to find the test app by its id");
+  });
+});
+
+add_test(function testLaunchApp() {
+  let manifestURL = "app://" + gAppId + "/manifest.webapp";
+  let startPoint = "/index.html";
+  let request = {
+    to: gActor, type: "launch",
+    manifestURL: manifestURL,
+    startPoint: startPoint
+  };
+  Services.obs.addObserver(function observer(subject, topic, data) {
+    Services.obs.removeObserver(observer, topic);
+    let json = JSON.parse(data);
+    do_check_eq(json.manifestURL, manifestURL);
+    do_check_eq(json.startPoint, startPoint);
+    run_next_test();
+  }, "webapps-launch", false);
+
+  gClient.request(request, function (aResponse) {
+    do_check_false("error" in aResponse);
+  });
+});
+
+add_test(function testCloseApp() {
+  let manifestURL = "app://" + gAppId + "/manifest.webapp";
+  let request = {
+    to: gActor, type: "close",
+    manifestURL: manifestURL
+  };
+  Services.obs.addObserver(function observer(subject, topic, data) {
+    Services.obs.removeObserver(observer, topic);
+    let json = JSON.parse(data);
+    do_check_eq(json.manifestURL, manifestURL);
+    run_next_test();
+  }, "webapps-close", false);
+
+  gClient.request(request, function (aResponse) {
+    do_check_false("error" in aResponse);
+  });
+});
+
+add_test(function testUninstall() {
+  let origin = "app://" + gAppId;
+  let manifestURL = origin + "/manifest.webapp";
+  let request = {
+    to: gActor, type: "uninstall",
+    manifestURL: manifestURL
+  };
+
+  let gotFirstUninstallEvent = false;
+  Services.obs.addObserver(function observer(subject, topic, data) {
+    Services.obs.removeObserver(observer, topic);
+    let json = JSON.parse(data);
+    do_check_eq(json.manifestURL, manifestURL);
+    do_check_eq(json.origin, origin);
+    gotFirstUninstallEvent = true;
+  }, "webapps-uninstall", false);
+
+  Services.obs.addObserver(function observer(subject, topic, data) {
+    Services.obs.removeObserver(observer, topic);
+    let json = JSON.parse(data);
+    do_check_eq(json.manifestURL, manifestURL);
+    do_check_eq(json.origin, origin);
+    do_check_eq(json.id, gAppId);
+    do_check_true(gotFirstUninstallEvent);
+    run_next_test();
+  }, "webapps-sync-uninstall", false);
+
+  gClient.request(request, function (aResponse) {
+    do_check_false("error" in aResponse);
+  });
+});
+
+// Close the test remote connection before leaving this test
+add_test(function testTearDown() {
+  gClient.close(function () {
+    run_next_test();
+  });
+});
+
+function run_test() {
+  // We have to setup a profile, otherwise indexed db used by webapps
+  // will throw random exception when trying to get profile folder
+  do_get_profile();
+
+  // We also need a valid nsIXulAppInfo service as Webapps.jsm is querying it
+  Components.utils.import("resource://testing-common/AppInfo.jsm");
+  updateAppInfo();
+
+  // We have to toggle this flag in order to have apps being listed in getAll
+  // as only launchable apps are returned
+  Components.utils.import('resource://gre/modules/Webapps.jsm');
+  DOMApplicationRegistry.allAppsLaunchable = true;
+
+  run_next_test();
+}
+
--- a/dom/apps/tests/unit/xpcshell.ini
+++ b/dom/apps/tests/unit/xpcshell.ini
@@ -1,5 +1,7 @@
 [DEFAULT]
 head =
 tail =
 
 [test_manifestSanitizer.js]
+[test_webappsActor.js]
+run-if = toolkit == "gonk"
--- a/dom/system/gonk/RadioInterfaceLayer.js
+++ b/dom/system/gonk/RadioInterfaceLayer.js
@@ -2691,24 +2691,17 @@ RadioInterfaceLayer.prototype = {
       strict7BitEncoding = Services.prefs.getBoolPref("dom.sms.strict7BitEncoding");
     } catch (e) {
       strict7BitEncoding = false;
     }
 
     let options = this._fragmentText(message, null, strict7BitEncoding);
     options.rilMessageType = "sendSMS";
     options.number = PhoneNumberUtils.normalize(number);
-    let requestStatusReport;
-    try {
-      requestStatusReport =
-        Services.prefs.getBoolPref("dom.sms.requestStatusReport");
-    } catch (e) {
-      requestStatusReport = false;
-    }
-    options.requestStatusReport = requestStatusReport;
+    options.requestStatusReport = true;
     if (options.segmentMaxSeq > 1) {
       options.segmentRef16Bit = this.segmentRef16Bit;
       options.segmentRef = this.nextSegmentRef;
     }
 
     let sendingMessage = {
       type: "sms",
       receiver: number,
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -4063,17 +4063,16 @@ pref("dom.vibrator.max_vibrate_list_len"
 // Battery API
 pref("dom.battery.enabled", true);
 
 // WebSMS
 pref("dom.sms.enabled", false);
 // Enable Latin characters replacement with corresponding ones in GSM SMS
 // 7-bit default alphabet.
 pref("dom.sms.strict7BitEncoding", false);
-pref("dom.sms.requestStatusReport", false);
 
 // WebContacts
 pref("dom.mozContacts.enabled", false);
 
 // WebAlarms
 pref("dom.mozAlarms.enabled", false);
 
 // SimplePush
--- a/testing/mochitest/runtestsb2g.py
+++ b/testing/mochitest/runtestsb2g.py
@@ -55,21 +55,21 @@ class B2GMochitest(Mochitest):
             OOP_script = """
 let specialpowers = {};
 let loader = Cc["@mozilla.org/moz/jssubscript-loader;1"].getService(Ci.mozIJSSubScriptLoader);
 loader.loadSubScript("chrome://specialpowers/content/SpecialPowersObserver.js", specialpowers);
 let specialPowersObserver = new specialpowers.SpecialPowersObserver();
 specialPowersObserver.init();
 
 let mm = container.QueryInterface(Ci.nsIFrameLoaderOwner).frameLoader.messageManager;
-container.focus();
 mm.addMessageListener("SPPrefService", specialPowersObserver);
 mm.addMessageListener("SPProcessCrashService", specialPowersObserver);
 mm.addMessageListener("SPPingService", specialPowersObserver);
 mm.addMessageListener("SpecialPowers.Quit", specialPowersObserver);
+mm.addMessageListener("SpecialPowers.Focus", specialPowersObserver);
 mm.addMessageListener("SPPermissionManager", specialPowersObserver);
 
 mm.loadFrameScript(CHILD_LOGGER_SCRIPT, true);
 mm.loadFrameScript(CHILD_SCRIPT_API, true);
 mm.loadFrameScript(CHILD_SCRIPT, true);
 specialPowersObserver._isFrameScriptLoaded = true;
 """
         else:
--- a/testing/mochitest/tests/SimpleTest/ChromePowers.js
+++ b/testing/mochitest/tests/SimpleTest/ChromePowers.js
@@ -67,16 +67,24 @@ ChromePowers.prototype._receiveMessage =
 
 ChromePowers.prototype.quit = function() {
   // We come in here as SpecialPowers.quit, but SpecialPowers is really ChromePowers.
   // For some reason this.<func> resolves to TestRunner, so using SpecialPowers
   // allows us to use the ChromePowers object which we defined below.
   SpecialPowers._sendSyncMessage("SpecialPowers.Quit", {});
 };
 
+ChromePowers.prototype.focus = function(aWindow) {
+  // We come in here as SpecialPowers.focus, but SpecialPowers is really ChromePowers.
+  // For some reason this.<func> resolves to TestRunner, so using SpecialPowers
+  // allows us to use the ChromePowers object which we defined below.
+  if (aWindow)
+    aWindow.focus();
+};
+
 ChromePowers.prototype.executeAfterFlushingMessageQueue = function(aCallback) {
   aCallback();
 };
 
 // Expose everything but internal APIs (starting with underscores) to
 // web content.  We cannot use Object.keys to view SpecialPowers.prototype since
 // we are using the functions from SpecialPowersAPI.prototype
 ChromePowers.prototype.__exposedProps__ = {};
--- a/testing/mochitest/tests/SimpleTest/TestRunner.js
+++ b/testing/mochitest/tests/SimpleTest/TestRunner.js
@@ -228,21 +228,20 @@ TestRunner._toggle = function(el) {
 /**
  * Creates the iframe that contains a test
 **/
 TestRunner._makeIframe = function (url, retry) {
     var iframe = $('testframe');
     if (url != "about:blank" &&
         (("hasFocus" in document && !document.hasFocus()) ||
          ("activeElement" in document && document.activeElement != iframe))) {
-        // typically calling ourselves from setTimeout is sufficient
-        // but we'll try focus() just in case that's needed
 
         contentAsyncEvent("Focus");
         window.focus();
+        SpecialPowers.focus();
         iframe.focus();
         if (retry < 3) {
             window.setTimeout('TestRunner._makeIframe("'+url+'", '+(retry+1)+')', 1000);
             return;
         }
 
         TestRunner.log("Error: Unable to restore focus, expect failures and timeouts.");
     }
@@ -277,18 +276,16 @@ TestRunner.runTests = function (/*url...
     TestRunner.log("SimpleTest START");
     TestRunner.originalTestURL = $("current-test").innerHTML;
 
     SpecialPowers.registerProcessCrashObservers();
 
     TestRunner._urls = flattenArguments(arguments);
     $('testframe').src="";
     TestRunner._checkForHangs();
-    window.focus();
-    $('testframe').focus();
     TestRunner.runNextTest();
 };
 
 /**
  * Used for running a set of tests in a loop for debugging purposes
  * Takes an array of URLs
 **/
 TestRunner.resetTests = function(listURLs) {
@@ -296,18 +293,16 @@ TestRunner.resetTests = function(listURL
   // Reset our "Current-test" line - functionality depends on it
   $("current-test").innerHTML = TestRunner.originalTestURL;
   if (TestRunner.logEnabled)
     TestRunner.log("SimpleTest START Loop " + TestRunner._currentLoop);
 
   TestRunner._urls = listURLs;
   $('testframe').src="";
   TestRunner._checkForHangs();
-  window.focus();
-  $('testframe').focus();
   TestRunner.runNextTest();
 }
 
 /*
  * Used to run a single test in a loop and update the UI with the results
  */
 TestRunner.loopTest = function(testPath) {
   //must set the following line so that TestHarness.updateUI finds the right div to update
--- a/testing/specialpowers/components/SpecialPowersObserver.js
+++ b/testing/specialpowers/components/SpecialPowersObserver.js
@@ -51,16 +51,17 @@ SpecialPowersObserver.prototype = new Sp
 
       case "chrome-document-global-created":
         if (!this._isFrameScriptLoaded) {
           // Register for any messages our API needs us to handle
           this._messageManager.addMessageListener("SPPrefService", this);
           this._messageManager.addMessageListener("SPProcessCrashService", this);
           this._messageManager.addMessageListener("SPPingService", this);
           this._messageManager.addMessageListener("SpecialPowers.Quit", this);
+          this._messageManager.addMessageListener("SpecialPowers.Focus", this);
           this._messageManager.addMessageListener("SPPermissionManager", this);
           this._messageManager.addMessageListener("SPWebAppService", this);
 
           this._messageManager.loadFrameScript(CHILD_LOGGER_SCRIPT, true);
           this._messageManager.loadFrameScript(CHILD_SCRIPT_API, true);
           this._messageManager.loadFrameScript(CHILD_SCRIPT, true);
           this._isFrameScriptLoaded = true;
         }
@@ -139,14 +140,17 @@ SpecialPowersObserver.prototype = new Sp
                   .messageManager
                   .sendAsyncMessage("SPPingService", { op: "pong" });
         }
         break;
       case "SpecialPowers.Quit":
         let appStartup = Cc["@mozilla.org/toolkit/app-startup;1"].getService(Ci.nsIAppStartup);
         appStartup.quit(Ci.nsIAppStartup.eForceQuit);
         break;
+      case "SpecialPowers.Focus":
+        aMessage.target.focus();
+        break;
       default:
         return this._receiveMessage(aMessage);
     }
   };
 
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([SpecialPowersObserver]);
--- a/testing/specialpowers/content/specialpowersAPI.js
+++ b/testing/specialpowers/content/specialpowersAPI.js
@@ -1251,18 +1251,22 @@ SpecialPowersAPI.prototype = {
   activeWindow: function() {
     return this.focusManager.activeWindow;
   },
 
   focusedWindow: function() {
     return this.focusManager.focusedWindow;
   },
 
-  focus: function(window) {
-    window.focus();
+  focus: function(aWindow) {
+    // This is called inside TestRunner._makeIframe without aWindow, because of assertions in oop mochitests
+    // With aWindow, it is called in SimpleTest.waitForFocus to allow popup window opener focus switching
+    if (aWindow)
+      aWindow.focus();
+    sendAsyncMessage("SpecialPowers.Focus", {});
   },
 
   getClipboardData: function(flavor) {
     if (this._cb == null)
       this._cb = Components.classes["@mozilla.org/widget/clipboard;1"].
                             getService(Components.interfaces.nsIClipboard);
 
     var xferable = Components.classes["@mozilla.org/widget/transferable;1"].
--- a/testing/xpcshell/xpcshell_b2g.ini
+++ b/testing/xpcshell/xpcshell_b2g.ini
@@ -1,12 +1,13 @@
 ; This Source Code Form is subject to the terms of the Mozilla Public
 ; License, v. 2.0. If a copy of the MPL was not distributed with this
 ; file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
+[include:dom/apps/tests/unit/xpcshell.ini]
 [include:dom/mobilemessage/tests/xpcshell.ini]
 [include:dom/mms/tests/xpcshell.ini]
 [include:dom/system/gonk/tests/xpcshell.ini]
 [include:toolkit/devtools/debugger/tests/unit/xpcshell.ini]
 [include:toolkit/devtools/sourcemap/tests/unit/xpcshell.ini]
 [include:toolkit/mozapps/downloads/tests/unit/xpcshell.ini]
 [include:toolkit/mozapps/update/test_timermanager/unit/xpcshell.ini]
 [include:toolkit/mozapps/update/test_svc/unit/xpcshell.ini]
--- a/widget/gonk/HwcComposer2D.cpp
+++ b/widget/gonk/HwcComposer2D.cpp
@@ -161,26 +161,26 @@ PrepareLayerRects(nsIntRect aVisible, co
     }
 
     gfxMatrix inverse(aTransform);
     inverse.Invert();
     gfxRect crop = inverse.TransformBounds(visibleRectScreen);
 
     //clip to buffer size
     crop.IntersectRect(crop, aBufferRect);
-    crop.RoundOut();
+    crop.Round();
 
     if (crop.IsEmpty()) {
         LOGD("Skip layer");
         return false;
     }
 
     //propagate buffer clipping back to visible rect
     visibleRectScreen = aTransform.TransformBounds(crop);
-    visibleRectScreen.RoundOut();
+    visibleRectScreen.Round();
 
     // Map from layer space to buffer space
     crop -= aBufferRect.TopLeft();
 
     aSourceCrop->left = crop.x;
     aSourceCrop->top  = crop.y;
     aSourceCrop->right  = crop.x + crop.width;
     aSourceCrop->bottom = crop.y + crop.height;
@@ -189,16 +189,62 @@ PrepareLayerRects(nsIntRect aVisible, co
     aVisibleRegionScreen->top  = visibleRectScreen.y;
     aVisibleRegionScreen->right  = visibleRectScreen.x + visibleRectScreen.width;
     aVisibleRegionScreen->bottom = visibleRectScreen.y + visibleRectScreen.height;
 
     return true;
 }
 
 /**
+ * Prepares hwc layer visible region required for hwc composition
+ *
+ * @param aVisible Input. Layer's unclipped visible region
+ *        The origin is the top-left corner of the layer
+ * @param aTransform Input. Layer's transformation matrix
+ *        It transforms from layer space to screen space
+ * @param aClip Input. A clipping rectangle.
+ *        The origin is the top-left corner of the screen
+ * @param aBufferRect Input. The layer's buffer bounds
+ *        The origin is the top-left corner of the layer
+ * @param aVisibleRegionScreen Output. Visible region in screen space.
+ *        The origin is the top-left corner of the screen
+ * @return true if the layer should be rendered.
+ *         false if the layer can be skipped
+ */
+static bool
+PrepareVisibleRegion(const nsIntRegion& aVisible,
+                     const gfxMatrix& aTransform,
+                     nsIntRect aClip, nsIntRect aBufferRect,
+                     RectVector* aVisibleRegionScreen) {
+
+    nsIntRegionRectIterator rect(aVisible);
+    bool isVisible = false;
+    while (const nsIntRect* visibleRect = rect.Next()) {
+        hwc_rect_t visibleRectScreen;
+        gfxRect screenRect;
+
+        screenRect.IntersectRect(gfxRect(*visibleRect), aBufferRect);
+        screenRect = aTransform.TransformBounds(screenRect);
+        screenRect.IntersectRect(screenRect, aClip);
+        screenRect.Round();
+        if (screenRect.IsEmpty()) {
+            continue;
+        }
+        visibleRectScreen.left = screenRect.x;
+        visibleRectScreen.top  = screenRect.y;
+        visibleRectScreen.right  = screenRect.XMost();
+        visibleRectScreen.bottom = screenRect.YMost();
+        aVisibleRegionScreen->push_back(visibleRectScreen);
+        isVisible = true;
+    }
+
+    return isVisible;
+}
+
+/**
  * Calculates the layer's clipping rectangle
  *
  * @param aTransform Input. A transformation matrix
  *        It transforms the clip rect to screen space
  * @param aLayerClip Input. The layer's internal clipping rectangle.
  *        This may be NULL which means the layer has no internal clipping
  *        The origin is the top-left corner of the layer
  * @param aParentClip Input. The parent layer's rendering clipping rectangle
@@ -246,31 +292,21 @@ HwcComposer2D::PrepareLayerList(Layer* a
     bool fillColor = false;
 
     const nsIntRegion& visibleRegion = aLayer->GetEffectiveVisibleRegion();
     if (visibleRegion.IsEmpty()) {
         return true;
     }
 
     float opacity = aLayer->GetEffectiveOpacity();
-    if (opacity <= 0) {
-        LOGD("Layer is fully transparent so skip rendering");
-        return true;
-    }
-    else if (opacity < 1) {
+    if (opacity < 1) {
         LOGD("Layer has planar semitransparency which is unsupported");
         return false;
     }
 
-    if (visibleRegion.GetNumRects() > 1) {
-        // FIXME/bug 808339
-        LOGD("Layer has nontrivial visible region");
-        return false;
-    }
-
     nsIntRect clip;
     if (!CalculateClipRect(aParentTransform * aGLWorldTransform,
                            aLayer->GetEffectiveClipRect(),
                            aClip,
                            &clip))
     {
         LOGD("Clip rect is empty. Skip layer");
         return true;
@@ -297,19 +333,23 @@ HwcComposer2D::PrepareLayerList(Layer* a
                 return false;
             }
         }
         return true;
     }
 
     LayerOGL* layerGL = static_cast<LayerOGL*>(aLayer->ImplData());
     LayerRenderState state = layerGL->GetRenderState();
+    nsIntSize surfaceSize;
 
-    if (!state.mSurface ||
-        state.mSurface->type() != SurfaceDescriptor::TSurfaceDescriptorGralloc) {
+    if (state.mSurface &&
+        state.mSurface->type() == SurfaceDescriptor::TSurfaceDescriptorGralloc) {
+        surfaceSize = state.mSurface->get_SurfaceDescriptorGralloc().size();
+    }
+    else {
         if (aLayer->AsColorLayer() && mColorFill) {
             fillColor = true;
         } else {
             LOGD("Layer doesn't have a gralloc buffer");
             return false;
         }
     }
     if (state.BufferRotated()) {
@@ -333,20 +373,20 @@ HwcComposer2D::PrepareLayerList(Layer* a
     nsIntRect visibleRect = visibleRegion.GetBounds();
 
     nsIntRect bufferRect;
     if (fillColor) {
         bufferRect = nsIntRect(visibleRect);
     } else {
         if(state.mHasOwnOffset) {
             bufferRect = nsIntRect(state.mOffset.x, state.mOffset.y,
-                int(buffer->getWidth()), int(buffer->getHeight()));
+                surfaceSize.width, surfaceSize.height);
         } else {
             bufferRect = nsIntRect(visibleRect.x, visibleRect.y,
-                int(buffer->getWidth()), int(buffer->getHeight()));
+                surfaceSize.width, surfaceSize.height);
         }
     }
 
     hwc_layer_t& hwcLayer = mList->hwLayers[current];
 
     if(!PrepareLayerRects(visibleRect,
                           transform * aGLWorldTransform,
                           clip,
@@ -380,22 +420,40 @@ HwcComposer2D::PrepareLayerList(Layer* a
             hwcLayer.transform = HWC_TRANSFORM_ROT_180;
             LOGD("Layer buffer rotated 180 degrees");
         } else {
             hwcLayer.transform = 0;
         }
 
         hwcLayer.transform |= state.YFlipped() ? HWC_TRANSFORM_FLIP_V : 0;
         hwc_region_t region;
-        region.numRects = 1;
-        region.rects = &(hwcLayer.displayFrame);
+        if (visibleRegion.GetNumRects() > 1) {
+            mVisibleRegions.push_back(RectVector());
+            RectVector* visibleRects = &(mVisibleRegions.back());
+            if(!PrepareVisibleRegion(visibleRegion,
+                                     transform * aGLWorldTransform,
+                                     clip,
+                                     bufferRect,
+                                     visibleRects)) {
+                return true;
+            }
+            region.numRects = visibleRects->size();
+            region.rects = &((*visibleRects)[0]);
+        } else {
+            region.numRects = 1;
+            region.rects = &(hwcLayer.displayFrame);
+        }
         hwcLayer.visibleRegionScreen = region;
     } else {
         hwcLayer.flags |= HWC_COLOR_FILL;
-        ColorLayer* colorLayer = static_cast<ColorLayer*>(layerGL->GetLayer());
+        ColorLayer* colorLayer = aLayer->AsColorLayer();
+        if (colorLayer->GetColor().a < 1.0) {
+            LOGD("Color layer has semitransparency which is unsupported");
+            return false;
+        }
         hwcLayer.transform = colorLayer->GetColor().Packed();
     }
 
     mList->numHwLayers++;
     return true;
 }
 
 bool
@@ -407,16 +465,20 @@ HwcComposer2D::TryRender(Layer* aRoot,
         return false;
     }
 
     MOZ_ASSERT(Initialized());
     if (mList) {
         mList->numHwLayers = 0;
     }
 
+    // XXX: The clear() below means all rect vectors will be have to be
+    // reallocated. We may want to avoid this if possible
+    mVisibleRegions.clear();
+
     if (!PrepareLayerList(aRoot,
                           mScreenRect,
                           gfxMatrix(),
                           aGLWorldTransform))
     {
         LOGD("Render aborted. Nothing was drawn to the screen");
         return false;
     }
--- a/widget/gonk/HwcComposer2D.h
+++ b/widget/gonk/HwcComposer2D.h
@@ -15,24 +15,30 @@
  */
 
 #ifndef mozilla_HwcComposer2D
 #define mozilla_HwcComposer2D
 
 #include "Composer2D.h"
 #include "HWComposer.h"
 #include "Layers.h"
+#include <vector>
+#include <list>
 
 namespace mozilla {
 
 namespace layers {
 class ContainerLayer;
 class Layer;
 }
 
+//Holds a dynamically allocated vector of rectangles
+//used to decribe the complex visible region of a layer
+typedef std::vector<hwc_rect_t> RectVector;
+
 class HwcComposer2D : public android::HWComposer,
                       public mozilla::layers::Composer2D {
 public:
     HwcComposer2D();
     virtual ~HwcComposer2D();
 
     int Init(hwc_display_t aDisplay, hwc_surface_t aSurface);
 
@@ -49,13 +55,16 @@ private:
     bool ReallocLayerList();
     bool PrepareLayerList(layers::Layer* aContainer, const nsIntRect& aClip,
           const gfxMatrix& aParentTransform, const gfxMatrix& aGLWorldTransform);
 
     hwc_layer_list_t*       mList;
     nsIntRect               mScreenRect;
     int                     mMaxLayerCount;
     bool                    mColorFill;
+    //Holds all the dynamically allocated RectVectors needed
+    //to render the current frame
+    std::list<RectVector>   mVisibleRegions;
 };
 
 } // namespace mozilla
 
 #endif // mozilla_HwcComposer2D