Backed out 10 changesets (bug 1446809) for failures in testing/mozbase/moztest/tests/test.py on a CLOSED TREE
authorNoemi Erli <nerli@mozilla.com>
Tue, 20 Mar 2018 17:00:04 +0200
changeset 409018 dcfeba2cde5e3b373331fcd6f64fee3093890bbb
parent 409017 daef726185bbd890c5801641c7b103910778b64f
child 409019 20e9096156b084368e4adc884e5a63ea1f6ed753
push id33671
push usercsabou@mozilla.com
push dateTue, 20 Mar 2018 22:23:32 +0000
treeherdermozilla-central@e2e874ceae78 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1446809
milestone61.0a1
backs out5748f214f8133624bf30521c841c09af4ea208b5
1c7a6f2885fbfc9f799bf29111d093e821e44a49
2c31f0efbe6405e9068d2e99d1e55ba9fc7f770d
e102f93c590f80e3feb6e877d5d7d7bda9b0f54a
c722a1c3395f821c428db7a2465d9fb1156ec67a
20b4c87f8abbdeaa023fed7e22baaed19582bb74
31026393c5b685adf6c5d1138bf2dd314280b1f7
9103be0ca1763cf0002c4ff2e5fa108bc398e70a
11d671ad8ed4b4b3b519dd637f3f5a79b8ee06c3
e412991e7f95b3203e40b62bcff70ac1378637e8
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out 10 changesets (bug 1446809) for failures in testing/mozbase/moztest/tests/test.py on a CLOSED TREE Backed out changeset 5748f214f813 (bug 1446809) Backed out changeset 1c7a6f2885fb (bug 1446809) Backed out changeset 2c31f0efbe64 (bug 1446809) Backed out changeset e102f93c590f (bug 1446809) Backed out changeset c722a1c3395f (bug 1446809) Backed out changeset 20b4c87f8abb (bug 1446809) Backed out changeset 31026393c5b6 (bug 1446809) Backed out changeset 9103be0ca176 (bug 1446809) Backed out changeset 11d671ad8ed4 (bug 1446809) Backed out changeset e412991e7f95 (bug 1446809)
accessible/jsat/Presentation.jsm
accessible/jsat/Utils.jsm
accessible/tests/mochitest/hittest/a11y.ini
accessible/tests/mochitest/jsat/jsatcommon.js
accessible/tests/mochitest/jsat/test_content_integration.html
browser/components/BrowserComponents.manifest
browser/components/feeds/BrowserFeeds.manifest
browser/components/sessionstore/nsSessionStore.manifest
browser/experiments/docs/manifest.rst
build/docs/mozinfo.rst
build/unix/mozconfig.linux
devtools/docs/backend/actor-registration.md
devtools/shared/system.js
dom/cache/test/mochitest/serviceworker_driver.js
dom/canvas/test/webgl-conf/generated-mochitest.ini
dom/canvas/test/webgl-conf/mochitest-errata.ini
mobile/android/modules/FormAssistant.jsm
testing/mozbase/moztest/tests/test.py
testing/mozbase/mozversion/tests/manifest.ini
testing/mozbase/packages.txt
testing/mozharness/configs/multi_locale/standalone_mozilla-central.py
toolkit/nss.configure
toolkit/toolkit.mozbuild
widget/NativeKeyToDOMKeyName.h
--- a/accessible/jsat/Presentation.jsm
+++ b/accessible/jsat/Presentation.jsm
@@ -467,16 +467,179 @@ AndroidPresenter.prototype.noMove =
       { eventType: this.ANDROID_VIEW_ACCESSIBILITY_FOCUSED,
         exitView: aMoveMethod,
         text: [""]
       }]
     };
   };
 
 /**
+ * A B2G presenter for Gaia.
+ */
+function B2GPresenter() {}
+
+B2GPresenter.prototype = Object.create(Presenter.prototype);
+
+B2GPresenter.prototype.type = "B2G";
+
+B2GPresenter.prototype.keyboardEchoSetting =
+  new PrefCache("accessibility.accessfu.keyboard_echo");
+B2GPresenter.prototype.NO_ECHO = 0;
+B2GPresenter.prototype.CHARACTER_ECHO = 1;
+B2GPresenter.prototype.WORD_ECHO = 2;
+B2GPresenter.prototype.CHARACTER_AND_WORD_ECHO = 3;
+
+/**
+ * A pattern used for haptic feedback.
+ * @type {Array}
+ */
+B2GPresenter.prototype.PIVOT_CHANGE_HAPTIC_PATTERN = [40];
+
+/**
+ * Pivot move reasons.
+ * @type {Array}
+ */
+B2GPresenter.prototype.pivotChangedReasons = ["none", "next", "prev", "first",
+                                              "last", "text", "point"];
+
+B2GPresenter.prototype.pivotChanged =
+  function B2GPresenter_pivotChanged(aContext, aReason, aIsUserInput) {
+    if (!aContext.accessible) {
+      return null;
+    }
+
+    return {
+      type: this.type,
+      details: {
+        eventType: "vc-change",
+        data: UtteranceGenerator.genForContext(aContext),
+        options: {
+          pattern: this.PIVOT_CHANGE_HAPTIC_PATTERN,
+          isKey: Utils.isActivatableOnFingerUp(aContext.accessible),
+          reason: this.pivotChangedReasons[aReason],
+          isUserInput: aIsUserInput,
+          hints: aContext.interactionHints
+        }
+      }
+    };
+  };
+
+B2GPresenter.prototype.nameChanged =
+  function B2GPresenter_nameChanged(aAccessible, aIsPolite = true) {
+    return {
+      type: this.type,
+      details: {
+        eventType: "name-change",
+        data: aAccessible.name,
+        options: {enqueue: aIsPolite}
+      }
+    };
+  };
+
+B2GPresenter.prototype.valueChanged =
+  function B2GPresenter_valueChanged(aAccessible, aIsPolite = true) {
+
+    // the editable value changes are handled in the text changed presenter
+    if (Utils.getState(aAccessible).contains(States.EDITABLE)) {
+      return null;
+    }
+
+    return {
+      type: this.type,
+      details: {
+        eventType: "value-change",
+        data: aAccessible.value,
+        options: {enqueue: aIsPolite}
+      }
+    };
+  };
+
+B2GPresenter.prototype.textChanged = function B2GPresenter_textChanged(
+  aAccessible, aIsInserted, aStart, aLength, aText, aModifiedText) {
+    let echoSetting = this.keyboardEchoSetting.value;
+    let text = "";
+
+    if (echoSetting == this.CHARACTER_ECHO ||
+        echoSetting == this.CHARACTER_AND_WORD_ECHO) {
+      text = aModifiedText;
+    }
+
+    // add word if word boundary is added
+    if ((echoSetting == this.WORD_ECHO ||
+        echoSetting == this.CHARACTER_AND_WORD_ECHO) &&
+        aIsInserted && aLength === 1) {
+      let accText = aAccessible.QueryInterface(Ci.nsIAccessibleText);
+      let startBefore = {}, endBefore = {};
+      let startAfter = {}, endAfter = {};
+      accText.getTextBeforeOffset(aStart,
+        Ci.nsIAccessibleText.BOUNDARY_WORD_END, startBefore, endBefore);
+      let maybeWord = accText.getTextBeforeOffset(aStart + 1,
+        Ci.nsIAccessibleText.BOUNDARY_WORD_END, startAfter, endAfter);
+      if (endBefore.value !== endAfter.value) {
+        text += maybeWord;
+      }
+    }
+
+    return {
+      type: this.type,
+      details: {
+        eventType: "text-change",
+        data: text
+      }
+    };
+
+  };
+
+B2GPresenter.prototype.actionInvoked =
+  function B2GPresenter_actionInvoked(aObject, aActionName) {
+    return {
+      type: this.type,
+      details: {
+        eventType: "action",
+        data: UtteranceGenerator.genForAction(aObject, aActionName)
+      }
+    };
+  };
+
+B2GPresenter.prototype.liveRegion = function B2GPresenter_liveRegion(aContext,
+  aIsPolite, aIsHide, aModifiedText) {
+    return {
+      type: this.type,
+      details: {
+        eventType: "liveregion-change",
+        data: UtteranceGenerator.genForLiveRegion(aContext, aIsHide,
+          aModifiedText),
+        options: {enqueue: aIsPolite}
+      }
+    };
+  };
+
+B2GPresenter.prototype.announce =
+  function B2GPresenter_announce(aAnnouncement) {
+    return {
+      type: this.type,
+      details: {
+        eventType: "announcement",
+        data: aAnnouncement
+      }
+    };
+  };
+
+B2GPresenter.prototype.noMove =
+  function B2GPresenter_noMove(aMoveMethod) {
+    return {
+      type: this.type,
+      details: {
+        eventType: "no-move",
+        data: aMoveMethod
+      }
+    };
+  };
+
+/**
  * A braille presenter
  */
 function BraillePresenter() {}
 
 BraillePresenter.prototype = Object.create(Presenter.prototype);
 
 BraillePresenter.prototype.type = "Braille";
 
@@ -508,17 +671,18 @@ BraillePresenter.prototype.textSelection
     };
   };
 
 var Presentation = { // jshint ignore:line
   get presenters() {
     delete this.presenters;
     let presenterMap = {
       "mobile/android": [VisualPresenter, AndroidPresenter],
-      "browser": [VisualPresenter, AndroidPresenter]
+      "b2g": [VisualPresenter, B2GPresenter],
+      "browser": [VisualPresenter, B2GPresenter, AndroidPresenter]
     };
     this.presenters = presenterMap[Utils.MozBuildApp].map(P => new P());
     return this.presenters;
   },
 
   get displayedAccessibles() {
     delete this.displayedAccessibles;
     this.displayedAccessibles = new WeakMap();
--- a/accessible/jsat/Utils.jsm
+++ b/accessible/jsat/Utils.jsm
@@ -21,18 +21,21 @@ ChromeUtils.defineModuleGetter(this, "St
   "resource://gre/modules/accessibility/Constants.jsm");
 ChromeUtils.defineModuleGetter(this, "PluralForm", // jshint ignore:line
   "resource://gre/modules/PluralForm.jsm");
 
 var EXPORTED_SYMBOLS = ["Utils", "Logger", "PivotContext", "PrefCache"]; // jshint ignore:line
 
 var Utils = { // jshint ignore:line
   _buildAppMap: {
+    "{3c2e2abc-06d4-11e1-ac3b-374f68613e61}": "b2g",
+    "{d1bfe7d9-c01e-4237-998b-7b5f960a4314}": "graphene",
     "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}": "browser",
-    "{aa3c5121-dab2-40e2-81ca-7ea25febc110}": "mobile/android"
+    "{aa3c5121-dab2-40e2-81ca-7ea25febc110}": "mobile/android",
+    "{a23983c0-fd0e-11dc-95ff-0800200c9a66}": "mobile/xul"
   },
 
   init: function Utils_init(aWindow) {
     if (this._win) {
       // XXX: only supports attaching to one window now.
       throw new Error("Only one top-level window could used with AccessFu");
     }
     this._win = Cu.getWeakReference(aWindow);
@@ -125,25 +128,30 @@ var Utils = { // jshint ignore:line
     if (!this.win) {
       return null;
     }
     switch (this.MozBuildApp) {
       case "mobile/android":
         return this.win.BrowserApp;
       case "browser":
         return this.win.gBrowser;
+      case "b2g":
+        return this.win.shell;
       default:
         return null;
     }
   },
 
   get CurrentBrowser() {
     if (!this.BrowserApp) {
       return null;
     }
+    if (this.MozBuildApp == "b2g") {
+      return this.BrowserApp.contentBrowser;
+    }
     return this.BrowserApp.selectedBrowser;
   },
 
   get CurrentContentDoc() {
     let browser = this.CurrentBrowser;
     return browser ? browser.contentDocument : null;
   },
 
@@ -162,16 +170,23 @@ var Utils = { // jshint ignore:line
       }
     }
 
     collectLeafMessageManagers(this.win.messageManager);
 
     let document = this.CurrentContentDoc;
 
     if (document) {
+      if (document.location.host === "b2g") {
+        // The document is a b2g app chrome (ie. Mulet).
+        let contentBrowser = this.win.content.shell.contentBrowser;
+        messageManagers.add(this.getMessageManager(contentBrowser));
+        document = contentBrowser.contentDocument;
+      }
+
       let remoteframes = document.querySelectorAll("iframe");
 
       for (let i = 0; i < remoteframes.length; ++i) {
         let mm = this.getMessageManager(remoteframes[i]);
         if (mm) {
           messageManagers.add(mm);
         }
       }
--- a/accessible/tests/mochitest/hittest/a11y.ini
+++ b/accessible/tests/mochitest/hittest/a11y.ini
@@ -1,15 +1,15 @@
 [DEFAULT]
 support-files = zoom_tree.xul
   !/accessible/tests/mochitest/*.js
   !/accessible/tests/mochitest/letters.gif
 
 [test_browser.html]
 [test_canvas_hitregion.html]
-skip-if = (os == "android")
+skip-if = (os == "android" || appname == "b2g")
 [test_general.html]
 [test_menu.xul]
 [test_shadowroot.html]
 support-files = test_shadowroot_subframe.html
 [test_zoom.html]
 [test_zoom_text.html]
 [test_zoom_tree.xul]
--- a/accessible/tests/mochitest/jsat/jsatcommon.js
+++ b/accessible/tests/mochitest/jsat/jsatcommon.js
@@ -529,30 +529,33 @@ ExpectedMessage.prototype.is_correct_foc
     [ doc.activeElement, doc.querySelector(this.options.focused),
       "Correct element is focused: " + this.options.focused + " -- " + aInfo ]);
 };
 
 ExpectedMessage.prototype.ignore = function(aMessage) {
   return aMessage.name !== this.name;
 };
 
-function ExpectedPresent(aAndroid, aOptions) {
+function ExpectedPresent(aB2g, aAndroid, aOptions) {
   ExpectedMessage.call(this, "AccessFu:Present", aOptions);
+  if (aB2g) {
+    this.json.b2g = aB2g;
+  }
 
   if (aAndroid) {
     this.json.android = aAndroid;
   }
 }
 
 ExpectedPresent.prototype = Object.create(ExpectedMessage.prototype);
 
 ExpectedPresent.prototype.is = function(aReceived, aInfo) {
   var received = this.extract_presenters(aReceived);
 
-  for (var presenter of ["android"]) {
+  for (var presenter of ["b2g", "android"]) {
     if (!this.options["no_" + presenter]) {
       var todo = this.options.todo || this.options[presenter + "_todo"];
       SimpleTest[todo ? "todo" : "ok"].apply(
         SimpleTest, this.lazyCompare(received[presenter],
           this.json[presenter], aInfo + " (" + presenter + ")"));
     }
   }
 };
@@ -597,16 +600,18 @@ function ExpectedCursorTextChange(aSpeec
     eventType: "vc-change",
     data: aSpeech
   }, [{
     eventType: AndroidEvent.VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,
     fromIndex: aStartOffset,
     toIndex: aEndOffset
   }], aOptions);
 
+  // bug 980509
+  this.options.b2g_todo = true;
 }
 
 ExpectedCursorTextChange.prototype =
   Object.create(ExpectedCursorChange.prototype);
 
 function ExpectedClickAction(aOptions) {
   ExpectedPresent.call(this, {
     eventType: "action",
--- a/accessible/tests/mochitest/jsat/test_content_integration.html
+++ b/accessible/tests/mochitest/jsat/test_content_integration.html
@@ -105,17 +105,17 @@
           // Moving to the absolute last item from an embedded document
           // fails. Bug 972035.
           [ContentMessages.simpleMoveNext,
            new ExpectedCursorChange(
             ["such app", "wow", {"string": "headingLevel", "args": [1]}])],
           // Move from an inner frame to the last element in the parent doc
           [ContentMessages.simpleMoveLast,
             new ExpectedCursorChange(
-              ["slider", "0", {"string": "slider"}])],
+              ["slider", "0", {"string": "slider"}], { b2g_todo: true })],
 
           [ContentMessages.clearCursor, "AccessFu:CursorCleared"],
 
           [ContentMessages.simpleMoveNext,
            new ExpectedCursorChange(["Traversal Rule test document", "Phone status bar"])],
           [ContentMessages.moveOrAdjustDown("FormElement"),
            new ExpectedCursorChange(["Back", {"string": "pushbutton"}])],
           [ContentMessages.moveOrAdjustDown("FormElement"),
@@ -148,17 +148,17 @@
            new ExpectedCursorChange(["Back", {"string": "pushbutton"}])],
           [ContentMessages.simpleMoveNext,
            new ExpectedCursorChange(["such app", "wow", {"string": "headingLevel", "args": [1]}])],
           [ContentMessages.simpleMoveNext, new ExpectedCursorChange(
             ["many option", {"string": "stateNotChecked"},
              {"string": "checkbutton"}, {"string": "listStart"},
              {"string": "list"}, {"string": "listItemsCount", "count": 1}])],
           [ContentMessages.simpleMoveFirst,
-            new ExpectedCursorChange(["Phone status bar"])],
+            new ExpectedCursorChange(["Phone status bar"], { b2g_todo: true })],
 
           // Reset cursors
           [ContentMessages.clearCursor, "AccessFu:CursorCleared"],
 
           // Current virtual cursor's position's name changes
           [ContentMessages.simpleMoveNext,
            new ExpectedCursorChange(["Traversal Rule test document", "Phone status bar"])],
           [ContentMessages.focusSelector("button#fruit", false),
--- a/browser/components/BrowserComponents.manifest
+++ b/browser/components/BrowserComponents.manifest
@@ -24,18 +24,21 @@ category command-line-handler x-default 
 category command-line-validator b-browser @mozilla.org/browser/clh;1 application={ec8030f7-c20a-464f-9b0e-13a3a9e97384}
 
 # nsBrowserGlue.js
 
 # This component must restrict its registration for the app-startup category
 # to the specific list of apps that use it so it doesn't get loaded in xpcshell.
 # Thus we restrict it to these apps:
 #
+#   b2g:            {3c2e2abc-06d4-11e1-ac3b-374f68613e61}
 #   browser:        {ec8030f7-c20a-464f-9b0e-13a3a9e97384}
 #   mobile/android: {aa3c5121-dab2-40e2-81ca-7ea25febc110}
+#   mobile/xul:     {a23983c0-fd0e-11dc-95ff-0800200c9a66}
+#   graphene:       {d1bfe7d9-c01e-4237-998b-7b5f960a4314}
 
 component {eab9012e-5f74-4cbc-b2b5-a590235513cc} nsBrowserGlue.js
 contract @mozilla.org/browser/browserglue;1 {eab9012e-5f74-4cbc-b2b5-a590235513cc}
-category app-startup nsBrowserGlue service,@mozilla.org/browser/browserglue;1 application={ec8030f7-c20a-464f-9b0e-13a3a9e97384} application={aa3c5121-dab2-40e2-81ca-7ea25febc110}
+category app-startup nsBrowserGlue service,@mozilla.org/browser/browserglue;1 application={3c2e2abc-06d4-11e1-ac3b-374f68613e61} application={ec8030f7-c20a-464f-9b0e-13a3a9e97384} application={aa3c5121-dab2-40e2-81ca-7ea25febc110} application={a23983c0-fd0e-11dc-95ff-0800200c9a66} application={d1bfe7d9-c01e-4237-998b-7b5f960a4314}
 component {d8903bf6-68d5-4e97-bcd1-e4d3012f721a} nsBrowserGlue.js
 #ifndef MOZ_MULET
 contract @mozilla.org/content-permission/prompt;1 {d8903bf6-68d5-4e97-bcd1-e4d3012f721a}
 #endif
--- a/browser/components/feeds/BrowserFeeds.manifest
+++ b/browser/components/feeds/BrowserFeeds.manifest
@@ -1,18 +1,21 @@
 # This component must restrict its registration for the app-startup category
 # to the specific list of apps that use it so it doesn't get loaded in xpcshell.
 # Thus we restrict it to these apps:
 #
+#   b2g:            {3c2e2abc-06d4-11e1-ac3b-374f68613e61}
 #   browser:        {ec8030f7-c20a-464f-9b0e-13a3a9e97384}
 #   mobile/android: {aa3c5121-dab2-40e2-81ca-7ea25febc110}
+#   mobile/xul:     {a23983c0-fd0e-11dc-95ff-0800200c9a66}
+#   graphene:       {d1bfe7d9-c01e-4237-998b-7b5f960a4314}
 
 component {229fa115-9412-4d32-baf3-2fc407f76fb1} FeedConverter.js
 contract @mozilla.org/streamconv;1?from=application/vnd.mozilla.maybe.feed&to=*/* {229fa115-9412-4d32-baf3-2fc407f76fb1}
 contract @mozilla.org/streamconv;1?from=application/vnd.mozilla.maybe.video.feed&to=*/* {229fa115-9412-4d32-baf3-2fc407f76fb1}
 contract @mozilla.org/streamconv;1?from=application/vnd.mozilla.maybe.audio.feed&to=*/* {229fa115-9412-4d32-baf3-2fc407f76fb1}
 component {2376201c-bbc6-472f-9b62-7548040a61c6} FeedConverter.js
 contract @mozilla.org/browser/feeds/result-service;1 {2376201c-bbc6-472f-9b62-7548040a61c6}
 component {49bb6593-3aff-4eb3-a068-2712c28bd58e} FeedWriter.js
 contract @mozilla.org/browser/feeds/result-writer;1 {49bb6593-3aff-4eb3-a068-2712c28bd58e}
 component {792a7e82-06a0-437c-af63-b2d12e808acc} WebContentConverter.js
 contract @mozilla.org/embeddor.implemented/web-content-handler-registrar;1 {792a7e82-06a0-437c-af63-b2d12e808acc}
-category app-startup WebContentConverter service,@mozilla.org/embeddor.implemented/web-content-handler-registrar;1 application={ec8030f7-c20a-464f-9b0e-13a3a9e97384} application={aa3c5121-dab2-40e2-81ca-7ea25febc110}
+category app-startup WebContentConverter service,@mozilla.org/embeddor.implemented/web-content-handler-registrar;1 application={3c2e2abc-06d4-11e1-ac3b-374f68613e61} application={ec8030f7-c20a-464f-9b0e-13a3a9e97384} application={aa3c5121-dab2-40e2-81ca-7ea25febc110} application={a23983c0-fd0e-11dc-95ff-0800200c9a66} application={d1bfe7d9-c01e-4237-998b-7b5f960a4314}
--- a/browser/components/sessionstore/nsSessionStore.manifest
+++ b/browser/components/sessionstore/nsSessionStore.manifest
@@ -1,12 +1,15 @@
 # This component must restrict its registration for the app-startup category
 # to the specific list of apps that use it so it doesn't get loaded in xpcshell.
 # Thus we restrict it to these apps:
 #
+#   b2g:            {3c2e2abc-06d4-11e1-ac3b-374f68613e61}
 #   browser:        {ec8030f7-c20a-464f-9b0e-13a3a9e97384}
 #   mobile/android: {aa3c5121-dab2-40e2-81ca-7ea25febc110}
+#   mobile/xul:     {a23983c0-fd0e-11dc-95ff-0800200c9a66}
+#   graphene:       {d1bfe7d9-c01e-4237-998b-7b5f960a4314}
 
 component {5280606b-2510-4fe0-97ef-9b5a22eafe6b} nsSessionStore.js
 contract @mozilla.org/browser/sessionstore;1 {5280606b-2510-4fe0-97ef-9b5a22eafe6b}
 component {ec7a6c20-e081-11da-8ad9-0800200c9a66} nsSessionStartup.js
 contract @mozilla.org/browser/sessionstartup;1 {ec7a6c20-e081-11da-8ad9-0800200c9a66}
-category app-startup nsSessionStartup service,@mozilla.org/browser/sessionstartup;1 application={ec8030f7-c20a-464f-9b0e-13a3a9e97384} application={aa3c5121-dab2-40e2-81ca-7ea25febc110}
+category app-startup nsSessionStartup service,@mozilla.org/browser/sessionstartup;1 application={3c2e2abc-06d4-11e1-ac3b-374f68613e61} application={ec8030f7-c20a-464f-9b0e-13a3a9e97384} application={aa3c5121-dab2-40e2-81ca-7ea25febc110} application={a23983c0-fd0e-11dc-95ff-0800200c9a66} application={d1bfe7d9-c01e-4237-998b-7b5f960a4314}
--- a/browser/experiments/docs/manifest.rst
+++ b/browser/experiments/docs/manifest.rst
@@ -96,17 +96,17 @@ maxActiveSeconds
    initial activation.
 
    This value only involves wall time, not browser activity or session time.
 
 appName
    Array of application names this experiment should run on.
 
    An application name comes from ``nsIXULAppInfo.name``. It is a value
-   like ``Firefox`` or ``Fennec``.
+   like ``Firefox``, ``Fennec``, or `B2G`.
 
    The client should compare its application name against the members of
    this array. If a match is found, the experiment is applicable.
 
 minVersion
    (optional) String version number of the minimum application version this
    experiment should run on.
 
--- a/build/docs/mozinfo.rst
+++ b/build/docs/mozinfo.rst
@@ -58,17 +58,17 @@ bits
    this key defined.
 
    Optional.
 
 buildapp
    The path to the XUL application being built.
 
    For desktop Firefox, this is ``browser``. For Fennec, it's
-   ``mobile/android``.
+   ``mobile/android``. For B2G, it's ``b2g``.
 
 crashreporter
    Whether the crash reporter is enabled for this build.
 
    Values are ``true`` and ``false``.
 
    Always defined.
 
@@ -109,17 +109,17 @@ nightly_build
    Whether this is a nightly build.
 
    Values are ``true`` and ``false``.
 
    Always defined.
 
 os
    The operating system the build is produced for. Values for tier-1
-   supported platforms are ``linux``, ``win``, ``mac``, and
+   supported platforms are ``linux``, ``win``, ``mac``, ``b2g``, and
    ``android``. For other platforms, the value is the lowercase version
    of the ``OS_TARGET`` variable from ``config.status``.
 
    Always defined.
 
 processor
    Information about the processor architecture this build targets.
 
--- a/build/unix/mozconfig.linux
+++ b/build/unix/mozconfig.linux
@@ -2,17 +2,26 @@ if [ "x$IS_NIGHTLY" = "xyes" ]; then
   # Some nightlies (eg: Mulet) don't want these set.
   MOZ_AUTOMATION_UPDATE_PACKAGING=${MOZ_AUTOMATION_UPDATE_PACKAGING-1}
 fi
 
 . "$topsrcdir/build/mozconfig.common"
 
 TOOLTOOL_DIR=${TOOLTOOL_DIR:-$topsrcdir}
 
-# We deal with valgrind builds here
-CC="$TOOLTOOL_DIR/gcc/bin/gcc"
-CXX="$TOOLTOOL_DIR/gcc/bin/g++"
+# some b2g desktop builds still happen on i686 machines, and the tooltool
+# toolchain is x86_64 only.
+# We also deal with valgrind builds here, they don't use tooltool manifests at
+# all yet.
+if [ -z "$no_tooltool" ]
+then
+  CC="$TOOLTOOL_DIR/gcc/bin/gcc"
+  CXX="$TOOLTOOL_DIR/gcc/bin/g++"
 
-# We want to make sure we use binutils and other binaries in the tooltool
-# package.
-mk_add_options "export PATH=$TOOLTOOL_DIR/gcc/bin:$PATH"
+  # We want to make sure we use binutils and other binaries in the tooltool
+  # package.
+  mk_add_options "export PATH=$TOOLTOOL_DIR/gcc/bin:$PATH"
+else
+  CC="/tools/gcc-4.7.3-0moz1/bin/gcc"
+  CXX="/tools/gcc-4.7.3-0moz1/bin/g++"
+fi
 
 . "$topsrcdir/build/unix/mozconfig.stdcxx"
--- a/devtools/docs/backend/actor-registration.md
+++ b/devtools/docs/backend/actor-registration.md
@@ -1,17 +1,17 @@
 # How to register an actor
 
 ## Tab actors vs. global actors
 
 Tab actors are the most common types of actors. That's the type of actors you will most probably be adding.
 
-Tab actors target a document, this could be a tab in Firefox or a remote document in Firefox for Android/Safari/Chrome for Android (via Valence).
+Tab actors target a document, this could be a tab in Firefox, an app on B2G or a remote document in Firefox for Android/Safari/Chrome for Android (via Valence).
 
-Global actors however are for the rest, for things not related to any particular document but instead for things global to the whole Firefox/Chrome/Safari intance the toolbox is connected to (e.g. the preference actor).
+Global actors however are for the rest, for things not related to any particular document but instead for things global to the whole Firefox/B2G/Chrome/Safari intance the toolbox is connected to (e.g. the preference actor).
 
 ## The DebuggerServer.registerModule function
 
 To register a tab actor:
 
 ```
 DebuggerServer.registerModule("devtools/server/actors/webconsole", {
   prefix: "console",
@@ -33,9 +33,9 @@ DebuggerServer.registerModule("devtools/
 If you are adding a new built-in devtools actor, you should be registering it using `DebuggerServer.registerModule` in `_addBrowserActors` or `addTabActors` in `/devtools/server/main.js`.
 
 If you are adding a new actor from an add-on, you should call `DebuggerServer.registerModule` directly from your add-on code.
 
 ## A note about lazy registration
 
 The `DebuggerServer` loads and creates all of the actors lazily to keep the initial memory usage down (which is extremely important on lower end devices).
 
-It becomes especially important when debugging pages with e10s when there are more than one process, because that's when we need to spawn a `DebuggerServer` per process (it may not be immediately obvious that the server in the main process is mostly only here for piping messages to the actors in the child process).
+It becomes especially important when debugging apps on b2g or pages with e10s when there are more than one process, because that's when we need to spawn a `DebuggerServer` per process (it may not be immediately obvious that the server in the main process is mostly only here for piping messages to the actors in the child process).
--- a/devtools/shared/system.js
+++ b/devtools/shared/system.js
@@ -34,17 +34,19 @@ loader.lazyGetter(this, "endianness", ()
   return "BE";
 });
 
 const APP_MAP = {
   "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}": "firefox",
   "{3550f703-e582-4d05-9a08-453d09bdfdc6}": "thunderbird",
   "{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}": "seamonkey",
   "{718e30fb-e89b-41dd-9da7-e25a45638b28}": "sunbird",
-  "{aa3c5121-dab2-40e2-81ca-7ea25febc110}": "mobile/android"
+  "{3c2e2abc-06d4-11e1-ac3b-374f68613e61}": "b2g",
+  "{aa3c5121-dab2-40e2-81ca-7ea25febc110}": "mobile/android",
+  "{a23983c0-fd0e-11dc-95ff-0800200c9a66}": "mobile/xul"
 };
 
 var CACHED_INFO = null;
 
 async function getSystemInfo() {
   if (CACHED_INFO) {
     return CACHED_INFO;
   }
@@ -61,18 +63,32 @@ async function getSystemInfo() {
     os,
     brandName;
   let appid = appInfo.ID;
   let apptype = APP_MAP[appid];
   let geckoVersion = appInfo.platformVersion;
   let hardware = "unknown";
   let version = "unknown";
 
-  os = appInfo.OS;
-  version = appInfo.version;
+  // B2G specific
+  if (apptype === "b2g") {
+    os = "B2G";
+    // `getSetting` does not work in child processes on b2g.
+    // TODO bug 1205797, make this work in child processes.
+    try {
+      hardware = await exports.getSetting("deviceinfo.hardware");
+      version = await exports.getSetting("deviceinfo.os");
+    } catch (e) {
+      // Ignore.
+    }
+  } else {
+    // Not B2G
+    os = appInfo.OS;
+    version = appInfo.version;
+  }
 
   let bundle = Services.strings.createBundle("chrome://branding/locale/brand.properties");
   if (bundle) {
     brandName = bundle.GetStringFromName("brandFullName");
   } else {
     brandName = null;
   }
 
@@ -104,16 +120,17 @@ async function getSystemInfo() {
     vendor: appInfo.vendor,
 
     // Name of the application, like "Firefox", "Thunderbird".
     name: appInfo.name,
 
     // The application's version, for example "0.8.0+" or "3.7a1pre".
     // Typically, the version of Firefox, for example.
     // It is different than the version of Gecko or the XULRunner platform.
+    // On B2G, this is the Gaia version.
     version,
 
     // The application's build ID/date, for example "2004051604".
     appbuildid: appInfo.appBuildID,
 
     // The build ID/date of Gecko and the XULRunner platform.
     platformbuildid: appInfo.platformBuildID,
     geckobuildid: appInfo.platformBuildID,
@@ -134,16 +151,17 @@ async function getSystemInfo() {
     // Returns the endianness of the architecture: either "LE" or "BE"
     endianness: endianness,
 
     // Returns the hostname of the machine
     hostname: hostname,
 
     // Name of the OS type. Typically the same as `uname -s`. Possible values:
     // https://developer.mozilla.org/en/OS_TARGET
+    // Also may be "B2G".
     os,
     platform: os,
 
     // hardware and version info from `deviceinfo.hardware`
     // and `deviceinfo.os`.
     hardware,
 
     // Type of process architecture running:
@@ -248,16 +266,17 @@ function getScreenDimensions() {
 }
 
 function getSetting(name) {
   let deferred = defer();
 
   if ("@mozilla.org/settingsService;1" in Cc) {
     let settingsService;
 
+    // settingsService fails in b2g child processes
     // TODO bug 1205797, make this work in child processes.
     try {
       settingsService = Cc["@mozilla.org/settingsService;1"]
                           .getService(Ci.nsISettingsService);
     } catch (e) {
       return promise.reject(e);
     }
 
--- a/dom/cache/test/mochitest/serviceworker_driver.js
+++ b/dom/cache/test/mochitest/serviceworker_driver.js
@@ -1,12 +1,19 @@
 // Any copyright is dedicated to the Public Domain.
 // http://creativecommons.org/publicdomain/zero/1.0/
 
 function serviceWorkerTestExec(testFile) {
+  var isB2G = !navigator.userAgent.includes("Android") &&
+              /Mobile|Tablet/.test(navigator.userAgent);
+  if (isB2G) {
+    // TODO B2G doesn't support running service workers for now due to bug 1137683.
+    dump("Skipping running the test in SW until bug 1137683 gets fixed.\n");
+    return Promise.resolve();
+  }
   return new Promise(function(resolve, reject) {
     function setupSW(registration) {
       var worker = registration.waiting ||
                    registration.active;
 
       window.addEventListener("message",function onMessage(event) {
         if (event.data.context != "ServiceWorker") {
           return;
--- a/dom/canvas/test/webgl-conf/generated-mochitest.ini
+++ b/dom/canvas/test/webgl-conf/generated-mochitest.ini
@@ -1,15 +1,15 @@
 # This is a GENERATED FILE. Do not edit it directly.
 # Regenerated it by using `python generate-wrappers-and-manifest.py`.
 # Mark failing (fail-if) and crashing (skip-if) tests in mochitest-errata.ini.
 
 [DEFAULT]
 subsuite = webgl
-skip-if = (os == 'linux') && (buildapp == 'mulet')
+skip-if = os == 'b2g' || ((os == 'linux') && (buildapp == 'mulet'))
 
 support-files = always-fail.html
                 checkout/00_test_list.txt
                 checkout/CONFORMANCE_RULES.txt
                 checkout/README.md
                 checkout/closure-library/AUTHORS
                 checkout/closure-library/CONTRIBUTING
                 checkout/closure-library/LICENSE
@@ -7532,17 +7532,17 @@ skip-if = (os == 'mac')
 skip-if = (os == 'android')
 [generated/test_conformance__canvas__texture-bindings-unaffected-on-resize.html]
 [generated/test_conformance__canvas__to-data-url-test.html]
 [generated/test_conformance__canvas__viewport-unchanged-upon-resize.html]
 skip-if = (os == 'mac')
 [generated/test_conformance__context__constants-and-properties.html]
 [generated/test_conformance__context__context-attribute-preserve-drawing-buffer.html]
 [generated/test_conformance__context__context-attributes-alpha-depth-stencil-antialias.html]
-skip-if = (os == 'linux') || (os == 'android')
+skip-if = (os == 'b2g') || (os == 'linux') || (os == 'android')
 fail-if = (os == 'mac' && os_version == '10.6')
 [generated/test_conformance__context__context-creation-and-destruction.html]
 [generated/test_conformance__context__context-creation.html]
 skip-if = (os == 'android')
 [generated/test_conformance__context__context-eviction-with-garbage-collection.html]
 skip-if = (os == 'android')
 [generated/test_conformance__context__context-hidden-alpha.html]
 [generated/test_conformance__context__context-lost-restored.html]
@@ -7926,20 +7926,22 @@ fail-if = (os == 'android')
 [generated/test_conformance__glsl__misc__struct-specifiers-in-uniforms.html]
 [generated/test_conformance__glsl__misc__struct-unary-operators.html]
 [generated/test_conformance__glsl__misc__ternary-operator-on-arrays.html]
 [generated/test_conformance__glsl__misc__ternary-operators-in-global-initializers.html]
 [generated/test_conformance__glsl__misc__ternary-operators-in-initializers.html]
 [generated/test_conformance__glsl__misc__uniform-location-length-limits.html]
 [generated/test_conformance__glsl__reserved___webgl_field.vert.html]
 [generated/test_conformance__glsl__reserved___webgl_function.vert.html]
+fail-if = (os == 'b2g')
 [generated/test_conformance__glsl__reserved___webgl_struct.vert.html]
 [generated/test_conformance__glsl__reserved___webgl_variable.vert.html]
 [generated/test_conformance__glsl__reserved__webgl_field.vert.html]
 [generated/test_conformance__glsl__reserved__webgl_function.vert.html]
+fail-if = (os == 'b2g')
 [generated/test_conformance__glsl__reserved__webgl_struct.vert.html]
 [generated/test_conformance__glsl__reserved__webgl_variable.vert.html]
 [generated/test_conformance__glsl__samplers__glsl-function-texture2d-bias.html]
 [generated/test_conformance__glsl__samplers__glsl-function-texture2dlod.html]
 [generated/test_conformance__glsl__samplers__glsl-function-texture2dproj.html]
 skip-if = (os == 'android')
 [generated/test_conformance__glsl__samplers__glsl-function-texture2dprojlod.html]
 skip-if = (os == 'android')
@@ -7961,30 +7963,31 @@ skip-if = (os == 'linux')
 [generated/test_conformance__limits__gl-min-uniforms.html]
 [generated/test_conformance__misc__bad-arguments-test.html]
 skip-if = (os == 'mac') || (os == 'win') || (os == 'linux') || (os == 'android')
 [generated/test_conformance__misc__boolean-argument-conversion.html]
 skip-if = (os == 'android')
 [generated/test_conformance__misc__delayed-drawing.html]
 skip-if = (os == 'android' && android_version == '10')
 [generated/test_conformance__misc__error-reporting.html]
+fail-if = (os == 'b2g')
 [generated/test_conformance__misc__expando-loss.html]
 [generated/test_conformance__misc__functions-returning-strings.html]
 [generated/test_conformance__misc__instanceof-test.html]
 [generated/test_conformance__misc__invalid-passed-params.html]
 skip-if = (os == 'android') || (os == 'linux')
 [generated/test_conformance__misc__is-object.html]
 [generated/test_conformance__misc__null-object-behaviour.html]
 [generated/test_conformance__misc__object-deletion-behaviour.html]
 skip-if = (os == 'android' && debug)
 fail-if = (os == 'android')
 [generated/test_conformance__misc__shader-precision-format.html]
 skip-if = (os == 'android')
 [generated/test_conformance__misc__type-conversion-test.html]
-skip-if = (os == 'android') || (os == 'linux')
+skip-if = (os == 'android') || (os == 'b2g') || (os == 'linux')
 fail-if = (os == 'linux')
 [generated/test_conformance__misc__uninitialized-test.html]
 skip-if = (os == 'android')
 [generated/test_conformance__misc__webgl-specific.html]
 [generated/test_conformance__more__conformance__constants.html]
 [generated/test_conformance__more__conformance__getContext.html]
 [generated/test_conformance__more__conformance__methods.html]
 [generated/test_conformance__more__conformance__quickCheckAPI-A.html]
@@ -8200,16 +8203,17 @@ fail-if = (os == 'mac' && os_version == 
 [generated/test_conformance__ogles__GL__swizzlers__swizzlers_105_to_112.html]
 [generated/test_conformance__ogles__GL__swizzlers__swizzlers_113_to_120.html]
 [generated/test_conformance__ogles__GL__tan__tan_001_to_006.html]
 [generated/test_conformance__ogles__GL__vec3__vec3_001_to_008.html]
 [generated/test_conformance__ogles__GL__vec__vec_001_to_008.html]
 [generated/test_conformance__ogles__GL__vec__vec_009_to_016.html]
 [generated/test_conformance__ogles__GL__vec__vec_017_to_018.html]
 [generated/test_conformance__programs__get-active-test.html]
+fail-if = (os == 'b2g')
 [generated/test_conformance__programs__gl-bind-attrib-location-long-names-test.html]
 [generated/test_conformance__programs__gl-bind-attrib-location-test.html]
 [generated/test_conformance__programs__gl-get-active-attribute.html]
 [generated/test_conformance__programs__gl-get-active-uniform.html]
 [generated/test_conformance__programs__gl-getshadersource.html]
 [generated/test_conformance__programs__gl-shader-test.html]
 [generated/test_conformance__programs__invalid-UTF-16.html]
 [generated/test_conformance__programs__program-infolog.html]
--- a/dom/canvas/test/webgl-conf/mochitest-errata.ini
+++ b/dom/canvas/test/webgl-conf/mochitest-errata.ini
@@ -18,18 +18,19 @@
 #   https://msdn.microsoft.com/en-us/library/windows/desktop/ms724832%28v=vs.85%29.aspx
 #   * Windows 7: 6.1
 #   * Windows 8: 6.2
 #   * Windows 8.1: 6.3
 #   * Windows 10: 10.0
 
 [DEFAULT]
 subsuite = webgl
+# Skip B2G for now, until we get a handle on the longer tail of emulator bugs.
 # Bug 1136181 disabled on Mulet for intermittent failures
-skip-if = (os == 'linux') && (buildapp == 'mulet')
+skip-if = os == 'b2g' || ((os == 'linux') && (buildapp == 'mulet'))
 
 [generated/test_..__always-fail.html]
 fail-if = 1
 
 ####################
 # Tests requesting non-local network connections.
 
 [generated/test_conformance__more__functions__readPixelsBadArgs.html]
@@ -70,18 +71,18 @@ skip-if = (os == 'android') || (os == 'l
 # Timeout on D3D11
 skip-if = (os == 'win')
 
 ########################################################################
 # Complicated
 
 [generated/test_conformance__context__context-attributes-alpha-depth-stencil-antialias.html]
 fail-if = (os == 'mac' && os_version == '10.6')
-# Asserts on linux debug. Crashes on Android.
-skip-if = (os == 'linux') || (os == 'android')
+# Asserts on 'B2G ICS Emulator Debug' and linux debug. Crashes on Android.
+skip-if = (os == 'b2g') || (os == 'linux') || (os == 'android')
 
 [generated/test_conformance__extensions__webgl-draw-buffers.html]
 # Crashes
 skip-if = (os == 'linux')
 
 [generated/test_conformance__glsl__constructors__glsl-construct-bvec3.html]
 # Crashes from libglsl.so
 # application crashed [@ jemalloc_crash] on Android
@@ -106,18 +107,18 @@ skip-if = ((os == 'linux') && asan)
 [generated/test_conformance__glsl__bugs__sampler-array-using-loop-index.html]
 # Testfail on Linux after removing SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX.
 # Only happen on tryserver
 fail-if = (os == 'linux')
 
 [generated/test_conformance__misc__type-conversion-test.html]
 fail-if = (os == 'linux')
 # Resets device on Android 2.3.
-# Crashes on desktop Linux, and Mulet Linux x64.
-skip-if = (os == 'android') || (os == 'linux')
+# Crashes on B2G ICS Emulator, desktop Linux, and Mulet Linux x64.
+skip-if = (os == 'android') || (os == 'b2g') || (os == 'linux')
 
 [generated/test_conformance__misc__object-deletion-behaviour.html]
 fail-if = (os == 'android')
 # void mozilla::gl::GLContext::fDetachShader(GLuint, GLuint): Generated unexpected GL_INVALID_VALUE error. (0x0501)
 skip-if = (os == 'android' && debug)
 
 [generated/test_conformance__extensions__oes-vertex-array-object.html]
 fail-if = (os == 'mac') || (os == 'linux') || (os == 'win')
@@ -332,34 +333,36 @@ fail-if = (os == 'mac') || (os == 'win')
 [generated/test_2_conformance__textures__video__tex-2d-rgba-rgba-unsigned_byte.html]
 fail-if = (os == 'mac') || (os == 'win')
 [generated/test_2_conformance__textures__video__tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html]
 fail-if = (os == 'mac') || (os == 'win')
 [generated/test_2_conformance__textures__video__tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html]
 fail-if = (os == 'mac') || (os == 'win')
 ########################################################################
 # "tst-linux{32,64}-spot-NNN" Slaves:
-#   Android 2.3, Linux, and Mulet.
+#   Android 2.3, B2G Emu, Linux, and Mulet.
 # Android: os == 'android'. (Not enough info to separate out 2.3)
+# B2G Emu: os == 'b2g'.
 # Linux: os == 'linux'.
-# Mulet: buildapp == 'mulet'.
+# Mulet: os == 'b2g' && buildapp == 'mulet'.
 [generated/test_conformance__glsl__bugs__temp-expressions-should-not-crash.html]
 # Coincidentally enough, crashes on Linux and Android 4.0.
 skip-if = (os == 'android') || (os == 'linux')
 [generated/test_conformance__misc__invalid-passed-params.html]
 # Causes consistent *blues*: "DMError: Remote Device Error: unable to
 # connect to 127.0.0.1 after 5 attempts" on 'Android 2.3 Opt'.
 skip-if = (os == 'android') || (os == 'linux')
 [generated/test_conformance__ogles__GL__functions__functions_001_to_008.html]
 fail-if = (os == 'android')
 [generated/test_conformance__ogles__GL__sin__sin_001_to_006.html]
 fail-if = (os == 'android')
 [generated/test_conformance__reading__read-pixels-test.html]
 # Causes consistent *blues*: "DMError: Remote Device Error: unable to
 # connect to 127.0.0.1 after 5 attempts" on 'Android 2.3 Opt'.
+# Crashes near on B2G ICS Emulator.
 skip-if = (os == 'android') || (os == 'linux')
 [generated/test_conformance__textures__misc__texture-upload-size.html]
 # application crashed [@ mozilla::WebGLTexture::TexSubImage]
 skip-if = (os == 'win') || (os == 'android')
 
 ########################################################################
 ########################################################################
 # Android
@@ -575,20 +578,26 @@ skip-if = (os == 'android')
 # Crashes
 skip-if = (os == 'android')
 [generated/test_conformance__renderbuffers__framebuffer-object-attachment.html]
 # Crashes
 skip-if = (os == 'android')
 
 ########################################################################
 ########################################################################
+# B2G
 [generated/test_conformance__glsl__reserved___webgl_function.vert.html]
+fail-if = (os == 'b2g')
 [generated/test_conformance__glsl__reserved__webgl_function.vert.html]
+fail-if = (os == 'b2g')
 [generated/test_conformance__misc__error-reporting.html]
+fail-if = (os == 'b2g')
 [generated/test_conformance__programs__get-active-test.html]
+fail-if = (os == 'b2g')
+
 
 ########################################################################
 ########################################################################
 # Linux
 [generated/test_conformance__glsl__constructors__glsl-construct-vec-mat-corner-cases.html]
 # mozalloc_abort in libglsl.so
 skip-if = (os == 'linux')
 [generated/test_conformance__glsl__constructors__glsl-construct-vec3.html]
--- a/mobile/android/modules/FormAssistant.jsm
+++ b/mobile/android/modules/FormAssistant.jsm
@@ -230,16 +230,17 @@ var FormAssistant = {
     };
 
     this._formAutoCompleteService.autoCompleteSearchAsync(aElement.name || aElement.id,
                                                           aSearchString, aElement, null,
                                                           null, resultsAvailable);
   },
 
   /**
+   * (Copied from mobile/xul/chrome/content/forms.js)
    * This function is similar to getListSuggestions from
    * components/satchel/src/nsInputListAutoComplete.js but sadly this one is
    * used by the autocomplete.xml binding which is not in used in fennec
    */
   _getListSuggestions: function(aElement) {
     if (!(aElement instanceof Ci.nsIDOMHTMLInputElement) || !aElement.list) {
       return [];
     }
--- a/testing/mozbase/moztest/tests/test.py
+++ b/testing/mozbase/moztest/tests/test.py
@@ -36,16 +36,17 @@ class Result(unittest.TestCase):
 
 
 class Collection(unittest.TestCase):
 
     def setUp(self):
         c1 = TestContext('host1')
         c2 = TestContext('host2')
         c3 = TestContext('host2')
+        c3.os = 'B2G'
         c4 = TestContext('host1')
 
         t1 = TestResult('t1', context=c1)
         t2 = TestResult('t2', context=c2)
         t3 = TestResult('t3', context=c3)
         t4 = TestResult('t4', context=c4)
 
         self.collection = TestResultCollection('tests')
--- a/testing/mozbase/mozversion/tests/manifest.ini
+++ b/testing/mozbase/mozversion/tests/manifest.ini
@@ -1,5 +1,6 @@
 [DEFAULT]
 subsuite = mozbase, os == "linux"
 [test_binary.py]
 [test_sources.py]
+[test_b2g.py]
 [test_apk.py]
--- a/testing/mozbase/packages.txt
+++ b/testing/mozbase/packages.txt
@@ -1,9 +1,10 @@
 manifestparser.pth:testing/mozbase/manifestparser
+mozb2g.pth:testing/mozbase/mozb2g
 mozcrash.pth:testing/mozbase/mozcrash
 mozdebug.pth:testing/mozbase/mozdebug
 mozdevice.pth:testing/mozbase/mozdevice
 mozfile.pth:testing/mozbase/mozfile
 mozhttpd.pth:testing/mozbase/mozhttpd
 mozinfo.pth:testing/mozbase/mozinfo
 mozinstall.pth:testing/mozbase/mozinstall
 mozleak.pth:testing/mozbase/mozleak
--- a/testing/mozharness/configs/multi_locale/standalone_mozilla-central.py
+++ b/testing/mozharness/configs/multi_locale/standalone_mozilla-central.py
@@ -1,21 +1,21 @@
-
 import os
 # The name of the directory we'll pull our source into.
 BUILD_DIR = "mozilla-central"
 # This is everything that comes after https://hg.mozilla.org/
 # e.g. "releases/mozilla-aurora"
 REPO_PATH = "mozilla-central"
 # This is where the l10n repos are (everything after https://hg.mozilla.org/)
 # for mozilla-central, that's "l10n-central".
 # For mozilla-aurora, that's "releases/l10n/mozilla-aurora"
 L10N_REPO_PATH = "l10n-central"
 # Currently this is assumed to be a subdirectory of your build dir
 OBJDIR = "objdir-droid"
+# Set this to mobile/xul for XUL Fennec
 ANDROID_DIR = "mobile/android"
 # Absolute path to your mozconfig.
 # By default it looks at "./mozconfig"
 MOZCONFIG = os.path.join(os.getcwd(), "mozconfig")
 
 config = {
     "work_dir": ".",
     "log_name": "multilocale",
--- a/toolkit/nss.configure
+++ b/toolkit/nss.configure
@@ -4,13 +4,13 @@
 # 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/.
 
 
 # DBM support in NSS
 # ==============================================================
 @depends(build_project, '--help')
 def dbm_default(build_project, _):
-    return build_project != 'mobile/android'
+    return build_project not in ('mobile/android', 'b2g', 'b2g/graphene')
 
 option('--enable-dbm', default=dbm_default, help='Enable building DBM')
 
 set_config('NSS_DISABLE_DBM', depends('--enable-dbm')(lambda x: not x))
--- a/toolkit/toolkit.mozbuild
+++ b/toolkit/toolkit.mozbuild
@@ -36,17 +36,18 @@ if CONFIG['ENABLE_TESTS']:
 DIRS += [
     '/toolkit/library/rust',
 ]
 
 if CONFIG['MOZ_SANDBOX']:
     DIRS += ['/security/sandbox']
 
 DIRS += [
-    # Depends on NSS and NSPR
+    # Depends on NSS and NSPR, and must be built after sandbox or else B2G emulator
+    # builds fail.
     '/security/certverifier',
     # Depends on certverifier
     '/security/apps',
 ]
 
 # the signing related bits of libmar depend on nss
 if CONFIG['MOZ_UPDATER']:
     DIRS += ['/modules/libmar']
--- a/widget/NativeKeyToDOMKeyName.h
+++ b/widget/NativeKeyToDOMKeyName.h
@@ -20,18 +20,22 @@
 #define KEY_MAP_WIN_JPN(aCPPKeyName, aNativeKey)
 #define KEY_MAP_WIN_KOR(aCPPKeyName, aNativeKey)
 #define KEY_MAP_WIN_OTH(aCPPKeyName, aNativeKey)
 #define KEY_MAP_WIN_CMD(aCPPKeyName, aAppCommand)
 // Mac OS X
 #define KEY_MAP_COCOA(aCPPKeyName, aNativeKey)
 // GTK
 #define KEY_MAP_GTK(aCPPKeyName, aNativeKey)
+// Android and B2G
+#define KEY_MAP_ANDROID(aCPPKeyName, aNativeKey)
 // Only for Android
-#define KEY_MAP_ANDROID(aCPPKeyName, aNativeKey)
+#define KEY_MAP_ANDROID_EXCEPT_B2G(aCPPKeyName, aNativeKey)
+// Only for B2G
+#define KEY_MAP_B2G(aCPPKeyName, aNativeKey)
 
 #if defined(XP_WIN)
 #if defined(NS_NATIVE_KEY_TO_DOM_KEY_NAME_INDEX)
 // KEY_MAP_WIN() defines the mapping not depending on keyboard layout.
 #undef KEY_MAP_WIN
 #define KEY_MAP_WIN(aCPPKeyName, aNativeKey) \
   NS_NATIVE_KEY_TO_DOM_KEY_NAME_INDEX(aNativeKey, KEY_NAME_INDEX_##aCPPKeyName)
 #elif defined(NS_JAPANESE_NATIVE_KEY_TO_DOM_KEY_NAME_INDEX)
@@ -71,16 +75,19 @@
 #elif defined(MOZ_WIDGET_GTK)
 #undef KEY_MAP_GTK
 #define KEY_MAP_GTK(aCPPKeyName, aNativeKey) \
   NS_NATIVE_KEY_TO_DOM_KEY_NAME_INDEX(aNativeKey, KEY_NAME_INDEX_##aCPPKeyName)
 #elif defined(ANDROID)
 #undef KEY_MAP_ANDROID
 #define KEY_MAP_ANDROID(aCPPKeyName, aNativeKey) \
   NS_NATIVE_KEY_TO_DOM_KEY_NAME_INDEX(aNativeKey, KEY_NAME_INDEX_##aCPPKeyName)
+#undef KEY_MAP_ANDROID_EXCEPT_B2G
+#define KEY_MAP_ANDROID_EXCEPT_B2G(aCPPKeyName, aNativeKey) \
+  NS_NATIVE_KEY_TO_DOM_KEY_NAME_INDEX(aNativeKey, KEY_NAME_INDEX_##aCPPKeyName)
 #endif
 
 /******************************************************************************
  * Modifier Keys
  ******************************************************************************/
 // Alt
 KEY_MAP_WIN     (Alt, VK_MENU)
 KEY_MAP_WIN     (Alt, VK_LMENU)
@@ -1044,26 +1051,27 @@ KEY_MAP_ANDROID (AppSwitch, AKEYCODE_APP
 
 // Call
 KEY_MAP_ANDROID (Call, AKEYCODE_CALL)
 
 // Camera
 KEY_MAP_ANDROID (Camera, AKEYCODE_CAMERA)
 
 // CameraFocus
-KEY_MAP_ANDROID(CameraFocus, AKEYCODE_FOCUS)
+KEY_MAP_ANDROID_EXCEPT_B2G(CameraFocus, AKEYCODE_FOCUS)
 
 // EndCall
 KEY_MAP_ANDROID (EndCall, AKEYCODE_ENDCALL)
 
 // GoBack
 KEY_MAP_ANDROID (GoBack, AKEYCODE_BACK)
 
 // GoHome
-KEY_MAP_ANDROID(GoHome,     AKEYCODE_HOME)
+KEY_MAP_ANDROID_EXCEPT_B2G(GoHome,     AKEYCODE_HOME)
+KEY_MAP_B2G               (HomeScreen, AKEYCODE_HOME)
 
 // HeadsetHook
 KEY_MAP_ANDROID (HeadsetHook, AKEYCODE_HEADSETHOOK)
 
 // Notification
 KEY_MAP_ANDROID (Notification, AKEYCODE_NOTIFICATION)
 
 // MannerMode
@@ -1275,8 +1283,10 @@ KEY_MAP_ANDROID (SoftRight, AKEYCODE_SOF
 #undef KEY_MAP_WIN
 #undef KEY_MAP_WIN_JPN
 #undef KEY_MAP_WIN_KOR
 #undef KEY_MAP_WIN_OTH
 #undef KEY_MAP_WIN_CMD
 #undef KEY_MAP_COCOA
 #undef KEY_MAP_GTK
 #undef KEY_MAP_ANDROID
+#undef KEY_MAP_ANDROID_EXCEPT_B2G
+#undef KEY_MAP_B2G