Merge the last PGO-green inbound changeset to m-c.
authorRyan VanderMeulen <ryanvm@gmail.com>
Thu, 27 Sep 2012 20:52:01 -0400
changeset 108445 2d96ee8d9dd44ac0e80d79b33828f05cef79cedb
parent 108361 510300b96e626fd649d9311efcab359c037461ea (current diff)
parent 108444 3aab17dffac7e5fc6aed9911de4b6f8728766c10 (diff)
child 108446 64558e8ed7235e7284b17568832f44a9eb24c7ed
child 108466 2fb8343e929fcb8bb9c58793e6933ddc2cfe44ff
push id82
push usershu@rfrn.org
push dateFri, 05 Oct 2012 13:20:22 +0000
milestone18.0a1
Merge the last PGO-green inbound changeset to m-c.
mobile/android/base/resources/drawable-hdpi-v11/ic_menu_desktop_mode.png
mobile/android/base/resources/drawable-mdpi-v11/ic_menu_desktop_mode.png
mobile/android/base/resources/drawable-xhdpi-v11/ic_menu_desktop_mode.png
netwerk/base/public/nsIProxyAutoConfig.idl
netwerk/base/src/nsProxyAutoConfig.js
netwerk/base/src/nsProxyAutoConfig.manifest
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -485,17 +485,18 @@ pref("extensions.getAddons.cache.enabled
 
 // Context Menu
 pref("ui.click_hold_context_menus", true);
 pref("ui.click_hold_context_menus.delay", 1000);
 
 // Enable device storage
 pref("device.storage.enabled", true);
 
-pref("media.plugins.enabled", true);
+pref("media.plugins.enabled", false);
+pref("media.omx.enabled", true);
 
 // Disable printing (particularly, window.print())
 pref("dom.disable_window_print", true);
 
 // Disable window.showModalDialog
 pref("dom.disable_window_showModalDialog", true);
 
 // Enable new experimental html forms
--- a/b2g/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -367,18 +367,16 @@
 #ifdef MOZ_GTK2
 @BINPATH@/components/nsFilePicker.manifest
 @BINPATH@/components/nsFilePicker.js
 #endif
 @BINPATH@/components/nsHelperAppDlg.manifest
 @BINPATH@/components/nsHelperAppDlg.js
 @BINPATH@/components/nsDownloadManagerUI.manifest
 @BINPATH@/components/nsDownloadManagerUI.js
-@BINPATH@/components/nsProxyAutoConfig.manifest
-@BINPATH@/components/nsProxyAutoConfig.js
 @BINPATH@/components/NetworkGeolocationProvider.manifest
 @BINPATH@/components/NetworkGeolocationProvider.js
 @BINPATH@/components/GPSDGeolocationProvider.manifest
 @BINPATH@/components/GPSDGeolocationProvider.js
 @BINPATH@/components/nsSidebar.manifest
 @BINPATH@/components/nsSidebar.js
 @BINPATH@/components/extensions.manifest
 @BINPATH@/components/addonManager.js
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -4467,16 +4467,25 @@ var TabsProgressListener = {
     if (aRequest instanceof Ci.nsIChannel &&
         aStateFlags & Ci.nsIWebProgressListener.STATE_START &&
         aStateFlags & Ci.nsIWebProgressListener.STATE_IS_DOCUMENT &&
         gCrashReporter.enabled) {
       gCrashReporter.annotateCrashReport("URL", aRequest.URI.spec);
     }
 #endif
 
+    // Collect telemetry data about tab load times.
+    if (aWebProgress.DOMWindow == aWebProgress.DOMWindow.top &&
+        aStateFlags & Ci.nsIWebProgressListener.STATE_IS_WINDOW) {
+      if (aStateFlags & Ci.nsIWebProgressListener.STATE_START)
+        TelemetryStopwatch.start("FX_PAGE_LOAD_MS", aBrowser);
+      else if (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP)
+        TelemetryStopwatch.finish("FX_PAGE_LOAD_MS", aBrowser);
+    }
+
     // Attach a listener to watch for "click" events bubbling up from error
     // pages and other similar page. This lets us fix bugs like 401575 which
     // require error page UI to do privileged things, without letting error
     // pages have any privilege themselves.
     // We can't look for this during onLocationChange since at that point the
     // document URI is not yet the about:-uri of the error page.
 
     if (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP &&
--- a/browser/confvars.sh
+++ b/browser/confvars.sh
@@ -16,17 +16,17 @@ if test "$OS_ARCH" = "WINNT"; then
 fi
 
 MOZ_CHROME_FILE_FORMAT=omni
 MOZ_SAFE_BROWSING=1
 MOZ_SERVICES_AITC=1
 MOZ_SERVICES_NOTIFICATIONS=1
 MOZ_SERVICES_SYNC=1
 MOZ_APP_VERSION=$FIREFOX_VERSION
-MOZ_EXTENSIONS_DEFAULT=" gnomevfs"
+MOZ_EXTENSIONS_DEFAULT=" gio"
 # MOZ_APP_DISPLAYNAME will be set by branding/configure.sh
 # Changing MOZ_*BRANDING_DIRECTORY requires a clobber to ensure correct results,
 # because branding dependencies are broken.
 # MOZ_BRANDING_DIRECTORY is the default branding directory used when none is
 # specified. It should never point to the "official" branding directory.
 # For mozilla-beta, mozilla-release, or mozilla-central repositories, use
 # "nightly" branding (until bug 659568 is fixed).
 # For the mozilla-aurora repository, use "aurora".
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -357,18 +357,16 @@
 #ifdef MOZ_GTK2
 @BINPATH@/components/nsFilePicker.manifest
 @BINPATH@/components/nsFilePicker.js
 #endif
 @BINPATH@/components/nsHelperAppDlg.manifest
 @BINPATH@/components/nsHelperAppDlg.js
 @BINPATH@/components/nsDownloadManagerUI.manifest
 @BINPATH@/components/nsDownloadManagerUI.js
-@BINPATH@/components/nsProxyAutoConfig.manifest
-@BINPATH@/components/nsProxyAutoConfig.js
 @BINPATH@/components/NetworkGeolocationProvider.manifest
 @BINPATH@/components/NetworkGeolocationProvider.js
 @BINPATH@/components/GPSDGeolocationProvider.manifest
 @BINPATH@/components/GPSDGeolocationProvider.js
 @BINPATH@/components/nsSidebar.manifest
 @BINPATH@/components/nsSidebar.js
 @BINPATH@/components/extensions.manifest
 @BINPATH@/components/addonManager.js
--- a/browser/installer/removed-files.in
+++ b/browser/installer/removed-files.in
@@ -82,16 +82,18 @@ components/dom_system_b2g.xpt
 components/uconvd.dll
 components/WeaveCrypto.js
 components/WeaveCrypto.manifest
 components/xmlextras.xpt
 components/xpcom.xpt
 components/xpti.dat
 components/xptitemp.dat
 components/nsMicrosummaryService.js
+components/nsProxyAutoConfig.manifest
+components/nsProxyAutoConfig.js
 D3DCompiler_42.dll
 d3dx9_42.dll
 defaults/pref/all.js
 defaults/pref/bug259708.js
 defaults/pref/bug307259.js
 defaults/pref/reporter.js
 defaults/pref/security-prefs.js
 defaults/pref/winpref.js
@@ -916,16 +918,17 @@ xpicleanup@BIN_SUFFIX@
   components/nsLoginInfo.js
   components/nsLoginManager.js
   components/nsLoginManagerPrompter.js
   components/nsPlacesAutoComplete.js
   components/nsPlacesDBFlush.js
   components/nsPlacesExpiration.js
   components/nsPrivateBrowsingService.js
   components/nsPrompter.js
+  components/nsProxyAutoConfig.manifest
   components/nsProxyAutoConfig.js
   components/nsSafebrowsingApplication.js
   components/nsSearchService.js
   components/nsSearchSuggestions.js
   components/nsSessionStartup.js
   components/nsSessionStore.js
   components/nsSetDefaultBrowser.js
   components/nsSidebar.js
--- a/caps/idl/nsIPrincipal.idl
+++ b/caps/idl/nsIPrincipal.idl
@@ -296,10 +296,10 @@ interface nsIPrincipal : nsISerializable
 [uuid(f3e177Df-6a5e-489f-80a7-2dd1481471d8)]
 interface nsIExpandedPrincipal : nsISupports
 {
   /**
    * An array of principals that the expanded principal subsumes.
    * Note: this list is not reference counted, it is shared, so 
    * should not be changed and should only be used ephemerally.
    */
-  [notxpcom] readonly attribute PrincipalArray whiteList;
+  [noscript] readonly attribute PrincipalArray whiteList;
 };
--- a/caps/src/nsSecurityManagerFactory.cpp
+++ b/caps/src/nsSecurityManagerFactory.cpp
@@ -62,25 +62,16 @@ static JSFunctionSpec PrivilegeManager_s
  * et al. so that code that worked with 4.0 can still work.
  */
 NS_IMETHODIMP 
 nsSecurityNameSet::InitializeNameSet(nsIScriptContext* aScriptContext)
 {
     JSContext* cx = aScriptContext->GetNativeContext();
     JSObject *global = JS_ObjectToInnerObject(cx, JS_GetGlobalObject(cx));
 
-    // We hide enablePrivilege behind a pref because it has been altered in a
-    // way that makes it fundamentally insecure to use in production. Mozilla
-    // uses this pref during automated testing to support legacy test code that
-    // uses enablePrivilege. If you're not doing test automation, you _must_ not
-    // flip this pref, or you will be exposing all your users to security
-    // vulnerabilities.
-    if (!Preferences::GetBool("security.enablePrivilege.enable_for_tests"))
-        return NS_OK;
-
     /*
      * Find Object.prototype's class by walking up the global object's
      * prototype chain.
      */
     JSObject *obj = global;
     JSObject *proto;
     JSAutoRequest ar(cx);
     for (;;) {
@@ -111,16 +102,25 @@ nsSecurityNameSet::InitializeNameSet(nsI
         if (obj == nullptr)
             return NS_ERROR_FAILURE;
         securityObj = JS_DefineObject(cx, obj, "security", objectClass,
                                       nullptr, 0);
         if (securityObj == nullptr)
             return NS_ERROR_FAILURE;
     }
 
+    // We hide enablePrivilege behind a pref because it has been altered in a
+    // way that makes it fundamentally insecure to use in production. Mozilla
+    // uses this pref during automated testing to support legacy test code that
+    // uses enablePrivilege. If you're not doing test automation, you _must_ not
+    // flip this pref, or you will be exposing all your users to security
+    // vulnerabilities.
+    if (!Preferences::GetBool("security.enablePrivilege.enable_for_tests"))
+        return NS_OK;
+
     /* Define PrivilegeManager object with the necessary "static" methods. */
     obj = JS_DefineObject(cx, securityObj, "PrivilegeManager", objectClass,
                           nullptr, 0);
     if (obj == nullptr)
         return NS_ERROR_FAILURE;
 
     return JS_DefineFunctions(cx, obj, PrivilegeManager_static_methods)
            ? NS_OK
--- a/configure.in
+++ b/configure.in
@@ -4841,64 +4841,58 @@ then
 fi
 
 dnl ========================================================
 dnl = GnomeVFS, GIO and GConf support module
 dnl ========================================================
 
 if test "$MOZ_X11"
 then
-    dnl build the gnomevfs extension by default only when the
+    dnl build the GIO extension by default only when the
     dnl GTK2 toolkit is in use.
     if test "$MOZ_ENABLE_GTK2"
     then
-        MOZ_ENABLE_GNOMEVFS=1
+        MOZ_ENABLE_GIO=1
         MOZ_ENABLE_GCONF=1
     fi
 
     dnl ========================================================
     dnl = GnomeVFS support module
     dnl ========================================================
-    MOZ_ARG_DISABLE_BOOL(gnomevfs,
-    [  --disable-gnomevfs      Disable GnomeVFS support ],
-        MOZ_ENABLE_GNOMEVFS=,
-        MOZ_ENABLE_GNOMEVFS=force)
+    MOZ_ARG_ENABLE_BOOL(gnomevfs,
+    [  --enable-gnomevfs       Enable GnomeVFS support (default: disabled)],
+        MOZ_ENABLE_GNOMEVFS=force,
+        MOZ_ENABLE_GNOMEVFS=)
 
     if test "$MOZ_ENABLE_GNOMEVFS"
     then
         PKG_CHECK_MODULES(MOZ_GNOMEVFS, gnome-vfs-2.0 >= $GNOMEVFS_VERSION gnome-vfs-module-2.0 >= $GNOMEVFS_VERSION,[
             MOZ_GNOMEVFS_LIBS=`echo $MOZ_GNOMEVFS_LIBS | sed 's/-llinc\>//'`
             MOZ_ENABLE_GNOMEVFS=1
             AC_DEFINE(MOZ_ENABLE_GNOMEVFS)
         ],[
             if test "$MOZ_ENABLE_GNOMEVFS" = "force"
             then
                 AC_MSG_ERROR([* * * Could not find gnome-vfs-module-2.0 >= $GNOMEVFS_VERSION])
             fi
             MOZ_ENABLE_GNOMEVFS=
         ])
-    else
-        if test `echo "$MOZ_EXTENSIONS" | grep -c gnomevfs` -ne 0; then
-            PKG_CHECK_MODULES(MOZ_GNOMEVFS, gnome-vfs-2.0 >= $GNOMEVFS_VERSION gnome-vfs-module-2.0 >= $GNOMEVFS_VERSION,[
-              MOZ_GNOMEVFS_LIBS=`echo $MOZ_GNOMEVFS_LIBS | sed 's/-llinc\>//'`
-            ])
-        fi
     fi
 
     AC_SUBST(MOZ_ENABLE_GNOMEVFS)
     AC_SUBST(MOZ_GNOMEVFS_CFLAGS)
     AC_SUBST(MOZ_GNOMEVFS_LIBS)
 
     dnl ========================================================
     dnl = GIO support module
     dnl ========================================================
-    MOZ_ARG_ENABLE_BOOL(gio,
-    [  --enable-gio            Enable GIO support (default: disabled)],
-        MOZ_ENABLE_GIO=force,
-        MOZ_ENABLE_GIO=)
+    MOZ_ARG_DISABLE_BOOL(gio,
+    [  --disable-gio           Disable GIO support],
+        MOZ_ENABLE_GIO=,
+        MOZ_ENABLE_GIO=force)
 
     if test "$MOZ_ENABLE_GIO" -a "$MOZ_ENABLE_GTK2"
     then
         PKG_CHECK_MODULES(_GTKCHECK, gtk+-2.0 >= 2.14, ,
                           [AC_MSG_ERROR([* * * Could not find gtk+-2.0 > 2.14. Required for build with gio.])])
         PKG_CHECK_MODULES(MOZ_GIO, gio-2.0 >= $GIO_VERSION,[
             MOZ_GIO_LIBS=`echo $MOZ_GIO_LIBS | sed 's/-llinc\>//'`
             MOZ_ENABLE_GIO=1
@@ -5962,33 +5956,33 @@ MOZ_ARG_ENABLE_STRING(extensions,
         option=`echo $option | sed 's/^-//'`
         MOZ_EXTENSIONS=`echo "$MOZ_EXTENSIONS" | sed "s/ ${option}//"`
     else
         MOZ_EXTENSIONS="$MOZ_EXTENSIONS $option"
     fi
 done],
     MOZ_EXTENSIONS="$MOZ_EXTENSIONS_DEFAULT")
 
-if test -z "$MOZ_ENABLE_GNOMEVFS" -a -z "$MOZ_GNOMEVFS_LIBS" -a `echo "$MOZ_EXTENSIONS" | grep -c gnomevfs` -ne 0; then
+if test -z "$MOZ_ENABLE_GNOMEVFS" -a `echo "$MOZ_EXTENSIONS" | grep -c gnomevfs` -ne 0; then
     # Suppress warning on non-X11 platforms
     if test -n "$MOZ_X11"; then
-        AC_MSG_WARN([Cannot build gnomevfs without required libraries. Removing gnomevfs from MOZ_EXTENSIONS.])
+        AC_MSG_WARN([Removing gnomevfs from MOZ_EXTENSIONS due to no --enable-gnomevfs.])
     fi
     MOZ_EXTENSIONS=`echo $MOZ_EXTENSIONS | sed -e 's|gnomevfs||'`
 fi
 
 dnl Do not build gnomevfs with libxul based apps
 if test -n "$LIBXUL_SDK_DIR" -a `echo "$MOZ_EXTENSIONS" | grep -c gnomevfs` -ne 0; then
     MOZ_EXTENSIONS=`echo $MOZ_EXTENSIONS | sed -e 's|gnomevfs||'`
 fi
 
 if test -z "$MOZ_ENABLE_GIO" -a `echo "$MOZ_EXTENSIONS" | grep -c gio` -ne 0; then
     # Suppress warning on non-X11 platforms
     if test -n "$MOZ_X11"; then
-        AC_MSG_WARN([Cannot build gio without required libraries. Removing gio from MOZ_EXTENSIONS.])
+        AC_MSG_WARN([Removing gio from MOZ_EXTENSIONS due to --disable-gio.])
     fi
     MOZ_EXTENSIONS=`echo $MOZ_EXTENSIONS | sed -e 's|gio||'`
 fi
 
 dnl Do not build gio with libxul based apps
 if test -n "$LIBXUL_SDK_DIR" -a `echo "$MOZ_EXTENSIONS" | grep -c gio` -ne 0; then
     MOZ_EXTENSIONS=`echo $MOZ_EXTENSIONS | sed -e 's|gio||'`
 fi
--- a/content/base/src/nsInProcessTabChildGlobal.cpp
+++ b/content/base/src/nsInProcessTabChildGlobal.cpp
@@ -112,16 +112,25 @@ nsInProcessTabChildGlobal::nsInProcessTa
   mIsBrowserFrame = isBrowser;
 }
 
 nsInProcessTabChildGlobal::~nsInProcessTabChildGlobal()
 {
   NS_ASSERTION(!mCx, "Couldn't release JSContext?!?");
 }
 
+/* [notxpcom] boolean markForCC (); */
+// This method isn't automatically forwarded safely because it's notxpcom, so
+// the IDL binding doesn't know what value to return.
+NS_IMETHODIMP_(bool)
+nsInProcessTabChildGlobal::MarkForCC()
+{
+  return mMessageManager ? mMessageManager->MarkForCC() : false;
+}
+
 nsresult
 nsInProcessTabChildGlobal::Init()
 {
 #ifdef DEBUG
   nsresult rv =
 #endif
   InitTabChildGlobal();
   NS_WARN_IF_FALSE(NS_SUCCEEDED(rv),
--- a/content/canvas/src/WebGLContext.cpp
+++ b/content/canvas/src/WebGLContext.cpp
@@ -324,21 +324,29 @@ WebGLContext::SetContextOptions(nsIPrope
 
     mOptions = newOpts;
     return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::SetDimensions(int32_t width, int32_t height)
 {
-    /*** early success return cases ***/
+    // Early error return cases
+
+    if (width < 0 || height < 0) {
+        GenerateWarning("Canvas size is too large (seems like a negative value wrapped)");
+        return NS_ERROR_OUT_OF_MEMORY;
+    }
 
-    if (mCanvasElement) {
-        mCanvasElement->InvalidateCanvas();
-    }
+    if (!GetCanvas())
+        return NS_ERROR_FAILURE;
+
+    // Early success return cases
+
+    GetCanvas()->InvalidateCanvas();
 
     if (gl && mWidth == width && mHeight == height)
         return NS_OK;
 
     // Zero-sized surfaces can cause problems.
     if (width == 0 || height == 0) {
         width = 1;
         height = 1;
@@ -356,20 +364,19 @@ WebGLContext::SetDimensions(int32_t widt
         mHeight = gl->OffscreenActualSize().height;
         mResetLayer = true;
 
         gl->ClearSafely();
 
         return NS_OK;
     }
 
-    /*** End of early success return cases.
-     *** At this point we know that we're not just resizing an existing context,
-     *** we are initializing a new context.
-     ***/
+    // End of early return cases.
+    // At this point we know that we're not just resizing an existing context,
+    // we are initializing a new context.
 
     // if we exceeded either the global or the per-principal limit for WebGL contexts,
     // lose the oldest-used context now to free resources. Note that we can't do that
     // in the WebGLContext constructor as we don't have a canvas element yet there.
     // Here is the right place to do so, as we are about to create the OpenGL context
     // and that is what can fail if we already have too many.
     LoseOldestWebGLContextIfLimitExceeded();
 
--- a/content/events/src/nsDOMWifiEvent.cpp
+++ b/content/events/src/nsDOMWifiEvent.cpp
@@ -124,44 +124,54 @@ nsDOMMozWifiConnectionInfoEvent::GetRelS
 NS_IMETHODIMP
 nsDOMMozWifiConnectionInfoEvent::GetLinkSpeed(int32_t* aLinkSpeed)
 {
   *aLinkSpeed = mLinkSpeed;
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsDOMMozWifiConnectionInfoEvent::GetIpAddress(nsAString& aIpAddress)
+{
+    aIpAddress = mIpAddress;
+    return NS_OK;
+}
+
+NS_IMETHODIMP
 nsDOMMozWifiConnectionInfoEvent::InitMozWifiConnectionInfoEvent(const nsAString& aType,
                                                                 bool aCanBubble,
                                                                 bool aCancelable,
                                                                 nsIVariant *aNetwork,
                                                                 int16_t aSignalStrength,
                                                                 int16_t aRelSignalStrength,
-                                                                int32_t aLinkSpeed)
+                                                                int32_t aLinkSpeed,
+                                                                const nsAString &aIpAddress)
 {
   nsresult rv = nsDOMEvent::InitEvent(aType, aCanBubble, aCancelable);
   NS_ENSURE_SUCCESS(rv, rv);
 
   mNetwork = aNetwork;
   mSignalStrength = aSignalStrength;
   mRelSignalStrength = aRelSignalStrength;
   mLinkSpeed = aLinkSpeed;
+  mIpAddress = aIpAddress;
 
   return NS_OK;
 }
 
 nsresult
 nsDOMMozWifiConnectionInfoEvent::InitFromCtor(const nsAString& aType,
                                               JSContext* aCx, jsval* aVal)
 {
   mozilla::dom::MozWifiConnectionInfoEventInit d;
   nsresult rv = d.Init(aCx, aVal);
   NS_ENSURE_SUCCESS(rv, rv);
   return InitMozWifiConnectionInfoEvent(aType, d.bubbles, d.cancelable, d.network,
-                                        d.signalStrength, d.relSignalStrength, d.linkSpeed);
+                                        d.signalStrength, d.relSignalStrength, d.linkSpeed,
+                                        d.ipAddress);
 }
 
 nsresult
 NS_NewDOMMozWifiConnectionInfoEvent(nsIDOMEvent** aInstancePtrResult,
                                     nsPresContext* aPresContext,
                                     nsEvent* aEvent) 
 {
   nsDOMMozWifiConnectionInfoEvent* e = new nsDOMMozWifiConnectionInfoEvent(aPresContext, aEvent);
--- a/content/events/src/nsDOMWifiEvent.h
+++ b/content/events/src/nsDOMWifiEvent.h
@@ -11,17 +11,17 @@
 #include "nsDOMEvent.h"
 
 class nsDOMMozWifiStatusChangeEvent : public nsDOMEvent,
                                    public nsIDOMMozWifiStatusChangeEvent
 {
 public:
   nsDOMMozWifiStatusChangeEvent(nsPresContext* aPresContext, nsEvent* aEvent)
     : nsDOMEvent(aPresContext, aEvent) {}
-                     
+
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsDOMMozWifiStatusChangeEvent, nsDOMEvent)
   // Forward to base class
   NS_FORWARD_TO_NSDOMEVENT
 
   NS_DECL_NSIDOMMOZWIFISTATUSCHANGEEVENT
 
   virtual nsresult InitFromCtor(const nsAString& aType,
@@ -32,26 +32,27 @@ private:
 };
 
 class nsDOMMozWifiConnectionInfoEvent : public nsDOMEvent,
                                         public nsIDOMMozWifiConnectionInfoEvent
 {
 public:
   nsDOMMozWifiConnectionInfoEvent(nsPresContext* aPresContext, nsEvent* aEvent)
     : nsDOMEvent(aPresContext, aEvent) {}
-                     
+
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsDOMMozWifiConnectionInfoEvent, nsDOMEvent)
   // Forward to base class
   NS_FORWARD_TO_NSDOMEVENT
 
   NS_DECL_NSIDOMMOZWIFICONNECTIONINFOEVENT
 
   virtual nsresult InitFromCtor(const nsAString& aType,
                                 JSContext* aCx, jsval* aVal);
 private:
   nsCOMPtr<nsIVariant> mNetwork;
   int16_t mSignalStrength;
   int16_t mRelSignalStrength;
   int32_t mLinkSpeed;
+  nsString mIpAddress;
 };
 
 #endif // nsDOMWifiEvent_h__
--- a/content/html/content/public/nsHTMLMediaElement.h
+++ b/content/html/content/public/nsHTMLMediaElement.h
@@ -302,16 +302,23 @@ public:
 
 #ifdef MOZ_GSTREAMER
   static bool IsH264Enabled();
   static bool IsH264Type(const nsACString& aType);
   static const char gH264Types[3][16];
   static char const *const gH264Codecs[7];
 #endif
 
+#ifdef MOZ_WIDGET_GONK
+  static bool IsOmxEnabled();
+  static bool IsH264Type(const nsACString& aType);
+  static const char gH264Types[3][16];
+  static char const *const gH264Codecs[7];
+#endif
+
 #ifdef MOZ_MEDIA_PLUGINS
   static bool IsMediaPluginsEnabled();
   static bool IsMediaPluginsType(const nsACString& aType);
 #endif
 
   /**
    * Get the mime type for this element.
    */
--- a/content/html/content/src/nsHTMLMediaElement.cpp
+++ b/content/html/content/src/nsHTMLMediaElement.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* 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 "mozilla/Util.h"
 
+#include "base/basictypes.h"
 #include "nsIDOMHTMLMediaElement.h"
 #include "nsIDOMHTMLSourceElement.h"
 #include "nsHTMLMediaElement.h"
 #include "nsTimeRanges.h"
 #include "nsGenericHTMLElement.h"
 #include "nsPresContext.h"
 #include "nsIPresShell.h"
 #include "nsGkAtoms.h"
@@ -82,16 +83,19 @@
 #endif
 #ifdef MOZ_GSTREAMER
 #include "nsGStreamerDecoder.h"
 #endif
 #ifdef MOZ_MEDIA_PLUGINS
 #include "nsMediaPluginHost.h"
 #include "nsMediaPluginDecoder.h"
 #endif
+#ifdef MOZ_WIDGET_GONK
+#include "nsMediaOmxDecoder.h"
+#endif
 
 #ifdef PR_LOGGING
 static PRLogModuleInfo* gMediaElementLog;
 static PRLogModuleInfo* gMediaElementEventsLog;
 #define LOG(type, msg) PR_LOG(gMediaElementLog, type, msg)
 #define LOG_EVENT(type, msg) PR_LOG(gMediaElementEventsLog, type, msg)
 #else
 #define LOG(type, msg)
@@ -2120,33 +2124,35 @@ nsHTMLMediaElement::IsWebMType(const nsA
       return true;
     }
   }
 
   return false;
 }
 #endif
 
-#ifdef MOZ_GSTREAMER
+#if defined(MOZ_GSTREAMER) || defined(MOZ_WIDGET_GONK)
 const char nsHTMLMediaElement::gH264Types[3][16] = {
   "video/mp4",
   "video/3gpp",
   "video/quicktime",
 };
 
 char const *const nsHTMLMediaElement::gH264Codecs[7] = {
   "avc1.42E01E",
   "avc1.42001E",
   "avc1.58A01E",
   "avc1.4D401E",
   "avc1.64001E",
   "mp4a.40.2",
   nullptr
 };
-
+#endif
+
+#ifdef MOZ_GSTREAMER
 bool
 nsHTMLMediaElement::IsH264Enabled()
 {
   return Preferences::GetBool("media.h264.enabled");
 }
 
 bool
 nsHTMLMediaElement::IsH264Type(const nsACString& aType)
@@ -2160,16 +2166,40 @@ nsHTMLMediaElement::IsH264Type(const nsA
       return true;
     }
   }
 
   return false;
 }
 #endif
 
+#ifdef MOZ_WIDGET_GONK
+bool
+nsHTMLMediaElement::IsOmxEnabled()
+{
+  return Preferences::GetBool("media.omx.enabled", false);
+}
+
+bool
+nsHTMLMediaElement::IsH264Type(const nsACString& aType)
+{
+  if (!IsOmxEnabled()) {
+    return false;
+  }
+
+  for (uint32_t i = 0; i < ArrayLength(gH264Types); ++i) {
+    if (aType.EqualsASCII(gH264Types[i])) {
+      return true;
+    }
+  }
+
+  return false;
+}
+#endif
+
 #ifdef MOZ_MEDIA_PLUGINS
 bool
 nsHTMLMediaElement::IsMediaPluginsEnabled()
 {
   return Preferences::GetBool("media.plugins.enabled");
 }
 
 bool
@@ -2222,16 +2252,22 @@ nsHTMLMediaElement::CanHandleMediaType(c
 #endif
 
 #ifdef MOZ_GSTREAMER
   if (IsH264Type(nsDependentCString(aMIMEType))) {
     *aCodecList = gH264Codecs;
     return CANPLAY_MAYBE;
   }
 #endif
+#ifdef MOZ_WIDGET_GONK
+  if (IsH264Type(nsDependentCString(aMIMEType))) {
+    *aCodecList = gH264Codecs;
+    return CANPLAY_MAYBE;
+  }
+#endif
 #ifdef MOZ_MEDIA_PLUGINS
   if (IsMediaPluginsEnabled() && GetMediaPluginHost()->FindDecoder(nsDependentCString(aMIMEType), aCodecList))
     return CANPLAY_MAYBE;
 #endif
   return CANPLAY_NO;
 }
 
 /* static */
@@ -2248,16 +2284,21 @@ bool nsHTMLMediaElement::ShouldHandleMed
 #ifdef MOZ_WEBM
   if (IsWebMType(nsDependentCString(aMIMEType)))
     return true;
 #endif
 #ifdef MOZ_GSTREAMER
   if (IsH264Type(nsDependentCString(aMIMEType)))
     return true;
 #endif
+#ifdef MOZ_WIDGET_GONK
+  if (IsH264Type(nsDependentCString(aMIMEType))) {
+    return true;
+  }
+#endif
 #ifdef MOZ_MEDIA_PLUGINS
   if (IsMediaPluginsEnabled() && GetMediaPluginHost()->FindDecoder(nsDependentCString(aMIMEType), NULL))
     return true;
 #endif
   // We should not return true for Wave types, since there are some
   // Wave codecs actually in use in the wild that we don't support, and
   // we should allow those to be handled by plugins or helper apps.
   // Furthermore people can play Wave files on most platforms by other
@@ -2364,16 +2405,24 @@ nsHTMLMediaElement::CreateDecoder(const 
 #ifdef MOZ_WAVE
   if (IsWaveType(aType)) {
     nsRefPtr<nsWaveDecoder> decoder = new nsWaveDecoder();
     if (decoder->Init(this)) {
       return decoder.forget();
     }
   }
 #endif
+#ifdef MOZ_WIDGET_GONK
+  if (IsH264Type(aType)) {
+    nsRefPtr<nsMediaOmxDecoder> decoder = new nsMediaOmxDecoder();
+    if (decoder->Init(this)) {
+      return decoder.forget();
+    }
+  }
+#endif
 #ifdef MOZ_MEDIA_PLUGINS
   if (IsMediaPluginsEnabled() && GetMediaPluginHost()->FindDecoder(aType, NULL)) {
     nsRefPtr<nsMediaPluginDecoder> decoder = new nsMediaPluginDecoder(aType);
     if (decoder->Init(this)) {
       return decoder.forget();
     }
   }
 #endif
--- a/content/media/Makefile.in
+++ b/content/media/Makefile.in
@@ -85,16 +85,20 @@ PARALLEL_DIRS += gstreamer
 endif
 
 ifdef MOZ_MEDIA_PLUGINS
 PARALLEL_DIRS += plugins
 endif
 
 PARALLEL_DIRS += webrtc
 
+ifeq (gonk,$(MOZ_WIDGET_TOOLKIT))
+PARALLEL_DIRS += omx
+endif
+
 TEST_DIRS += test
 
 FORCE_STATIC_LIB = 1
 
 include $(topsrcdir)/config/config.mk
 include $(topsrcdir)/ipc/chromium/chromium-config.mk
 include $(topsrcdir)/config/rules.mk
 
--- a/content/media/VideoFrameContainer.cpp
+++ b/content/media/VideoFrameContainer.cpp
@@ -41,25 +41,49 @@ void VideoFrameContainer::SetCurrentFram
     mIntrinsicSizeChanged = true;
   }
 
   gfxIntSize oldFrameSize = mImageContainer->GetCurrentSize();
   TimeStamp lastPaintTime = mImageContainer->GetPaintTime();
   if (!lastPaintTime.IsNull() && !mPaintTarget.IsNull()) {
     mPaintDelay = lastPaintTime - mPaintTarget;
   }
+
+  // When using the OMX decoder, destruction of the current image can indirectly
+  //  block on main thread I/O. If we let this happen while holding onto
+  //  |mImageContainer|'s lock, then when the main thread then tries to
+  //  composite it can then block on |mImageContainer|'s lock, causing a
+  //  deadlock. We use this hack to defer the destruction of the current image
+  //  until it is safe.
+  nsRefPtr<Image> kungFuDeathGrip;
+  kungFuDeathGrip = mImageContainer->LockCurrentImage();
+  mImageContainer->UnlockCurrentImage();
+
   mImageContainer->SetCurrentImage(aImage);
   gfxIntSize newFrameSize = mImageContainer->GetCurrentSize();
   if (oldFrameSize != newFrameSize) {
     mImageSizeChanged = true;
   }
 
   mPaintTarget = aTargetTime;
 }
 
+void VideoFrameContainer::ClearCurrentFrame()
+{
+  MutexAutoLock lock(mMutex);
+
+  // See comment in SetCurrentFrame for the reasoning behind
+  // using a kungFuDeathGrip here.
+  nsRefPtr<Image> kungFuDeathGrip;
+  kungFuDeathGrip = mImageContainer->LockCurrentImage();
+  mImageContainer->UnlockCurrentImage();
+
+  mImageContainer->SetCurrentImage(nullptr);
+}
+
 ImageContainer* VideoFrameContainer::GetImageContainer() {
   return mImageContainer;
 }
 
 
 double VideoFrameContainer::GetFrameDelay()
 {
   MutexAutoLock lock(mMutex);
--- a/content/media/VideoFrameContainer.h
+++ b/content/media/VideoFrameContainer.h
@@ -41,16 +41,17 @@ public:
 
   VideoFrameContainer(nsHTMLMediaElement* aElement,
                       already_AddRefed<ImageContainer> aContainer);
   ~VideoFrameContainer();
 
   // Call on any thread
   void SetCurrentFrame(const gfxIntSize& aIntrinsicSize, Image* aImage,
                        TimeStamp aTargetTime);
+  void ClearCurrentFrame();
   // Time in seconds by which the last painted video frame was late by.
   // E.g. if the last painted frame should have been painted at time t,
   // but was actually painted at t+n, this returns n in seconds. Threadsafe.
   double GetFrameDelay();
   // Call on main thread
   void Invalidate();
   ImageContainer* GetImageContainer();
   void ForgetElement() { mElement = nullptr; }
--- a/content/media/nsBuiltinDecoderReader.cpp
+++ b/content/media/nsBuiltinDecoderReader.cpp
@@ -1,14 +1,15 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* 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 "GonkIOSurfaceImage.h"
 #include "nsBuiltinDecoder.h"
 #include "nsBuiltinDecoderReader.h"
 #include "nsBuiltinDecoderStateMachine.h"
 #include "VideoUtils.h"
 #include "ImageContainer.h"
 
 #include "mozilla/mozalloc.h"
 #include "mozilla/StandardInteger.h"
@@ -233,16 +234,84 @@ VideoData* VideoData::Create(nsVideoInfo
   data.mPicSize = gfxIntSize(aPicture.width, aPicture.height);
   data.mStereoMode = aInfo.mStereoMode;
 
   videoImage->SetDelayedConversion(true);
   videoImage->SetData(data);
   return v.forget();
 }
 
+#ifdef MOZ_WIDGET_GONK
+VideoData* VideoData::Create(nsVideoInfo& aInfo,
+                             ImageContainer* aContainer,
+                             int64_t aOffset,
+                             int64_t aTime,
+                             int64_t aEndTime,
+                             mozilla::layers::GraphicBufferLocked *aBuffer,
+                             bool aKeyframe,
+                             int64_t aTimecode,
+                             nsIntRect aPicture)
+{
+  if (!aContainer) {
+    // Create a dummy VideoData with no image. This gives us something to
+    // send to media streams if necessary.
+    nsAutoPtr<VideoData> v(new VideoData(aOffset,
+                                         aTime,
+                                         aEndTime,
+                                         aKeyframe,
+                                         aTimecode,
+                                         aInfo.mDisplay));
+    return v.forget();
+  }
+
+  // The following situations could be triggered by invalid input
+  if (aPicture.width <= 0 || aPicture.height <= 0) {
+    NS_WARNING("Empty picture rect");
+    return nullptr;
+  }
+
+  // Ensure the picture size specified in the headers can be extracted out of
+  // the frame we've been supplied without indexing out of bounds.
+  CheckedUint32 xLimit = aPicture.x + CheckedUint32(aPicture.width);
+  CheckedUint32 yLimit = aPicture.y + CheckedUint32(aPicture.height);
+  if (!xLimit.isValid() || !yLimit.isValid())
+  {
+    // The specified picture dimensions can't be contained inside the video
+    // frame, we'll stomp memory if we try to copy it. Fail.
+    NS_WARNING("Overflowing picture rect");
+    return nullptr;
+  }
+
+  nsAutoPtr<VideoData> v(new VideoData(aOffset,
+                                       aTime,
+                                       aEndTime,
+                                       aKeyframe,
+                                       aTimecode,
+                                       aInfo.mDisplay));
+
+  ImageFormat format = GONK_IO_SURFACE;
+  v->mImage = aContainer->CreateImage(&format, 1);
+  if (!v->mImage) {
+    return nullptr;
+  }
+  NS_ASSERTION(v->mImage->GetFormat() == GONK_IO_SURFACE,
+               "Wrong format?");
+  typedef mozilla::layers::GonkIOSurfaceImage GonkIOSurfaceImage;
+  GonkIOSurfaceImage* videoImage = static_cast<GonkIOSurfaceImage*>(v->mImage.get());
+  GonkIOSurfaceImage::Data data;
+
+  data.mPicSize = gfxIntSize(aPicture.width, aPicture.height);
+  data.mGraphicBuffer = aBuffer;
+
+  videoImage->SetData(data);
+
+  return v.forget();
+}
+#endif  // MOZ_WIDGET_GONK
+
 void* nsBuiltinDecoderReader::VideoQueueMemoryFunctor::operator()(void* anObject) {
   const VideoData* v = static_cast<const VideoData*>(anObject);
   if (!v->mImage) {
     return nullptr;
   }
   NS_ASSERTION(v->mImage->GetFormat() == PLANAR_YCBCR,
                "Wrong format?");
   mozilla::layers::PlanarYCbCrImage* vi = static_cast<mozilla::layers::PlanarYCbCrImage*>(v->mImage.get());
--- a/content/media/nsBuiltinDecoderReader.h
+++ b/content/media/nsBuiltinDecoderReader.h
@@ -116,16 +116,22 @@ public:
   const uint32_t mChannels;
   // At least one of mAudioBuffer/mAudioData must be non-null.
   // mChannels channels, each with mFrames frames
   nsRefPtr<SharedBuffer> mAudioBuffer;
   // mFrames frames, each with mChannels values
   nsAutoArrayPtr<AudioDataValue> mAudioData;
 };
 
+namespace mozilla {
+namespace layers {
+class GraphicBufferLocked;
+}
+}
+
 // Holds a decoded video frame, in YCbCr format. These are queued in the reader.
 class VideoData {
 public:
   typedef mozilla::layers::ImageContainer ImageContainer;
   typedef mozilla::layers::Image Image;
 
   // YCbCr data obtained from decoding the video. The index's are:
   //   0 = Y
@@ -155,16 +161,26 @@ public:
                            int64_t aOffset,
                            int64_t aTime,
                            int64_t aEndTime,
                            const YCbCrBuffer &aBuffer,
                            bool aKeyframe,
                            int64_t aTimecode,
                            nsIntRect aPicture);
 
+  static VideoData* Create(nsVideoInfo& aInfo,
+                           ImageContainer* aContainer,
+                           int64_t aOffset,
+                           int64_t aTime,
+                           int64_t aEndTime,
+                           mozilla::layers::GraphicBufferLocked *aBuffer,
+                           bool aKeyframe,
+                           int64_t aTimecode,
+                           nsIntRect aPicture);
+
   // Constructs a duplicate VideoData object. This intrinsically tells the
   // player that it does not need to update the displayed frame when this
   // frame is played; this frame is identical to the previous.
   static VideoData* CreateDuplicate(int64_t aOffset,
                                     int64_t aTime,
                                     int64_t aEndTime,
                                     int64_t aTimecode)
   {
--- a/content/media/nsBuiltinDecoderStateMachine.cpp
+++ b/content/media/nsBuiltinDecoderStateMachine.cpp
@@ -58,17 +58,25 @@ const uint32_t SILENCE_BYTES_CHUNK = 32 
 // If we have fewer than LOW_VIDEO_FRAMES decoded frames, and
 // we're not "pumping video", we'll skip the video up to the next keyframe
 // which is at or after the current playback position.
 static const uint32_t LOW_VIDEO_FRAMES = 1;
 
 // If we've got more than AMPLE_VIDEO_FRAMES decoded video frames waiting in
 // the video queue, we will not decode any more video frames until some have
 // been consumed by the play state machine thread.
+#ifdef MOZ_WIDGET_GONK
+// On B2G this is decided by a similar value which varies for each OMX decoder
+// |OMX_PARAM_PORTDEFINITIONTYPE::nBufferCountMin|. This number must be less
+// than the OMX equivalent or gecko will think it is chronically starved of
+// video frames. All decoders seen so far have a value of at least 4.
+static const uint32_t AMPLE_VIDEO_FRAMES = 3;
+#else
 static const uint32_t AMPLE_VIDEO_FRAMES = 10;
+#endif
 
 // Arbitrary "frame duration" when playing only audio.
 static const int AUDIO_DURATION_USECS = 40000;
 
 // If we increase our "low audio threshold" (see LOW_AUDIO_USECS above), we
 // use this as a factor in all our calculations. Increasing this will cause
 // us to be more likely to increase our low audio threshold, and to
 // increase it by more.
new file mode 100644
--- /dev/null
+++ b/content/media/omx/MPAPI.h
@@ -0,0 +1,133 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* 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/. */
+#if !defined(MPAPI_h_)
+#define MPAPI_h_
+
+#include <stdint.h>
+#include "GonkIOSurfaceImage.h"
+
+namespace MPAPI {
+
+struct VideoPlane {
+  void *mData;
+  int32_t mStride;
+  int32_t mWidth;
+  int32_t mHeight;
+  int32_t mOffset;
+  int32_t mSkip;
+};
+
+struct VideoFrame {
+  int64_t mTimeUs;
+  int64_t mEndTimeUs;
+  bool mKeyFrame;
+  void *mData;
+  size_t mSize;
+  int32_t mStride;
+  int32_t mSliceHeight;
+  int32_t mRotation;
+  VideoPlane Y;
+  VideoPlane Cb;
+  VideoPlane Cr;
+  nsRefPtr<mozilla::layers::GraphicBufferLocked> mGraphicBuffer;
+
+  void Set(int64_t aTimeUs, bool aKeyFrame,
+           void *aData, size_t aSize, int32_t aStride, int32_t aSliceHeight, int32_t aRotation,
+           void *aYData, int32_t aYStride, int32_t aYWidth, int32_t aYHeight, int32_t aYOffset, int32_t aYSkip,
+           void *aCbData, int32_t aCbStride, int32_t aCbWidth, int32_t aCbHeight, int32_t aCbOffset, int32_t aCbSkip,
+           void *aCrData, int32_t aCrStride, int32_t aCrWidth, int32_t aCrHeight, int32_t aCrOffset, int32_t aCrSkip)
+  {
+    mTimeUs = aTimeUs;
+    mKeyFrame = aKeyFrame;
+    mData = aData;
+    mSize = aSize;
+    mStride = aStride;
+    mSliceHeight = aSliceHeight;
+    mRotation = aRotation;
+    mGraphicBuffer = nullptr;
+    Y.mData = aYData;
+    Y.mStride = aYStride;
+    Y.mWidth = aYWidth;
+    Y.mHeight = aYHeight;
+    Y.mOffset = aYOffset;
+    Y.mSkip = aYSkip;
+    Cb.mData = aCbData;
+    Cb.mStride = aCbStride;
+    Cb.mWidth = aCbWidth;
+    Cb.mHeight = aCbHeight;
+    Cb.mOffset = aCbOffset;
+    Cb.mSkip = aCbSkip;
+    Cr.mData = aCrData;
+    Cr.mStride = aCrStride;
+    Cr.mWidth = aCrWidth;
+    Cr.mHeight = aCrHeight;
+    Cr.mOffset = aCrOffset;
+    Cr.mSkip = aCrSkip;
+  }
+};
+
+struct AudioFrame {
+  int64_t mTimeUs;
+  void *mData; // 16PCM interleaved
+  size_t mSize; // Size of mData in bytes
+  int32_t mAudioChannels;
+  int32_t mAudioSampleRate;
+
+  AudioFrame() :
+    mTimeUs(0),
+    mData(0),
+    mSize(0),
+    mAudioChannels(0),
+    mAudioSampleRate(0)
+  {
+  }
+
+  void Set(int64_t aTimeUs,
+           void *aData, size_t aSize,
+           int32_t aAudioChannels, int32_t aAudioSampleRate)
+  {
+    mTimeUs = aTimeUs;
+    mData = aData;
+    mSize = aSize;
+    mAudioChannels = aAudioChannels;
+    mAudioSampleRate = aAudioSampleRate;
+  }
+};
+
+struct Decoder;
+
+struct PluginHost {
+  bool (*Read)(Decoder *aDecoder, char *aBuffer, int64_t aOffset, uint32_t aCount, uint32_t* aBytes);
+  uint64_t (*GetLength)(Decoder *aDecoder);
+  void (*SetMetaDataReadMode)(Decoder *aDecoder);
+  void (*SetPlaybackReadMode)(Decoder *aDecoder);
+};
+
+struct Decoder {
+  void *mResource;
+  void *mPrivate;
+
+  Decoder();
+
+  void (*GetDuration)(Decoder *aDecoder, int64_t *durationUs);
+  void (*GetVideoParameters)(Decoder *aDecoder, int32_t *aWidth, int32_t *aHeight);
+  void (*GetAudioParameters)(Decoder *aDecoder, int32_t *aNumChannels, int32_t *aSampleRate);
+  bool (*HasVideo)(Decoder *aDecoder);
+  bool (*HasAudio)(Decoder *aDecoder);
+  bool (*ReadVideo)(Decoder *aDecoder, VideoFrame *aFrame, int64_t aSeekTimeUs);
+  bool (*ReadAudio)(Decoder *aDecoder, AudioFrame *aFrame, int64_t aSeekTimeUs);
+  void (*DestroyDecoder)(Decoder *);
+};
+
+struct Manifest {
+  bool (*CanDecode)(const char *aMimeChars, size_t aMimeLen, const char* const**aCodecs);
+  bool (*CreateDecoder)(PluginHost *aPluginHost, Decoder *aDecoder,
+                        const char *aMimeChars, size_t aMimeLen);
+};
+
+}
+
+#endif
new file mode 100644
--- /dev/null
+++ b/content/media/omx/Makefile.in
@@ -0,0 +1,42 @@
+# 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/.
+
+DEPTH		= @DEPTH@
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE		= content
+LIBRARY_NAME	= gkconomx_s
+LIBXUL_LIBRARY 	= 1
+
+EXPORTS		+= \
+		nsMediaOmxDecoder.h \
+		$(NULL)
+
+CPPSRCS		= \
+		nsMediaOmxDecoder.cpp \
+		nsMediaOmxReader.cpp \
+		OmxDecoder.cpp \
+		$(NULL)
+
+FORCE_STATIC_LIB = 1
+
+include $(topsrcdir)/config/rules.mk
+include $(topsrcdir)/ipc/chromium/chromium-config.mk
+
+INCLUDES	+= \
+		-I$(topsrcdir)/ipc/chromium/src \
+		-I$(srcdir)/../../base/src \
+		-I$(srcdir)/../../html/content/src \
+		-I$(ANDROID_SOURCE)/dalvik/libnativehelper/include/nativehelper \
+		-I$(ANDROID_SOURCE)/frameworks/base/include/ \
+		-I$(ANDROID_SOURCE)/frameworks/base/include/binder/ \
+		-I$(ANDROID_SOURCE)/frameworks/base/include/utils/ \
+		-I$(ANDROID_SOURCE)/frameworks/base/include/media/ \
+		-I$(ANDROID_SOURCE)/frameworks/base/include/media/stagefright/openmax \
+		-I$(ANDROID_SOURCE)/frameworks/base/media/libstagefright/include/ \
+		$(NULL)
new file mode 100644
--- /dev/null
+++ b/content/media/omx/OmxDecoder.cpp
@@ -0,0 +1,570 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* 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 <unistd.h>
+#include <fcntl.h>
+
+#include "base/basictypes.h"
+#include <stagefright/DataSource.h>
+#include <stagefright/MediaExtractor.h>
+#include <stagefright/MetaData.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 "OmxDecoder.h"
+
+#ifdef PR_LOGGING
+PRLogModuleInfo *gOmxDecoderLog;
+#define LOG(type, msg...) PR_LOG(gOmxDecoderLog, type, (msg))
+#else
+#define LOG(x...)
+#endif
+
+using namespace MPAPI;
+
+namespace mozilla {
+namespace layers {
+
+VideoGraphicBuffer::VideoGraphicBuffer(android::MediaBuffer *aBuffer,
+                                       SurfaceDescriptor *aDescriptor)
+  : GraphicBufferLocked(*aDescriptor),
+    mMediaBuffer(aBuffer)
+{
+  mMediaBuffer->add_ref();
+}
+
+VideoGraphicBuffer::~VideoGraphicBuffer()
+{
+  if (mMediaBuffer) {
+    mMediaBuffer->release();
+  }
+}
+
+void
+VideoGraphicBuffer::Unlock()
+{
+  if (mMediaBuffer) {
+    mMediaBuffer->release();
+    mMediaBuffer = nullptr;
+  }
+}
+
+}
+}
+
+namespace android {
+
+MediaStreamSource::MediaStreamSource(MediaResource *aResource,
+                                     nsBuiltinDecoder *aDecoder) :
+  mDecoder(aDecoder), mResource(aResource)
+{
+}
+
+MediaStreamSource::~MediaStreamSource()
+{
+}
+
+status_t MediaStreamSource::initCheck() const
+{
+  return OK;
+}
+
+ssize_t MediaStreamSource::readAt(off64_t offset, void *data, size_t size)
+{
+  char *ptr = static_cast<char *>(data);
+  size_t todo = size;
+  while (todo > 0) {
+    uint32_t bytesRead;
+    if ((offset != mResource->Tell() &&
+         NS_FAILED(mResource->Seek(nsISeekableStream::NS_SEEK_SET, offset))) ||
+        NS_FAILED(mResource->Read(ptr, todo, &bytesRead))) {
+      return ERROR_IO;
+    }
+    offset += bytesRead;
+    todo -= bytesRead;
+    ptr += bytesRead;
+  }
+  return size;
+}
+
+status_t MediaStreamSource::getSize(off64_t *size)
+{
+  uint64_t length = mResource->GetLength();
+  if (length == static_cast<uint64_t>(-1))
+    return ERROR_UNSUPPORTED;
+
+  *size = length;
+
+  return OK;
+}
+
+}  // namespace android
+
+using namespace android;
+
+OmxDecoder::OmxDecoder(MediaResource *aResource,
+                       nsBuiltinDecoder *aDecoder) :
+  mResource(aResource),
+  mDecoder(aDecoder),
+  mVideoWidth(0),
+  mVideoHeight(0),
+  mVideoColorFormat(0),
+  mVideoStride(0),
+  mVideoSliceHeight(0),
+  mVideoRotation(0),
+  mAudioChannels(-1),
+  mAudioSampleRate(-1),
+  mDurationUs(-1),
+  mVideoBuffer(nullptr),
+  mAudioBuffer(nullptr),
+  mAudioMetadataRead(false)
+{
+}
+
+OmxDecoder::~OmxDecoder()
+{
+  ReleaseVideoBuffer();
+  ReleaseAudioBuffer();
+
+  if (mVideoSource.get()) {
+    mVideoSource->stop();
+  }
+
+  if (mAudioSource.get()) {
+    mAudioSource->stop();
+  }
+}
+
+class AutoStopMediaSource {
+  sp<MediaSource> mMediaSource;
+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.
+  DataSource::RegisterDefaultSniffers();
+
+  sp<DataSource> dataSource = new MediaStreamSource(mResource, mDecoder);
+  if (dataSource->initCheck()) {
+    NS_WARNING("Initializing DataSource for OMX decoder failed");
+    return false;
+  }
+
+  mResource->SetReadMode(nsMediaCacheStream::MODE_METADATA);
+
+  sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
+  if (extractor == nullptr) {
+    NS_WARNING("Could not create MediaExtractor");
+    return false;
+  }
+
+  ssize_t audioTrackIndex = -1;
+  ssize_t videoTrackIndex = -1;
+  const char *audioMime = nullptr;
+
+  for (size_t i = 0; i < extractor->countTracks(); ++i) {
+    sp<MetaData> meta = extractor->getTrackMetaData(i);
+
+    int32_t bitRate;
+    if (!meta->findInt32(kKeyBitRate, &bitRate))
+      bitRate = 0;
+
+    const char *mime;
+    if (!meta->findCString(kKeyMIMEType, &mime)) {
+      continue;
+    }
+
+    if (videoTrackIndex == -1 && !strncasecmp(mime, "video/", 6)) {
+      videoTrackIndex = i;
+    } else if (audioTrackIndex == -1 && !strncasecmp(mime, "audio/", 6)) {
+      audioTrackIndex = i;
+      audioMime = mime;
+    }
+  }
+
+  if (videoTrackIndex == -1 && audioTrackIndex == -1) {
+    NS_WARNING("OMX decoder could not find video or audio tracks");
+    return false;
+  }
+
+  mResource->SetReadMode(nsMediaCacheStream::MODE_PLAYBACK);
+
+  int64_t totalDurationUs = 0;
+
+  mNativeWindow = new GonkNativeWindow();
+
+  sp<MediaSource> videoTrack;
+  sp<MediaSource> videoSource;
+  if (videoTrackIndex != -1 && (videoTrack = extractor->getTrack(videoTrackIndex)) != nullptr) {
+    int flags = 0; // prefer hw codecs
+
+    if (mozilla::Preferences::GetBool("media.omx.prefer_software_codecs", false)) {
+      flags |= kPreferSoftwareCodecs;
+    }
+
+    videoSource = OMXCodec::Create(GetOMX(),
+                                   videoTrack->getFormat(),
+                                   false, // decoder
+                                   videoTrack,
+                                   nullptr,
+                                   flags,
+                                   mNativeWindow);
+    if (videoSource == nullptr) {
+      NS_WARNING("Couldn't create OMX video source");
+      return false;
+    }
+
+    if (videoSource->start() != OK) {
+      NS_WARNING("Couldn't start OMX video source");
+      return false;
+    }
+
+    int64_t durationUs;
+    if (videoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
+      if (durationUs > totalDurationUs)
+        totalDurationUs = durationUs;
+    }
+  }
+
+  sp<MediaSource> audioTrack;
+  sp<MediaSource> audioSource;
+  if (audioTrackIndex != -1 && (audioTrack = extractor->getTrack(audioTrackIndex)) != nullptr)
+  {
+    if (!strcasecmp(audioMime, "audio/raw")) {
+      audioSource = audioTrack;
+    } else {
+      audioSource = OMXCodec::Create(GetOMX(),
+                                     audioTrack->getFormat(),
+                                     false, // decoder
+                                     audioTrack);
+    }
+    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)) {
+      if (durationUs > totalDurationUs)
+        totalDurationUs = durationUs;
+    }
+  }
+
+  // set decoder state
+  mVideoTrack = videoTrack;
+  mVideoSource = videoSource;
+  mAudioTrack = audioTrack;
+  mAudioSource = audioSource;
+  mDurationUs = totalDurationUs;
+
+  if (mVideoSource.get() && !SetVideoFormat()) {
+    NS_WARNING("Couldn't set OMX video format");
+    return false;
+  }
+
+  // To reliably get the channel and sample rate data we need to read from the
+  // audio source until we get a INFO_FORMAT_CHANGE status
+  if (mAudioSource.get()) {
+    if (mAudioSource->read(&mAudioBuffer) != INFO_FORMAT_CHANGED) {
+      sp<MetaData> meta = mAudioSource->getFormat();
+      if (!meta->findInt32(kKeyChannelCount, &mAudioChannels) ||
+          !meta->findInt32(kKeySampleRate, &mAudioSampleRate)) {
+        NS_WARNING("Couldn't get audio metadata from OMX decoder");
+        return false;
+      }
+      mAudioMetadataRead = true;
+    }
+    else if (!SetAudioFormat()) {
+      NS_WARNING("Couldn't set audio format");
+      return false;
+    }
+  }
+
+  return true;
+}
+
+bool OmxDecoder::SetVideoFormat() {
+  const char *componentName;
+
+  if (!mVideoSource->getFormat()->findInt32(kKeyWidth, &mVideoWidth) ||
+      !mVideoSource->getFormat()->findInt32(kKeyHeight, &mVideoHeight) ||
+      !mVideoSource->getFormat()->findCString(kKeyDecoderComponent, &componentName) ||
+      !mVideoSource->getFormat()->findInt32(kKeyColorFormat, &mVideoColorFormat) ) {
+    return false;
+  }
+
+  if (!mVideoSource->getFormat()->findInt32(kKeyStride, &mVideoStride)) {
+    mVideoStride = mVideoWidth;
+    NS_WARNING("stride not available, assuming width");
+  }
+
+  if (!mVideoSource->getFormat()->findInt32(kKeySliceHeight, &mVideoSliceHeight)) {
+    mVideoSliceHeight = mVideoHeight;
+    NS_WARNING("slice height not available, assuming height");
+  }
+
+  if (!mVideoSource->getFormat()->findInt32(kKeyRotation, &mVideoRotation)) {
+    mVideoRotation = 0;
+    NS_WARNING("rotation not available, assuming 0");
+  }
+
+  LOG(PR_LOG_DEBUG, "width: %d height: %d component: %s format: %d stride: %d sliceHeight: %d rotation: %d",
+      mVideoWidth, mVideoHeight, componentName, mVideoColorFormat,
+      mVideoStride, mVideoSliceHeight, mVideoRotation);
+
+  return true;
+}
+
+bool OmxDecoder::SetAudioFormat() {
+  // If the format changed, update our cached info.
+  if (!mAudioSource->getFormat()->findInt32(kKeyChannelCount, &mAudioChannels) ||
+      !mAudioSource->getFormat()->findInt32(kKeySampleRate, &mAudioSampleRate)) {
+    return false;
+  }
+
+  LOG(PR_LOG_DEBUG, "channelCount: %d sampleRate: %d",
+      mAudioChannels, mAudioSampleRate);
+
+  return true;
+}
+
+void OmxDecoder::ReleaseVideoBuffer() {
+  if (mVideoBuffer) {
+    mVideoBuffer->release();
+    mVideoBuffer = nullptr;
+  }
+}
+
+void OmxDecoder::ReleaseAudioBuffer() {
+  if (mAudioBuffer) {
+    mAudioBuffer->release();
+    mAudioBuffer = nullptr;
+  }
+}
+
+void OmxDecoder::PlanarYUV420Frame(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame) {
+  void *y = aData;
+  void *u = static_cast<uint8_t *>(y) + mVideoStride * mVideoSliceHeight;
+  void *v = static_cast<uint8_t *>(u) + mVideoStride/2 * mVideoSliceHeight/2;
+
+  aFrame->Set(aTimeUs, aKeyFrame,
+              aData, aSize, mVideoStride, mVideoSliceHeight, mVideoRotation,
+              y, mVideoStride, mVideoWidth, mVideoHeight, 0, 0,
+              u, mVideoStride/2, mVideoWidth/2, mVideoHeight/2, 0, 0,
+              v, mVideoStride/2, mVideoWidth/2, mVideoHeight/2, 0, 0);
+}
+
+void OmxDecoder::CbYCrYFrame(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame) {
+  aFrame->Set(aTimeUs, aKeyFrame,
+              aData, aSize, mVideoStride, mVideoSliceHeight, mVideoRotation,
+              aData, mVideoStride, mVideoWidth, mVideoHeight, 1, 1,
+              aData, mVideoStride, mVideoWidth/2, mVideoHeight/2, 0, 3,
+              aData, mVideoStride, mVideoWidth/2, mVideoHeight/2, 2, 3);
+}
+
+void OmxDecoder::SemiPlanarYUV420Frame(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame) {
+  void *y = aData;
+  void *uv = static_cast<uint8_t *>(y) + (mVideoStride * mVideoSliceHeight);
+
+  aFrame->Set(aTimeUs, aKeyFrame,
+              aData, aSize, mVideoStride, mVideoSliceHeight, mVideoRotation,
+              y, mVideoStride, mVideoWidth, mVideoHeight, 0, 0,
+              uv, mVideoStride, mVideoWidth/2, mVideoHeight/2, 0, 1,
+              uv, mVideoStride, mVideoWidth/2, mVideoHeight/2, 1, 1);
+}
+
+void OmxDecoder::SemiPlanarYVU420Frame(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame) {
+  SemiPlanarYUV420Frame(aFrame, aTimeUs, aData, aSize, aKeyFrame);
+  aFrame->Cb.mOffset = 1;
+  aFrame->Cr.mOffset = 0;
+}
+
+bool OmxDecoder::ToVideoFrame(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame) {
+  const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00;
+
+  aFrame->mGraphicBuffer = nullptr;
+
+  switch (mVideoColorFormat) {
+  case OMX_COLOR_FormatYUV420Planar:
+    PlanarYUV420Frame(aFrame, aTimeUs, aData, aSize, aKeyFrame);
+    break;
+  case OMX_COLOR_FormatCbYCrY:
+    CbYCrYFrame(aFrame, aTimeUs, aData, aSize, aKeyFrame);
+    break;
+  case OMX_COLOR_FormatYUV420SemiPlanar:
+    SemiPlanarYUV420Frame(aFrame, aTimeUs, aData, aSize, aKeyFrame);
+    break;
+  case OMX_QCOM_COLOR_FormatYVU420SemiPlanar:
+    SemiPlanarYVU420Frame(aFrame, aTimeUs, aData, aSize, aKeyFrame);
+    break;
+  default:
+    LOG(PR_LOG_DEBUG, "Unknown video color format %08x", mVideoColorFormat);
+    return false;
+  }
+  return true;
+}
+
+bool OmxDecoder::ToAudioFrame(AudioFrame *aFrame, int64_t aTimeUs, void *aData, size_t aDataOffset, size_t aSize, int32_t aAudioChannels, int32_t aAudioSampleRate)
+{
+  aFrame->Set(aTimeUs, static_cast<char *>(aData) + aDataOffset, aSize, aAudioChannels, aAudioSampleRate);
+  return true;
+}
+
+bool OmxDecoder::ReadVideo(VideoFrame *aFrame, int64_t aTimeUs,
+                           bool aKeyframeSkip, bool aDoSeek)
+{
+  if (!mVideoSource.get())
+    return false;
+
+  ReleaseVideoBuffer();
+
+  status_t err;
+
+  if (aDoSeek || aKeyframeSkip) {
+    MediaSource::ReadOptions options;
+    options.setSeekTo(aTimeUs, aDoSeek ? MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC :
+                                         MediaSource::ReadOptions::SEEK_NEXT_SYNC);
+    err = mVideoSource->read(&mVideoBuffer, &options);
+  } else {
+    err = mVideoSource->read(&mVideoBuffer);
+  }
+
+  if (err == OK && mVideoBuffer->range_length() > 0) {
+    int64_t timeUs;
+    int64_t durationUs;
+    int32_t unreadable;
+    int32_t keyFrame;
+
+    if (!mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs) ) {
+      NS_WARNING("OMX decoder did not return frame time");
+      return false;
+    }
+
+    if (!mVideoBuffer->meta_data()->findInt32(kKeyIsSyncFrame, &keyFrame)) {
+      keyFrame = 0;
+    }
+
+    if (!mVideoBuffer->meta_data()->findInt32(kKeyIsUnreadable, &unreadable)) {
+      unreadable = 0;
+    }
+
+    mozilla::layers::SurfaceDescriptor *descriptor = nullptr;
+    if ((mVideoBuffer->graphicBuffer().get())) {
+      descriptor = mNativeWindow->getSurfaceDescriptorFromBuffer(mVideoBuffer->graphicBuffer().get());
+    }
+
+    if (descriptor) {
+      aFrame->mGraphicBuffer = new mozilla::layers::VideoGraphicBuffer(mVideoBuffer, descriptor);
+      aFrame->mRotation = mVideoRotation;
+      aFrame->mTimeUs = timeUs;
+      aFrame->mEndTimeUs = timeUs + durationUs;
+      aFrame->mKeyFrame = keyFrame;
+      aFrame->Y.mWidth = mVideoWidth;
+      aFrame->Y.mHeight = mVideoHeight;
+    } else {
+      char *data = static_cast<char *>(mVideoBuffer->data()) + mVideoBuffer->range_offset();
+      size_t length = mVideoBuffer->range_length();
+
+      if (unreadable) {
+        LOG(PR_LOG_DEBUG, "video frame is unreadable");
+      }
+
+      if (!ToVideoFrame(aFrame, timeUs, data, length, keyFrame)) {
+        return false;
+      }
+
+      aFrame->mEndTimeUs = timeUs + durationUs;
+    }
+
+  }
+  else if (err == INFO_FORMAT_CHANGED) {
+    // If the format changed, update our cached info.
+    if (!SetVideoFormat()) {
+      return false;
+    } else {
+      return ReadVideo(aFrame, aTimeUs, aKeyframeSkip, aDoSeek);
+    }
+  }
+  else if (err == ERROR_END_OF_STREAM) {
+    return false;
+  }
+
+  return true;
+}
+
+bool OmxDecoder::ReadAudio(AudioFrame *aFrame, int64_t aSeekTimeUs)
+{
+  status_t err;
+
+  if (mAudioMetadataRead && aSeekTimeUs == -1) {
+    // Use the data read into the buffer during metadata time
+    err = OK;
+  }
+  else {
+    ReleaseAudioBuffer();
+    if (aSeekTimeUs != -1) {
+      MediaSource::ReadOptions options;
+      options.setSeekTo(aSeekTimeUs);
+      err = mAudioSource->read(&mAudioBuffer, &options);
+    } else {
+      err = mAudioSource->read(&mAudioBuffer);
+    }
+  }
+  mAudioMetadataRead = false;
+
+  aSeekTimeUs = -1;
+
+  if (err == OK && mAudioBuffer->range_length() != 0) {
+    int64_t timeUs;
+    if (!mAudioBuffer->meta_data()->findInt64(kKeyTime, &timeUs))
+      return false;
+
+    return ToAudioFrame(aFrame, timeUs,
+                        mAudioBuffer->data(),
+                        mAudioBuffer->range_offset(),
+                        mAudioBuffer->range_length(),
+                        mAudioChannels, mAudioSampleRate);
+  }
+  else if (err == INFO_FORMAT_CHANGED) {
+    // If the format changed, update our cached info.
+    if (!SetAudioFormat()) {
+      return false;
+    } else {
+      return ReadAudio(aFrame, aSeekTimeUs);
+    }
+  }
+
+  return true;
+}
new file mode 100644
--- /dev/null
+++ b/content/media/omx/OmxDecoder.h
@@ -0,0 +1,151 @@
+#include <OMX.h>
+#include <stagefright/MediaSource.h>
+#include <stagefright/DataSource.h>
+
+#include <utils/RefBase.h>
+
+#include "GonkNativeWindow.h"
+#include "GonkIOSurfaceImage.h"
+#include "MPAPI.h"
+#include "MediaResource.h"
+#include "nsBuiltinDecoder.h"
+
+namespace mozilla {
+namespace layers {
+
+class VideoGraphicBuffer : public GraphicBufferLocked {
+  // XXX change this to an actual smart pointer at some point
+  android::MediaBuffer *mMediaBuffer;
+  public:
+    VideoGraphicBuffer(android::MediaBuffer *aBuffer,
+                       SurfaceDescriptor *aDescriptor);
+    ~VideoGraphicBuffer();
+    void Unlock();
+};
+
+}
+}
+
+namespace android {
+
+// MediaStreamSource is a DataSource that reads from a MPAPI media stream.
+class MediaStreamSource : public DataSource {
+  typedef mozilla::MediaResource MediaResource;
+
+  MediaResource *mResource;
+  nsBuiltinDecoder *mDecoder;
+public:
+  MediaStreamSource(MediaResource *aResource,
+                    nsBuiltinDecoder *aDecoder);
+
+  virtual status_t initCheck() const;
+  virtual ssize_t readAt(off64_t offset, void *data, size_t size);
+  virtual ssize_t readAt(off_t offset, void *data, size_t size) {
+    return readAt(static_cast<off64_t>(offset), data, size);
+  }
+  virtual status_t getSize(off_t *size) {
+    off64_t size64;
+    status_t status = getSize(&size64);
+    *size = size64;
+    return status;
+  }
+  virtual status_t getSize(off64_t *size);
+  virtual uint32_t flags() {
+    return kWantsPrefetching;
+  }
+
+  virtual ~MediaStreamSource();
+
+private:
+  MediaStreamSource(const MediaStreamSource &);
+  MediaStreamSource &operator=(const MediaStreamSource &);
+};
+
+class OmxDecoder {
+  typedef MPAPI::AudioFrame AudioFrame;
+  typedef MPAPI::VideoFrame VideoFrame;
+  typedef mozilla::MediaResource MediaResource;
+
+  enum {
+    kPreferSoftwareCodecs = 1
+  };
+
+  nsBuiltinDecoder *mDecoder;
+  MediaResource *mResource;
+  sp<GonkNativeWindow> mNativeWindow;
+  sp<MediaSource> mVideoTrack;
+  sp<MediaSource> mVideoSource;
+  sp<MediaSource> mAudioTrack;
+  sp<MediaSource> mAudioSource;
+  int32_t mVideoWidth;
+  int32_t mVideoHeight;
+  int32_t mVideoColorFormat;
+  int32_t mVideoStride;
+  int32_t mVideoSliceHeight;
+  int32_t mVideoRotation;
+  int32_t mAudioChannels;
+  int32_t mAudioSampleRate;
+  int64_t mDurationUs;
+  VideoFrame mVideoFrame;
+  AudioFrame mAudioFrame;
+
+  // Lifetime of these should be handled by OMXCodec, as long as we release
+  //   them after use: see ReleaseVideoBuffer(), ReleaseAudioBuffer()
+  MediaBuffer *mVideoBuffer;
+  MediaBuffer *mAudioBuffer;
+
+  // 'true' if a read from the audio stream was done while reading the metadata
+  bool mAudioMetadataRead;
+
+  void ReleaseVideoBuffer();
+  void ReleaseAudioBuffer();
+
+  void PlanarYUV420Frame(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame);
+  void CbYCrYFrame(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame);
+  void SemiPlanarYUV420Frame(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame);
+  void SemiPlanarYVU420Frame(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame);
+  bool ToVideoFrame(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame);
+  bool ToAudioFrame(AudioFrame *aFrame, int64_t aTimeUs, void *aData, size_t aDataOffset, size_t aSize,
+                    int32_t aAudioChannels, int32_t aAudioSampleRate);
+public:
+  OmxDecoder(MediaResource *aResource, nsBuiltinDecoder *aDecoder);
+  ~OmxDecoder();
+
+  bool Init();
+  bool SetVideoFormat();
+  bool SetAudioFormat();
+
+  void GetDuration(int64_t *durationUs) {
+    *durationUs = mDurationUs;
+  }
+
+  void GetVideoParameters(int32_t *width, int32_t *height) {
+    *width = mVideoWidth;
+    *height = mVideoHeight;
+  }
+
+  void GetAudioParameters(int32_t *numChannels, int32_t *sampleRate) {
+    *numChannels = mAudioChannels;
+    *sampleRate = mAudioSampleRate;
+  }
+
+  bool HasVideo() {
+    return mVideoSource != nullptr;
+  }
+
+  bool HasAudio() {
+    return mAudioSource != nullptr;
+  }
+
+  bool ReadVideo(VideoFrame *aFrame, int64_t aSeekTimeUs, 
+                 bool aKeyframeSkip = false,
+                 bool aDoSeek = false);
+  bool ReadAudio(AudioFrame *aFrame, int64_t aSeekTimeUs);
+
+  MediaResource *GetResource() {
+    return mResource;
+  }
+};
+
+}
+
new file mode 100644
--- /dev/null
+++ b/content/media/omx/nsMediaOmxDecoder.cpp
@@ -0,0 +1,28 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* 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 "nsMediaOmxDecoder.h"
+#include "nsMediaOmxReader.h"
+#include "nsBuiltinDecoderStateMachine.h"
+
+nsMediaOmxDecoder::nsMediaOmxDecoder() :
+  nsBuiltinDecoder()
+{
+}
+
+nsMediaDecoder* nsMediaOmxDecoder::Clone()
+{
+  return new nsMediaOmxDecoder();
+}
+
+nsDecoderStateMachine* nsMediaOmxDecoder::CreateStateMachine()
+{
+  return new nsBuiltinDecoderStateMachine(this, new nsMediaOmxReader(this));
+}
+
+nsMediaOmxDecoder::~nsMediaOmxDecoder()
+{
+}
new file mode 100644
--- /dev/null
+++ b/content/media/omx/nsMediaOmxDecoder.h
@@ -0,0 +1,22 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* 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/. */
+#if !defined(nsMediaOmxDecoder_h_)
+#define nsMediaOmxDecoder_h_
+
+#include "base/basictypes.h"
+#include "nsBuiltinDecoder.h"
+
+class nsMediaOmxDecoder : public nsBuiltinDecoder
+{
+public:
+  nsMediaOmxDecoder();
+  ~nsMediaOmxDecoder();
+
+  virtual nsMediaDecoder* Clone();
+  virtual nsDecoderStateMachine* CreateStateMachine();
+};
+
+#endif
new file mode 100644
--- /dev/null
+++ b/content/media/omx/nsMediaOmxReader.cpp
@@ -0,0 +1,362 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* 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 "nsMediaOmxReader.h"
+
+#include "mozilla/TimeStamp.h"
+#include "nsTimeRanges.h"
+#include "MediaResource.h"
+#include "VideoUtils.h"
+#include "nsMediaOmxDecoder.h"
+
+using namespace android;
+using namespace mozilla;
+
+nsMediaOmxReader::nsMediaOmxReader(nsBuiltinDecoder *aDecoder) :
+  nsBuiltinDecoderReader(aDecoder),
+  mOmxDecoder(nullptr),
+  mHasVideo(false),
+  mHasAudio(false),
+  mVideoSeekTimeUs(-1),
+  mAudioSeekTimeUs(-1),
+  mLastVideoFrame(nullptr)
+{
+}
+
+nsMediaOmxReader::~nsMediaOmxReader()
+{
+  ResetDecode();
+}
+
+nsresult nsMediaOmxReader::Init(nsBuiltinDecoderReader* aCloneDonor)
+{
+  return NS_OK;
+}
+
+nsresult nsMediaOmxReader::ReadMetadata(nsVideoInfo* aInfo,
+                                        nsHTMLMediaElement::MetadataTags** aTags)
+{
+  NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
+
+  *aTags = nullptr;
+
+  if (!mOmxDecoder) {
+    mOmxDecoder = new OmxDecoder(mDecoder->GetResource(), mDecoder);
+    mOmxDecoder->Init();
+  }
+
+  // Set the total duration (the max of the audio and video track).
+  int64_t durationUs;
+  mOmxDecoder->GetDuration(&durationUs);
+  if (durationUs) {
+    ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
+    mDecoder->GetStateMachine()->SetDuration(durationUs);
+  }
+
+  if (mOmxDecoder->HasVideo()) {
+    int32_t width, height;
+    mOmxDecoder->GetVideoParameters(&width, &height);
+    nsIntRect pictureRect(0, 0, width, height);
+
+    // Validate the container-reported frame and pictureRect sizes. This ensures
+    // that our video frame creation code doesn't overflow.
+    nsIntSize displaySize(width, height);
+    nsIntSize frameSize(width, height);
+    if (!nsVideoInfo::ValidateVideoRegion(frameSize, pictureRect, displaySize)) {
+      return NS_ERROR_FAILURE;
+    }
+
+    // Video track's frame sizes will not overflow. Activate the video track.
+    mHasVideo = mInfo.mHasVideo = true;
+    mInfo.mDisplay = displaySize;
+    mPicture = pictureRect;
+    mInitialFrame = frameSize;
+    VideoFrameContainer* container = mDecoder->GetVideoFrameContainer();
+    if (container) {
+      container->SetCurrentFrame(gfxIntSize(displaySize.width, displaySize.height),
+                                 nullptr,
+                                 mozilla::TimeStamp::Now());
+    }
+  }
+
+  if (mOmxDecoder->HasAudio()) {
+    int32_t numChannels, sampleRate;
+    mOmxDecoder->GetAudioParameters(&numChannels, &sampleRate);
+    mHasAudio = mInfo.mHasAudio = true;
+    mInfo.mAudioChannels = numChannels;
+    mInfo.mAudioRate = sampleRate;
+  }
+
+ *aInfo = mInfo;
+
+  return NS_OK;
+}
+
+// Resets all state related to decoding, emptying all buffers etc.
+nsresult nsMediaOmxReader::ResetDecode()
+{
+  nsBuiltinDecoderReader::ResetDecode();
+
+  VideoFrameContainer* container = mDecoder->GetVideoFrameContainer();
+  if (container) {
+    container->ClearCurrentFrame();
+  }
+
+  if (mLastVideoFrame) {
+    delete mLastVideoFrame;
+    mLastVideoFrame = nullptr;
+  }
+  if (mOmxDecoder) {
+    delete mOmxDecoder;
+    mOmxDecoder = nullptr;
+  }
+  return NS_OK;
+}
+
+bool nsMediaOmxReader::DecodeVideoFrame(bool &aKeyframeSkip,
+                                        int64_t aTimeThreshold)
+{
+  // Record number of frames decoded and parsed. Automatically update the
+  // stats counters using the AutoNotifyDecoded stack-based class.
+  uint32_t parsed = 0, decoded = 0;
+  nsMediaDecoder::AutoNotifyDecoded autoNotify(mDecoder, parsed, decoded);
+
+  // Throw away the currently buffered frame if we are seeking.
+  if (mLastVideoFrame && mVideoSeekTimeUs != -1) {
+    delete mLastVideoFrame;
+    mLastVideoFrame = nullptr;
+  }
+
+  bool doSeek = mVideoSeekTimeUs != -1;
+  if (doSeek) {
+    aTimeThreshold = mVideoSeekTimeUs;
+  }
+
+  // Read next frame
+  while (true) {
+    MPAPI::VideoFrame frame;
+    frame.mGraphicBuffer = nullptr;
+    if (!mOmxDecoder->ReadVideo(&frame, aTimeThreshold, aKeyframeSkip, doSeek)) {
+      // We reached the end of the video stream. If we have a buffered
+      // video frame, push it the video queue using the total duration
+      // of the video as the end time.
+      if (mLastVideoFrame) {
+        int64_t durationUs;
+        mOmxDecoder->GetDuration(&durationUs);
+        mLastVideoFrame->mEndTime = (durationUs > mLastVideoFrame->mTime)
+                                  ? durationUs
+                                  : mLastVideoFrame->mTime;
+        mVideoQueue.Push(mLastVideoFrame);
+        mLastVideoFrame = nullptr;
+      }
+      mVideoQueue.Finish();
+      return false;
+    }
+
+    mVideoSeekTimeUs = -1;
+    doSeek = aKeyframeSkip = false;
+
+    nsIntRect picture = mPicture;
+    if (frame.Y.mWidth != mInitialFrame.width ||
+        frame.Y.mHeight != mInitialFrame.height) {
+
+      // Frame size is different from what the container reports. This is legal,
+      // and we will preserve the ratio of the crop rectangle as it
+      // was reported relative to the picture size reported by the container.
+      picture.x = (mPicture.x * frame.Y.mWidth) / mInitialFrame.width;
+      picture.y = (mPicture.y * frame.Y.mHeight) / mInitialFrame.height;
+      picture.width = (frame.Y.mWidth * mPicture.width) / mInitialFrame.width;
+      picture.height = (frame.Y.mHeight * mPicture.height) / mInitialFrame.height;
+    }
+
+    // This is the approximate byte position in the stream.
+    int64_t pos = mDecoder->GetResource()->Tell();
+
+    VideoData *v;
+    if (!frame.mGraphicBuffer) {
+
+      VideoData::YCbCrBuffer b;
+      b.mPlanes[0].mData = static_cast<uint8_t *>(frame.Y.mData);
+      b.mPlanes[0].mStride = frame.Y.mStride;
+      b.mPlanes[0].mHeight = frame.Y.mHeight;
+      b.mPlanes[0].mWidth = frame.Y.mWidth;
+      b.mPlanes[0].mOffset = frame.Y.mOffset;
+      b.mPlanes[0].mSkip = frame.Y.mSkip;
+
+      b.mPlanes[1].mData = static_cast<uint8_t *>(frame.Cb.mData);
+      b.mPlanes[1].mStride = frame.Cb.mStride;
+      b.mPlanes[1].mHeight = frame.Cb.mHeight;
+      b.mPlanes[1].mWidth = frame.Cb.mWidth;
+      b.mPlanes[1].mOffset = frame.Cb.mOffset;
+      b.mPlanes[1].mSkip = frame.Cb.mSkip;
+
+      b.mPlanes[2].mData = static_cast<uint8_t *>(frame.Cr.mData);
+      b.mPlanes[2].mStride = frame.Cr.mStride;
+      b.mPlanes[2].mHeight = frame.Cr.mHeight;
+      b.mPlanes[2].mWidth = frame.Cr.mWidth;
+      b.mPlanes[2].mOffset = frame.Cr.mOffset;
+      b.mPlanes[2].mSkip = frame.Cr.mSkip;
+
+      v = VideoData::Create(mInfo,
+                            mDecoder->GetImageContainer(),
+                            pos,
+                            frame.mTimeUs,
+                            frame.mTimeUs+1, // We don't know the end time.
+                            b,
+                            frame.mKeyFrame,
+                            -1,
+                            picture);
+    } else {
+      v = VideoData::Create(mInfo,
+                            mDecoder->GetImageContainer(),
+                            pos,
+                            frame.mTimeUs,
+                            frame.mTimeUs+1, // We don't know the end time.
+                            frame.mGraphicBuffer,
+                            frame.mKeyFrame,
+                            -1,
+                            picture);
+    }
+
+    if (!v) {
+      NS_WARNING("Unable to create VideoData");
+      return false;
+    }
+
+    parsed++;
+    decoded++;
+    NS_ASSERTION(decoded <= parsed, "Expect to decode fewer frames than parsed in MediaPlugin...");
+
+    // Seeking hack
+    if (mLastVideoFrame && mLastVideoFrame->mTime > v->mTime) {
+      delete mLastVideoFrame;
+      mLastVideoFrame = v;
+      continue;
+    }
+
+    // Since MPAPI doesn't give us the end time of frames, we keep one frame
+    // buffered in nsMediaOmxReader and push it into the queue as soon
+    // we read the following frame so we can use that frame's start time as
+    // the end time of the buffered frame.
+    if (!mLastVideoFrame) {
+      mLastVideoFrame = v;
+      continue;
+    }
+
+    mLastVideoFrame->mEndTime = v->mTime;
+
+    mVideoQueue.Push(mLastVideoFrame);
+
+    // Buffer the current frame we just decoded.
+    mLastVideoFrame = v;
+
+    break;
+  }
+
+  return true;
+}
+
+bool nsMediaOmxReader::DecodeAudioData()
+{
+  NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
+
+  // This is the approximate byte position in the stream.
+  int64_t pos = mDecoder->GetResource()->Tell();
+
+  // Read next frame
+  MPAPI::AudioFrame frame;
+  if (!mOmxDecoder->ReadAudio(&frame, mAudioSeekTimeUs)) {
+    mAudioQueue.Finish();
+    return false;
+  }
+  mAudioSeekTimeUs = -1;
+
+  // Ignore empty buffer which stagefright media read will sporadically return
+  if (frame.mSize == 0) {
+    return true;
+  }
+
+  nsAutoArrayPtr<AudioDataValue> buffer(new AudioDataValue[frame.mSize/2] );
+  memcpy(buffer.get(), frame.mData, frame.mSize);
+
+  uint32_t frames = frame.mSize / (2 * frame.mAudioChannels);
+  CheckedInt64 duration = FramesToUsecs(frames, frame.mAudioSampleRate);
+  if (!duration.isValid()) {
+    return false;
+  }
+
+  mAudioQueue.Push(new AudioData(pos,
+                                 frame.mTimeUs,
+                                 duration.value(),
+                                 frames,
+                                 buffer.forget(),
+                                 frame.mAudioChannels));
+  return true;
+}
+
+nsresult nsMediaOmxReader::Seek(int64_t aTarget, int64_t aStartTime, int64_t aEndTime, int64_t aCurrentTime)
+{
+  NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
+
+  mVideoQueue.Reset();
+  mAudioQueue.Reset();
+
+  mAudioSeekTimeUs = mVideoSeekTimeUs = aTarget;
+
+  return DecodeToTarget(aTarget);
+}
+
+static uint64_t BytesToTime(int64_t offset, uint64_t length, uint64_t durationUs) {
+  double perc = double(offset) / double(length);
+  if (perc > 1.0)
+    perc = 1.0;
+  return uint64_t(double(durationUs) * perc);
+}
+
+nsresult nsMediaOmxReader::GetBuffered(nsTimeRanges* aBuffered, int64_t aStartTime)
+{
+  if (!mOmxDecoder)
+    return NS_OK;
+
+  MediaResource* stream = mOmxDecoder->GetResource();
+
+  int64_t durationUs = 0;
+  mOmxDecoder->GetDuration(&durationUs);
+
+  // Nothing to cache if the media takes 0us to play.
+  if (!durationUs)
+    return NS_OK;
+
+  // Special case completely cached files.  This also handles local files.
+  if (stream->IsDataCachedToEndOfResource(0)) {
+    aBuffered->Add(0, durationUs);
+    return NS_OK;
+  }
+
+  int64_t totalBytes = stream->GetLength();
+
+  // If we can't determine the total size, pretend that we have nothing
+  // buffered. This will put us in a state of eternally-low-on-undecoded-data
+  // which is not get, but about the best we can do.
+  if (totalBytes == -1)
+    return NS_OK;
+
+  int64_t startOffset = stream->GetNextCachedData(0);
+  while (startOffset >= 0) {
+    int64_t endOffset = stream->GetCachedDataEnd(startOffset);
+    // Bytes [startOffset..endOffset] are cached.
+    NS_ASSERTION(startOffset >= 0, "Integer underflow in GetBuffered");
+    NS_ASSERTION(endOffset >= 0, "Integer underflow in GetBuffered");
+
+    uint64_t startUs = BytesToTime(startOffset, totalBytes, durationUs);
+    uint64_t endUs = BytesToTime(endOffset, totalBytes, durationUs);
+    if (startUs != endUs) {
+      aBuffered->Add((double)startUs / USECS_PER_S, (double)endUs / USECS_PER_S);
+    }
+    startOffset = stream->GetNextCachedData(endOffset);
+  }
+  return NS_OK;
+}
new file mode 100644
--- /dev/null
+++ b/content/media/omx/nsMediaOmxReader.h
@@ -0,0 +1,59 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* 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/. */
+#if !defined(nsMediaOmxReader_h_)
+#define nsMediaOmxReader_h_
+
+#include "base/basictypes.h"
+#include "MediaResource.h"
+#include "nsBuiltinDecoder.h"
+#include "nsBuiltinDecoderReader.h"
+#include "OmxDecoder.h"
+
+#include "MPAPI.h"
+
+class nsMediaOmxReader : public nsBuiltinDecoderReader
+{
+  nsCString mType;
+  android::OmxDecoder *mOmxDecoder;
+  bool mHasVideo;
+  bool mHasAudio;
+  nsIntRect mPicture;
+  nsIntSize mInitialFrame;
+  int64_t mVideoSeekTimeUs;
+  int64_t mAudioSeekTimeUs;
+  VideoData *mLastVideoFrame;
+public:
+  nsMediaOmxReader(nsBuiltinDecoder* aDecoder);
+  ~nsMediaOmxReader();
+
+  virtual nsresult Init(nsBuiltinDecoderReader* aCloneDonor);
+  virtual nsresult ResetDecode();
+
+  virtual bool DecodeAudioData();
+  virtual bool DecodeVideoFrame(bool &aKeyframeSkip,
+                                int64_t aTimeThreshold);
+
+  virtual bool HasAudio()
+  {
+    return mHasAudio;
+  }
+
+  virtual bool HasVideo()
+  {
+    return mHasVideo;
+  }
+
+  virtual nsresult ReadMetadata(nsVideoInfo* aInfo,
+                                nsHTMLMediaElement::MetadataTags** aTags);
+  virtual nsresult Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime, int64_t aCurrentTime);
+  virtual nsresult GetBuffered(nsTimeRanges* aBuffered, int64_t aStartTime);
+  virtual bool IsSeekableInBufferedRanges() {
+    return true;
+  }
+
+};
+
+#endif
--- a/content/xtf/src/nsXTFElementWrapper.cpp
+++ b/content/xtf/src/nsXTFElementWrapper.cpp
@@ -849,16 +849,26 @@ bool
 nsXTFElementWrapper::HandledByInner(nsIAtom *attr) const
 {
   bool retval = false;
   if (mAttributeHandler)
     mAttributeHandler->HandlesAttribute(attr, &retval);
   return retval;
 }
 
+/* [notxpcom,nostdcall] uint32_t getScriptableFlags(); */
+// This method isn't automatically forwarded safely because it's notxpcom, so
+// the IDL binding doesn't know what value to return.
+uint32_t
+nsXTFElementWrapper::GetScriptableFlags()
+{
+  return GetBaseXPCClassInfo() ? GetBaseXPCClassInfo()->GetScriptableFlags()
+                               : 0;
+}
+
 nsresult
 nsXTFElementWrapper::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
 {
   nsresult rv = NS_OK;
   if (aVisitor.mEventStatus == nsEventStatus_eConsumeNoDefault ||
       !(mNotificationMask & nsIXTFElement::NOTIFY_HANDLE_DEFAULT)) {
     return rv;
   }
--- a/content/xtf/src/nsXTFElementWrapper.h
+++ b/content/xtf/src/nsXTFElementWrapper.h
@@ -190,13 +190,22 @@ public:
   {
     return mWrapper ? mWrapper->GetInterfacesBitmap() : 0;
   }
 
 private:
   nsXTFElementWrapper* mWrapper;  
 };
 
+/* [notxpcom,nostdcall] uint32_t getScriptableFlags(); */
+// This method isn't automatically forwarded safely because it's notxpcom, so
+// the IDL binding doesn't know what value to return.
+inline uint32_t
+nsXTFClassInfo::GetScriptableFlags()
+{
+  return mWrapper ? mWrapper->GetScriptableFlags() : 0;
+}
+
 nsresult
 NS_NewXTFElementWrapper(nsIXTFElement* aXTFElement, already_AddRefed<nsINodeInfo> aNodeInfo,
                         nsIContent** aResult);
 
 #endif // __NS_XTFELEMENTWRAPPER_H__
--- a/dom/bluetooth/BluetoothDevice.cpp
+++ b/dom/bluetooth/BluetoothDevice.cpp
@@ -115,25 +115,17 @@ BluetoothDevice::SetPropertyByValue(cons
     mPath = value.get_nsString();
   } else if (name.EqualsLiteral("Address")) {
     mAddress = value.get_nsString();
   } else if (name.EqualsLiteral("Class")) {
     mClass = value.get_uint32_t();
   } else if (name.EqualsLiteral("Icon")) {
     mIcon = value.get_nsString();
   } else if (name.EqualsLiteral("Connected")) {
-#ifdef MOZ_WIDGET_GONK
-    // Connected is an 2-byte array
-    // arr[0]: boolean value, true means connected, false means disconnected
-    // arr[1]: disconnection reason
-    InfallibleTArray<uint8_t> arr = value.get_ArrayOfuint8_t();
-    mConnected = (arr[0] == 1);
-#else
     mConnected = value.get_bool();
-#endif
   } else if (name.EqualsLiteral("Paired")) {
     mPaired = value.get_bool();
   } else if (name.EqualsLiteral("UUIDs")) {
     mUuids = value.get_ArrayOfnsString();
     nsresult rv;
     nsIScriptContext* sc = GetContextForEventHandlers(&rv);
     if (sc) {
       rv =
--- a/dom/bluetooth/BluetoothHfpManager.cpp
+++ b/dom/bluetooth/BluetoothHfpManager.cpp
@@ -1,49 +1,256 @@
 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
 /* vim: set ts=2 et sw=2 tw=80: */
 /* 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 "base/basictypes.h"
 #include "BluetoothHfpManager.h"
 
 #include "BluetoothReplyRunnable.h"
 #include "BluetoothService.h"
 #include "BluetoothServiceUuid.h"
 
+#include "mozilla/dom/bluetooth/BluetoothTypes.h"
 #include "mozilla/Services.h"
+#include "nsContentUtils.h"
 #include "nsIObserverService.h"
+#include "nsIRadioInterfaceLayer.h"
+#include "nsISystemMessagesInternal.h"
+#include "nsVariant.h"
+
+#include <unistd.h> /* usleep() */
+
+#define MOZSETTINGS_CHANGED_ID "mozsettings-changed"
+#define AUDIO_VOLUME_MASTER "audio.volume.master"
 
 USING_BLUETOOTH_NAMESPACE
 using namespace mozilla::ipc;
 
 static nsRefPtr<BluetoothHfpManager> sInstance = nullptr;
+static nsCOMPtr<nsIThread> sHfpCommandThread;
+static bool sStopSendingRingFlag = true;
 
-BluetoothHfpManager::BluetoothHfpManager() : mCurrentVgs(-1)
+static int kRingInterval = 3000000;  //unit: us
+
+NS_IMPL_ISUPPORTS1(BluetoothHfpManager, nsIObserver)
+
+class SendRingIndicatorTask : public nsRunnable
 {
+public:
+  SendRingIndicatorTask()
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+  }
+
+  NS_IMETHOD Run()
+  {
+    MOZ_ASSERT(!NS_IsMainThread());
+
+    while (!sStopSendingRingFlag) {
+      sInstance->SendLine("RING");
+
+      usleep(kRingInterval);
+    }
+
+    return NS_OK;
+  }
+};
+
+BluetoothHfpManager::BluetoothHfpManager()
+  : mCurrentVgs(-1)
+  , mCurrentCallIndex(0)
+  , mCurrentCallState(nsIRadioInterfaceLayer::CALL_STATE_DISCONNECTED)
+{
+  nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
+
+  if (obs && NS_FAILED(obs->AddObserver(sInstance, MOZSETTINGS_CHANGED_ID, false))) {
+    NS_WARNING("Failed to add settings change observer!");
+  }
+
+  mListener = new BluetoothRilListener();
+  if (!mListener->StartListening()) {
+    NS_WARNING("Failed to start listening RIL");
+  }
+
+  if (!sHfpCommandThread) {
+    if (NS_FAILED(NS_NewThread(getter_AddRefs(sHfpCommandThread)))) {
+      NS_ERROR("Failed to new thread for sHfpCommandThread");
+    }
+  }
 }
 
 BluetoothHfpManager::~BluetoothHfpManager()
 {
+  if (!mListener->StopListening()) {
+    NS_WARNING("Failed to stop listening RIL");
+  }
+  mListener = nullptr;
+
+  // Shut down the command thread if it still exists.
+  if (sHfpCommandThread) {
+    nsCOMPtr<nsIThread> thread;
+    sHfpCommandThread.swap(thread);
+    if (NS_FAILED(thread->Shutdown())) {
+      NS_WARNING("Failed to shut down the bluetooth hfpmanager command thread!");
+    }
+  }
 }
 
 //static
 BluetoothHfpManager*
 BluetoothHfpManager::Get()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (sInstance == nullptr) {
     sInstance = new BluetoothHfpManager();
   }
 
   return sInstance;
 }
 
+bool
+BluetoothHfpManager::BroadcastSystemMessage(const char* aCommand,
+                                            const int aCommandLength)
+{
+  nsString type;
+  type.AssignLiteral("bluetooth-dialer-command");
+
+  JSContext* cx = nsContentUtils::GetSafeJSContext();
+  NS_ASSERTION(!::JS_IsExceptionPending(cx),
+               "Shouldn't get here when an exception is pending!");
+
+  JSAutoRequest jsar(cx);
+  JSObject* obj = JS_NewObject(cx, NULL, NULL, NULL);
+  if (!obj) {
+    NS_WARNING("Failed to new JSObject for system message!");
+    return false;
+  }
+
+  JSString* JsData = JS_NewStringCopyN(cx, aCommand, aCommandLength);
+  if (!JsData) {
+    NS_WARNING("JS_NewStringCopyN is out of memory");
+    return false;
+  }
+
+  jsval v = STRING_TO_JSVAL(JsData);
+  if (!JS_SetProperty(cx, obj, "command", &v)) {
+    NS_WARNING("Failed to set properties of system message!");
+    return false;
+  }
+
+  nsCOMPtr<nsISystemMessagesInternal> systemMessenger =
+    do_GetService("@mozilla.org/system-message-internal;1");
+
+  if (!systemMessenger) {
+    NS_WARNING("Failed to get SystemMessenger service!");
+    return false;
+  }
+
+  systemMessenger->BroadcastMessage(type, OBJECT_TO_JSVAL(obj));
+
+  return true;
+}
+
+nsresult
+BluetoothHfpManager::HandleVolumeChanged(const nsAString& aData)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  // The string that we're interested in will be a JSON string that looks like:
+  //  {"key":"volumeup", "value":1.0}
+  //  {"key":"volumedown", "value":0.2}
+
+  JSContext* cx = nsContentUtils::GetSafeJSContext();
+  if (!cx) {
+    return NS_OK;
+  }
+
+  JS::Value val;
+  if (!JS_ParseJSON(cx, aData.BeginReading(), aData.Length(), &val)) {
+    return JS_ReportPendingException(cx) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+  }
+
+  if (!val.isObject()) {
+    return NS_OK;
+  }
+
+  JSObject& obj(val.toObject());
+
+  JS::Value key;
+  if (!JS_GetProperty(cx, &obj, "key", &key)) {
+    MOZ_ASSERT(!JS_IsExceptionPending(cx));
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
+  if (!key.isString()) {
+    return NS_OK;
+  }
+
+  JSBool match;
+  if (!JS_StringEqualsAscii(cx, key.toString(), AUDIO_VOLUME_MASTER, &match)) {
+    MOZ_ASSERT(!JS_IsExceptionPending(cx));
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
+  if (!match) {
+    return NS_OK;
+  }
+
+  JS::Value value;
+  if (!JS_GetProperty(cx, &obj, "value", &value)) {
+    MOZ_ASSERT(!JS_IsExceptionPending(cx));
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
+  if (!value.isNumber()) {
+    return NS_ERROR_UNEXPECTED;
+  }
+
+  // AG volume range: [0.0, 1.0]
+  float volume = value.toNumber();
+
+  // HS volume range: [0, 15]
+  mCurrentVgs = ceil(volume * 15);
+
+  nsDiscriminatedUnion du;
+  du.mType = 0;
+  du.u.mInt8Value = mCurrentVgs;
+
+  nsCString vgs;
+  if (NS_FAILED(nsVariant::ConvertToACString(du, vgs))) {
+    NS_WARNING("Failed to convert volume to string");
+    return NS_ERROR_FAILURE;
+  }
+
+  nsAutoCString newVgs;
+  newVgs += "+VGS: ";
+  newVgs += vgs;
+
+  SendLine(newVgs.get());
+
+  return NS_OK;
+}
+
+nsresult
+BluetoothHfpManager::Observe(nsISupports* aSubject,
+                             const char* aTopic,
+                             const PRUnichar* aData)
+{
+  if (!strcmp(aTopic, MOZSETTINGS_CHANGED_ID)) {
+    return HandleVolumeChanged(nsDependentString(aData));
+  } else {
+    MOZ_ASSERT(false, "BluetoothHfpManager got unexpected topic!");
+  }
+  return NS_ERROR_UNEXPECTED;
+}
+
 // Virtual function of class SocketConsumer
 void
 BluetoothHfpManager::ReceiveSocketData(UnixSocketRawData* aMessage)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   const char* msg = (const char*)aMessage->mData;
 
@@ -103,16 +310,34 @@ BluetoothHfpManager::ReceiveSocketData(U
       os->NotifyObservers(nullptr, "bluetooth-volume-change", NS_LITERAL_STRING("up").get());
     } else if (newVgs < mCurrentVgs) {
       os->NotifyObservers(nullptr, "bluetooth-volume-change", NS_LITERAL_STRING("down").get());
     }
 
     mCurrentVgs = newVgs;
 
     SendLine("OK");
+  } else if (!strncmp(msg, "AT+BLDN", 7)) {
+    if (!BroadcastSystemMessage("BLDN", 4)) {
+      NS_WARNING("Failed to broadcast system message to dialer");
+      return;
+    }
+    SendLine("OK");
+  } else if (!strncmp(msg, "ATA", 3)) {
+    if (!BroadcastSystemMessage("ATA", 3)) {
+      NS_WARNING("Failed to broadcast system message to dialer");
+      return;
+    }
+    SendLine("OK");
+  } else if (!strncmp(msg, "AT+CHUP", 7)) {
+    if (!BroadcastSystemMessage("CHUP", 4)) {
+      NS_WARNING("Failed to broadcast system message to dialer");
+      return;
+    }
+    SendLine("OK");
   } else {
 #ifdef DEBUG
     nsCString warningMsg;
     warningMsg.AssignLiteral("Not handling HFP message, reply ok: ");
     warningMsg.Append(msg);
     NS_WARNING(warningMsg.get());
 #endif
     SendLine("OK");
@@ -162,8 +387,97 @@ BluetoothHfpManager::SendLine(const char
 
   msg += kHfpCrlf;
   msg += aMessage;
   msg += kHfpCrlf;
 
   return SendSocketData(msg);
 }
 
+/*
+ * CallStateChanged will be called whenever call status is changed, and it
+ * also means we need to notify HS about the change. For more information, 
+ * please refer to 4.13 ~ 4.15 in Bluetooth hands-free profile 1.6.
+ */
+void
+BluetoothHfpManager::CallStateChanged(int aCallIndex, int aCallState,
+                                      const char* aNumber, bool aIsActive)
+{
+  nsRefPtr<nsRunnable> sendRingTask;
+
+  switch (aCallState) {
+    case nsIRadioInterfaceLayer::CALL_STATE_INCOMING:
+      // Send "CallSetup = 1"
+      SendLine("+CIEV: 5,1");
+
+      // Start sending RING indicator to HF
+      sStopSendingRingFlag = false;
+      sendRingTask = new SendRingIndicatorTask();
+
+      if (NS_FAILED(sHfpCommandThread->Dispatch(sendRingTask, NS_DISPATCH_NORMAL))) {
+        NS_WARNING("Cannot dispatch ring task!");
+        return;
+      };
+      break;
+    case nsIRadioInterfaceLayer::CALL_STATE_DIALING:
+      // Send "CallSetup = 2"
+      SendLine("+CIEV: 5,2");
+      break;
+    case nsIRadioInterfaceLayer::CALL_STATE_ALERTING:
+      // Send "CallSetup = 3"
+      if (mCurrentCallIndex == nsIRadioInterfaceLayer::CALL_STATE_DIALING) {
+        SendLine("+CIEV: 5,3");
+      } else {
+#ifdef DEBUG
+        NS_WARNING("Not handling state changed");
+#endif
+      }
+      break;
+    case nsIRadioInterfaceLayer::CALL_STATE_CONNECTED:
+      switch (mCurrentCallState) {
+        case nsIRadioInterfaceLayer::CALL_STATE_INCOMING:
+          sStopSendingRingFlag = true;
+          // Continue executing, no break
+        case nsIRadioInterfaceLayer::CALL_STATE_DIALING:
+          // Send "Call = 1, CallSetup = 0"
+          SendLine("+CIEV: 4,1");
+          SendLine("+CIEV: 5,0");
+          break;
+        default:
+#ifdef DEBUG
+          NS_WARNING("Not handling state changed");
+#endif
+          break;
+      }
+
+      break;
+    case nsIRadioInterfaceLayer::CALL_STATE_DISCONNECTED:
+      switch (mCurrentCallState) {
+        case nsIRadioInterfaceLayer::CALL_STATE_INCOMING:
+          sStopSendingRingFlag = true;
+          // Continue executing, no break
+        case nsIRadioInterfaceLayer::CALL_STATE_DIALING:
+        case nsIRadioInterfaceLayer::CALL_STATE_ALERTING:
+          // Send "CallSetup = 0"
+          SendLine("+CIEV: 5,0");
+          break;
+        case nsIRadioInterfaceLayer::CALL_STATE_CONNECTED:
+          // Send "Call = 0"
+          SendLine("+CIEV: 4,0");
+          break;
+        default:
+#ifdef DEBUG
+          NS_WARNING("Not handling state changed");
+#endif
+          break;
+      }
+      break;
+
+    default:
+#ifdef DEBUG
+      NS_WARNING("Not handling state changed");
+#endif
+      break;
+  }
+
+  mCurrentCallIndex = aCallIndex;
+  mCurrentCallState = aCallState;
+}
--- a/dom/bluetooth/BluetoothHfpManager.h
+++ b/dom/bluetooth/BluetoothHfpManager.h
@@ -3,36 +3,51 @@
 /* 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/. */
 
 #ifndef mozilla_dom_bluetooth_bluetoothhfpmanager_h__
 #define mozilla_dom_bluetooth_bluetoothhfpmanager_h__
 
 #include "BluetoothCommon.h"
+#include "BluetoothRilListener.h"
 #include "mozilla/ipc/UnixSocket.h"
+#include "nsIObserver.h"
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 class BluetoothReplyRunnable;
 
 class BluetoothHfpManager : public mozilla::ipc::UnixSocketConsumer
+                          , public nsIObserver
 {
 public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIOBSERVER
+
   ~BluetoothHfpManager();
 
   static BluetoothHfpManager* Get();
   void ReceiveSocketData(mozilla::ipc::UnixSocketRawData* aMessage);
 
   bool Connect(const nsAString& aDeviceObjectPath,
                BluetoothReplyRunnable* aRunnable);
   void Disconnect();
   bool SendLine(const char* aMessage);
+  void CallStateChanged(int aCallIndex, int aCallState,
+                        const char* aNumber, bool aIsActive);
 
 private:
   BluetoothHfpManager();
 
+  bool BroadcastSystemMessage(const char* aCommand,
+                              const int aCommandLength);
+  nsresult HandleVolumeChanged(const nsAString& aData);
+
   int mCurrentVgs;
+  int mCurrentCallIndex;
+  int mCurrentCallState;
+  nsAutoPtr<BluetoothRilListener> mListener;
 };
 
 END_BLUETOOTH_NAMESPACE
 
 #endif
new file mode 100644
--- /dev/null
+++ b/dom/bluetooth/BluetoothRilListener.cpp
@@ -0,0 +1,89 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* 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 "BluetoothRilListener.h"
+
+#include "BluetoothHfpManager.h"
+#include "nsRadioInterfaceLayer.h"
+#include "nsServiceManagerUtils.h"
+#include "nsString.h"
+
+USING_BLUETOOTH_NAMESPACE
+
+class BluetoothRILTelephonyCallback : public nsIRILTelephonyCallback
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIRILTELEPHONYCALLBACK
+
+  BluetoothRILTelephonyCallback() { }
+};
+
+NS_IMPL_ISUPPORTS1(BluetoothRILTelephonyCallback, nsIRILTelephonyCallback)
+
+NS_IMETHODIMP
+BluetoothRILTelephonyCallback::CallStateChanged(PRUint32 aCallIndex,
+                                                PRUint16 aCallState,
+                                                const nsAString& aNumber,
+                                                bool aIsActive)
+{
+  BluetoothHfpManager* hfp = BluetoothHfpManager::Get();
+  hfp->CallStateChanged(aCallIndex, aCallState,
+                        NS_ConvertUTF16toUTF8(aNumber).get(), aIsActive);
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+BluetoothRILTelephonyCallback::EnumerateCallState(PRUint32 aCallIndex,
+                                                  PRUint16 aCallState,
+                                                  const nsAString_internal& aNumber,
+                                                  bool aIsActive,
+                                                  bool* aResult)
+{
+  *aResult = true;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+BluetoothRILTelephonyCallback::NotifyError(PRInt32 aCallIndex,
+                                           const nsAString& aError)
+{
+  return NS_OK;
+}
+
+BluetoothRilListener::BluetoothRilListener()
+{
+  mRILTelephonyCallback = new BluetoothRILTelephonyCallback();
+}
+
+bool
+BluetoothRilListener::StartListening()
+{
+  nsCOMPtr<nsIRILContentHelper> ril = do_GetService(NS_RILCONTENTHELPER_CONTRACTID);
+  if (!ril) {
+    NS_ERROR("No RIL Service!");
+    return false;
+  }
+
+  nsresult rv = ril->RegisterTelephonyCallback(mRILTelephonyCallback);
+
+  return NS_FAILED(rv) ? false : true;
+}
+
+bool
+BluetoothRilListener::StopListening()
+{
+  nsCOMPtr<nsIRILContentHelper> ril = do_GetService(NS_RILCONTENTHELPER_CONTRACTID);
+  if (!ril) {
+    NS_ERROR("No RIL Service!");
+    return false;
+  }
+
+  nsresult rv = ril->UnregisterTelephonyCallback(mRILTelephonyCallback);
+
+  return NS_FAILED(rv) ? false : true;
+}
new file mode 100644
--- /dev/null
+++ b/dom/bluetooth/BluetoothRilListener.h
@@ -0,0 +1,31 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* 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/. */
+
+#ifndef mozilla_dom_bluetooth_bluetoothrillistener_h__
+#define mozilla_dom_bluetooth_bluetoothrillistener_h__
+
+#include "BluetoothCommon.h"
+
+#include "nsCOMPtr.h"
+#include "nsIRadioInterfaceLayer.h"
+
+BEGIN_BLUETOOTH_NAMESPACE
+
+class BluetoothRilListener
+{
+public:
+  BluetoothRilListener();
+
+  bool StartListening();
+  bool StopListening();
+
+private:
+  nsCOMPtr<nsIRILTelephonyCallback> mRILTelephonyCallback;
+};
+
+END_BLUETOOTH_NAMESPACE
+
+#endif
--- a/dom/bluetooth/Makefile.in
+++ b/dom/bluetooth/Makefile.in
@@ -50,16 +50,20 @@ CPPSRCS += \
   BluetoothUtils.cpp \
   BluetoothChild.cpp \
   BluetoothParent.cpp \
   BluetoothServiceChildProcess.cpp \
   BluetoothUnixSocketConnector.cpp \
   BluetoothHfpManager.cpp \
   $(NULL)
 
+ifdef MOZ_B2G_RIL
+CPPSRCS += BluetoothRilListener.cpp
+endif
+
 XPIDLSRCS = \
   nsIDOMNavigatorBluetooth.idl \
   nsIDOMBluetoothManager.idl \
   nsIDOMBluetoothAdapter.idl \
   nsIDOMBluetoothDevice.idl \
   nsIDOMBluetoothDeviceEvent.idl \
   nsIDOMBluetoothDeviceAddressEvent.idl \
   nsIDOMBluetoothPropertyEvent.idl \
--- a/dom/bluetooth/linux/BluetoothDBusService.cpp
+++ b/dom/bluetooth/linux/BluetoothDBusService.cpp
@@ -76,21 +76,17 @@ typedef struct {
 
 static Properties sDeviceProperties[] = {
   {"Address", DBUS_TYPE_STRING},
   {"Name", DBUS_TYPE_STRING},
   {"Icon", DBUS_TYPE_STRING},
   {"Class", DBUS_TYPE_UINT32},
   {"UUIDs", DBUS_TYPE_ARRAY},
   {"Paired", DBUS_TYPE_BOOLEAN},
-#ifdef MOZ_WIDGET_GONK
-  {"Connected", DBUS_TYPE_ARRAY},
-#else
   {"Connected", DBUS_TYPE_BOOLEAN},
-#endif
   {"Trusted", DBUS_TYPE_BOOLEAN},
   {"Blocked", DBUS_TYPE_BOOLEAN},
   {"Alias", DBUS_TYPE_STRING},
   {"Nodes", DBUS_TYPE_ARRAY},
   {"Adapter", DBUS_TYPE_OBJECT_PATH},
   {"LegacyPairing", DBUS_TYPE_BOOLEAN},
   {"RSSI", DBUS_TYPE_INT16},
   {"TX", DBUS_TYPE_UINT32},
--- a/dom/camera/GonkNativeWindow.cpp
+++ b/dom/camera/GonkNativeWindow.cpp
@@ -298,16 +298,28 @@ int GonkNativeWindow::getSlotFromBufferL
         if (mSlots[i].mGraphicBuffer != NULL && mSlots[i].mGraphicBuffer->handle == buffer->handle) {
             return i;
         }
     }
     CNW_LOGE("getSlotFromBufferLocked: unknown buffer: %p", buffer->handle);
     return BAD_VALUE;
 }
 
+mozilla::layers::SurfaceDescriptor *
+GonkNativeWindow::getSurfaceDescriptorFromBuffer(ANativeWindowBuffer* buffer)
+{
+  int buf = getSlotFromBufferLocked(buffer);
+  if (buf < 0 || buf >= mBufferCount ||
+      mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
+    return nullptr;
+  }
+
+  return &mSlots[buf].mSurfaceDescriptor;
+}
+
 int GonkNativeWindow::queueBuffer(ANativeWindowBuffer* buffer)
 {
     {
         Mutex::Autolock lock(mMutex);
         CNW_LOGD("queueBuffer: E");
         int buf = getSlotFromBufferLocked(buffer);
 
         if (buf < 0 || buf >= mBufferCount) {
@@ -428,37 +440,36 @@ int GonkNativeWindow::cancelBuffer(ANati
     mSlots[buf].mFrameNumber = 0;
     mDequeueCondition.signal();
     return OK;
 }
 
 int GonkNativeWindow::perform(int operation, va_list args)
 {
     switch (operation) {
+        case NATIVE_WINDOW_SET_BUFFERS_SIZE:
+        case NATIVE_WINDOW_SET_SCALING_MODE:
+        case NATIVE_WINDOW_SET_CROP:
         case NATIVE_WINDOW_CONNECT:
-            // deprecated. must return NO_ERROR.
-            return NO_ERROR;
         case NATIVE_WINDOW_DISCONNECT:
             // deprecated. must return NO_ERROR.
             return NO_ERROR;
         case NATIVE_WINDOW_SET_USAGE:
             return dispatchSetUsage(args);
         case NATIVE_WINDOW_SET_BUFFER_COUNT:
             return dispatchSetBufferCount(args);
         case NATIVE_WINDOW_SET_BUFFERS_GEOMETRY:
             return dispatchSetBuffersGeometry(args);
         case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP:
             return dispatchSetBuffersTimestamp(args);
         case NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS:
             return dispatchSetBuffersDimensions(args);
         case NATIVE_WINDOW_SET_BUFFERS_FORMAT:
             return dispatchSetBuffersFormat(args);
-        case NATIVE_WINDOW_SET_CROP:
         case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM:
-        case NATIVE_WINDOW_SET_SCALING_MODE:
         case NATIVE_WINDOW_LOCK:
         case NATIVE_WINDOW_UNLOCK_AND_POST:
         case NATIVE_WINDOW_API_CONNECT:
         case NATIVE_WINDOW_API_DISCONNECT:
         default:
             return INVALID_OPERATION;
     }
 }
--- a/dom/camera/GonkNativeWindow.h
+++ b/dom/camera/GonkNativeWindow.h
@@ -45,21 +45,23 @@ namespace android {
 class GonkNativeWindowNewFrameCallback {
 public:
     virtual void OnNewFrame() = 0;
 };
 
 class GonkNativeWindow : public EGLNativeBase<ANativeWindow, GonkNativeWindow, RefBase>
 {
     typedef mozilla::layers::SurfaceDescriptor SurfaceDescriptor;
+    typedef mozilla::layers::GraphicBufferLocked GraphicBufferLocked;
 
 public:
     enum { MIN_UNDEQUEUED_BUFFERS = 2 };
     enum { MIN_BUFFER_SLOTS = MIN_UNDEQUEUED_BUFFERS };
     enum { NUM_BUFFER_SLOTS = 32 };
+    enum { NATIVE_WINDOW_SET_BUFFERS_SIZE = 0x10000000 };
 
     GonkNativeWindow();
     GonkNativeWindow(GonkNativeWindowNewFrameCallback* aCallback);
     ~GonkNativeWindow(); // this class cannot be overloaded
 
     // ANativeWindow hooks
     static int hook_cancelBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer);
     static int hook_dequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer);
@@ -75,16 +77,18 @@ public:
 
     // Return the buffer to the queue and mark it as FREE. After that
     // the buffer is useable again for the decoder.
     bool returnBuffer(uint32_t index, uint32_t generation);
 
     // Release all internal buffers
     void abandon();
 
+    SurfaceDescriptor *getSurfaceDescriptorFromBuffer(ANativeWindowBuffer* buffer);
+
 protected:
     virtual int cancelBuffer(ANativeWindowBuffer* buffer);
     virtual int dequeueBuffer(ANativeWindowBuffer** buffer);
     virtual int lockBuffer(ANativeWindowBuffer* buffer);
     virtual int perform(int operation, va_list args);
     virtual int query(int what, int* value) const;
     virtual int queueBuffer(ANativeWindowBuffer* buffer);
     virtual int setSwapInterval(int interval);
@@ -229,16 +233,17 @@ private:
     GonkNativeWindowNewFrameCallback* mNewFrameCallback;
 };
 
 
 // CameraGraphicBuffer maintains the buffer returned from GonkNativeWindow
 class CameraGraphicBuffer : public mozilla::layers::GraphicBufferLocked
 {
     typedef mozilla::layers::SurfaceDescriptor SurfaceDescriptor;
+    typedef mozilla::layers::ImageBridgeChild ImageBridgeChild;
 
 public:
     CameraGraphicBuffer(GonkNativeWindow* aNativeWindow,
                         uint32_t aIndex,
                         uint32_t aGeneration,
                         SurfaceDescriptor aBuffer)
         : GraphicBufferLocked(aBuffer)
         , mNativeWindow(aNativeWindow)
--- a/dom/camera/Makefile.in
+++ b/dom/camera/Makefile.in
@@ -28,30 +28,38 @@ CPPSRCS = \
 
 ifeq ($(MOZ_B2G_CAMERA),1)
 CPPSRCS += \
   GonkCameraManager.cpp \
   GonkCameraControl.cpp \
   GonkCameraHwMgr.cpp \
   GonkNativeWindow.cpp \
   $(NULL)
+else ifeq (gonk,$(MOZ_WIDGET_TOOLKIT))
+CPPSRCS += \
+  FallbackCameraManager.cpp \
+  FallbackCameraControl.cpp \
+  GonkNativeWindow.cpp \
+  $(NULL)
 else
 CPPSRCS += \
   FallbackCameraManager.cpp \
   FallbackCameraControl.cpp \
   $(NULL)
 endif
 
 XPIDLSRCS = \
   nsIDOMNavigatorCamera.idl \
   nsIDOMCameraManager.idl \
   $(NULL)
 
 EXPORTS = \
+  CameraCommon.h \
   DOMCameraManager.h \
+  GonkNativeWindow.h \
   $(NULL)
 
 include $(topsrcdir)/config/rules.mk
 include $(topsrcdir)/ipc/chromium/chromium-config.mk
 
 XPIDL_FLAGS += \
   -I$(topsrcdir)/dom/base \
   -I$(topsrcdir)/dom/interfaces/base \
--- a/dom/imptests/failures/editing/conformancetest/Makefile.in
+++ b/dom/imptests/failures/editing/conformancetest/Makefile.in
@@ -1,18 +1,20 @@
-DEPTH = @DEPTH@
+# THIS FILE IS AUTOGENERATED BY parseFailures.py - DO NOT EDIT
+
+DEPTH := @DEPTH@
 
-topsrcdir = @top_srcdir@
-srcdir = @srcdir@
-VPATH = @srcdir@
-relativesrcdir = @relativesrcdir@
-
-DIRS = \
-  $(NULL)
+topsrcdir := @top_srcdir@
+srcdir := @srcdir@
+VPATH := @srcdir@
+relativesrcdir := @relativesrcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
-MOCHITEST_FILES = \
+DIRS := \
+  $(NULL)
+
+MOCHITEST_FILES := \
   test_event.html.json \
   test_runtest.html.json \
   $(NULL)
 
 include $(topsrcdir)/config/rules.mk
--- a/dom/imptests/failures/editing/conformancetest/test_runtest.html.json
+++ b/dom/imptests/failures/editing/conformancetest/test_runtest.html.json
@@ -2364,26 +2364,16 @@
   "[[\"defaultparagraphseparator\",\"p\"],[\"formatblock\",\"<h6>\"]] \"<div>[foobar]</div>\" queryCommandValue(\"defaultparagraphseparator\") after":true,
   "[[\"defaultparagraphseparator\",\"p\"],[\"formatblock\",\"<h6>\"]] \"<div>[foobar]</div>\" queryCommandValue(\"formatblock\") before":true,
   "[[\"formatblock\",\"<ins>\"]] \"<div>[foobar]</div>\" queryCommandValue(\"formatblock\") before":true,
   "[[\"formatblock\",\"<ins>\"]] \"<div>[foobar]</div>\" queryCommandValue(\"formatblock\") after":true,
   "[[\"formatblock\",\"<li>\"]] \"<div>[foobar]</div>\" queryCommandValue(\"formatblock\") before":true,
   "[[\"formatblock\",\"<li>\"]] \"<div>[foobar]</div>\" queryCommandValue(\"formatblock\") after":true,
   "[[\"formatblock\",\"<ol>\"]] \"<div>[foobar]</div>\" queryCommandValue(\"formatblock\") before":true,
   "[[\"formatblock\",\"<ol>\"]] \"<div>[foobar]</div>\" queryCommandValue(\"formatblock\") after":true,
-  "[[\"defaultparagraphseparator\",\"div\"],[\"formatblock\",\"<p>\"]] \"<div>[foobar]</div>\": execCommand(\"defaultparagraphseparator\", false, \"div\") return value":true,
-  "[[\"defaultparagraphseparator\",\"div\"],[\"formatblock\",\"<p>\"]] \"<div>[foobar]</div>\" compare innerHTML":true,
-  "[[\"defaultparagraphseparator\",\"div\"],[\"formatblock\",\"<p>\"]] \"<div>[foobar]</div>\" queryCommandValue(\"defaultparagraphseparator\") before":true,
-  "[[\"defaultparagraphseparator\",\"div\"],[\"formatblock\",\"<p>\"]] \"<div>[foobar]</div>\" queryCommandValue(\"defaultparagraphseparator\") after":true,
-  "[[\"defaultparagraphseparator\",\"div\"],[\"formatblock\",\"<p>\"]] \"<div>[foobar]</div>\" queryCommandValue(\"formatblock\") before":true,
-  "[[\"defaultparagraphseparator\",\"p\"],[\"formatblock\",\"<p>\"]] \"<div>[foobar]</div>\": execCommand(\"defaultparagraphseparator\", false, \"p\") return value":true,
-  "[[\"defaultparagraphseparator\",\"p\"],[\"formatblock\",\"<p>\"]] \"<div>[foobar]</div>\" compare innerHTML":true,
-  "[[\"defaultparagraphseparator\",\"p\"],[\"formatblock\",\"<p>\"]] \"<div>[foobar]</div>\" queryCommandValue(\"defaultparagraphseparator\") before":true,
-  "[[\"defaultparagraphseparator\",\"p\"],[\"formatblock\",\"<p>\"]] \"<div>[foobar]</div>\" queryCommandValue(\"defaultparagraphseparator\") after":true,
-  "[[\"defaultparagraphseparator\",\"p\"],[\"formatblock\",\"<p>\"]] \"<div>[foobar]</div>\" queryCommandValue(\"formatblock\") before":true,
   "[[\"defaultparagraphseparator\",\"div\"],[\"formatblock\",\"<pre>\"]] \"<div>[foobar]</div>\": execCommand(\"defaultparagraphseparator\", false, \"div\") return value":true,
   "[[\"defaultparagraphseparator\",\"div\"],[\"formatblock\",\"<pre>\"]] \"<div>[foobar]</div>\" compare innerHTML":true,
   "[[\"defaultparagraphseparator\",\"div\"],[\"formatblock\",\"<pre>\"]] \"<div>[foobar]</div>\" queryCommandValue(\"defaultparagraphseparator\") before":true,
   "[[\"defaultparagraphseparator\",\"div\"],[\"formatblock\",\"<pre>\"]] \"<div>[foobar]</div>\" queryCommandValue(\"defaultparagraphseparator\") after":true,
   "[[\"defaultparagraphseparator\",\"div\"],[\"formatblock\",\"<pre>\"]] \"<div>[foobar]</div>\" queryCommandValue(\"formatblock\") before":true,
   "[[\"defaultparagraphseparator\",\"p\"],[\"formatblock\",\"<pre>\"]] \"<div>[foobar]</div>\": execCommand(\"defaultparagraphseparator\", false, \"p\") return value":true,
   "[[\"defaultparagraphseparator\",\"p\"],[\"formatblock\",\"<pre>\"]] \"<div>[foobar]</div>\" compare innerHTML":true,
   "[[\"defaultparagraphseparator\",\"p\"],[\"formatblock\",\"<pre>\"]] \"<div>[foobar]</div>\" queryCommandValue(\"defaultparagraphseparator\") before":true,
@@ -2404,24 +2394,16 @@
   "[[\"defaultparagraphseparator\",\"div\"],[\"formatblock\",\"<dd>\"]] \"<p>[foobar]</p>\": execCommand(\"defaultparagraphseparator\", false, \"div\") return value":true,
   "[[\"defaultparagraphseparator\",\"div\"],[\"formatblock\",\"<dd>\"]] \"<p>[foobar]</p>\" queryCommandValue(\"defaultparagraphseparator\") before":true,
   "[[\"defaultparagraphseparator\",\"div\"],[\"formatblock\",\"<dd>\"]] \"<p>[foobar]</p>\" queryCommandValue(\"defaultparagraphseparator\") after":true,
   "[[\"defaultparagraphseparator\",\"div\"],[\"formatblock\",\"<dd>\"]] \"<p>[foobar]</p>\" queryCommandValue(\"formatblock\") after":true,
   "[[\"defaultparagraphseparator\",\"p\"],[\"formatblock\",\"<dd>\"]] \"<p>[foobar]</p>\": execCommand(\"defaultparagraphseparator\", false, \"p\") return value":true,
   "[[\"defaultparagraphseparator\",\"p\"],[\"formatblock\",\"<dd>\"]] \"<p>[foobar]</p>\" queryCommandValue(\"defaultparagraphseparator\") before":true,
   "[[\"defaultparagraphseparator\",\"p\"],[\"formatblock\",\"<dd>\"]] \"<p>[foobar]</p>\" queryCommandValue(\"defaultparagraphseparator\") after":true,
   "[[\"defaultparagraphseparator\",\"p\"],[\"formatblock\",\"<dd>\"]] \"<p>[foobar]</p>\" queryCommandValue(\"formatblock\") after":true,
-  "[[\"defaultparagraphseparator\",\"div\"],[\"formatblock\",\"<div>\"]] \"<p>[foobar]</p>\": execCommand(\"defaultparagraphseparator\", false, \"div\") return value":true,
-  "[[\"defaultparagraphseparator\",\"div\"],[\"formatblock\",\"<div>\"]] \"<p>[foobar]</p>\" queryCommandValue(\"defaultparagraphseparator\") before":true,
-  "[[\"defaultparagraphseparator\",\"div\"],[\"formatblock\",\"<div>\"]] \"<p>[foobar]</p>\" queryCommandValue(\"defaultparagraphseparator\") after":true,
-  "[[\"defaultparagraphseparator\",\"div\"],[\"formatblock\",\"<div>\"]] \"<p>[foobar]</p>\" queryCommandValue(\"formatblock\") after":true,
-  "[[\"defaultparagraphseparator\",\"p\"],[\"formatblock\",\"<div>\"]] \"<p>[foobar]</p>\": execCommand(\"defaultparagraphseparator\", false, \"p\") return value":true,
-  "[[\"defaultparagraphseparator\",\"p\"],[\"formatblock\",\"<div>\"]] \"<p>[foobar]</p>\" queryCommandValue(\"defaultparagraphseparator\") before":true,
-  "[[\"defaultparagraphseparator\",\"p\"],[\"formatblock\",\"<div>\"]] \"<p>[foobar]</p>\" queryCommandValue(\"defaultparagraphseparator\") after":true,
-  "[[\"defaultparagraphseparator\",\"p\"],[\"formatblock\",\"<div>\"]] \"<p>[foobar]</p>\" queryCommandValue(\"formatblock\") after":true,
   "[[\"formatblock\",\"<dl>\"]] \"<p>[foobar]</p>\": execCommand(\"formatblock\", false, \"<dl>\") return value":true,
   "[[\"formatblock\",\"<dl>\"]] \"<p>[foobar]</p>\" compare innerHTML":true,
   "[[\"formatblock\",\"<dl>\"]] \"<p>[foobar]</p>\" queryCommandValue(\"formatblock\") after":true,
   "[[\"defaultparagraphseparator\",\"div\"],[\"formatblock\",\"<dt>\"]] \"<p>[foobar]</p>\": execCommand(\"defaultparagraphseparator\", false, \"div\") return value":true,
   "[[\"defaultparagraphseparator\",\"div\"],[\"formatblock\",\"<dt>\"]] \"<p>[foobar]</p>\" queryCommandValue(\"defaultparagraphseparator\") before":true,
   "[[\"defaultparagraphseparator\",\"div\"],[\"formatblock\",\"<dt>\"]] \"<p>[foobar]</p>\" queryCommandValue(\"defaultparagraphseparator\") after":true,
   "[[\"defaultparagraphseparator\",\"div\"],[\"formatblock\",\"<dt>\"]] \"<p>[foobar]</p>\" queryCommandValue(\"formatblock\") after":true,
   "[[\"defaultparagraphseparator\",\"p\"],[\"formatblock\",\"<dt>\"]] \"<p>[foobar]</p>\": execCommand(\"defaultparagraphseparator\", false, \"p\") return value":true,
@@ -3900,22 +3882,16 @@
   "[[\"stylewithcss\",\"false\"],[\"defaultparagraphseparator\",\"p\"],[\"inserthorizontalrule\",\"\"]] \"<p>foo<b>b[a]r</b>baz</p>\": execCommand(\"defaultparagraphseparator\", false, \"p\") return value":true,
   "[[\"stylewithcss\",\"false\"],[\"defaultparagraphseparator\",\"p\"],[\"inserthorizontalrule\",\"\"]] \"<p>foo<b>b[a]r</b>baz</p>\" queryCommandValue(\"defaultparagraphseparator\") before":true,
   "[[\"stylewithcss\",\"false\"],[\"defaultparagraphseparator\",\"p\"],[\"inserthorizontalrule\",\"\"]] \"<p>foo<b>b[a]r</b>baz</p>\" queryCommandValue(\"defaultparagraphseparator\") after":true,
   "[[\"inserthorizontalrule\",\"\"]] \"<address>foo[bar]baz</address>\" compare innerHTML":true,
   "[[\"inserthorizontalrule\",\"\"]] \"<bdi>foo[bar]baz</bdi>\" compare innerHTML":true,
   "[[\"inserthorizontalrule\",\"\"]] \"<table><caption>foo[bar]baz</caption><tr><td>quz</table>\": execCommand(\"inserthorizontalrule\", false, \"\") return value":true,
   "[[\"inserthorizontalrule\",\"\"]] \"<table><caption>foo[bar]baz</caption><tr><td>quz</table>\" compare innerHTML":true,
   "[[\"inserthorizontalrule\",\"\"]] \"<dl><dt>foo[bar]baz</dt></dl>\" compare innerHTML":true,
-  "[[\"defaultparagraphseparator\",\"div\"],[\"inserthorizontalrule\",\"\"]] \"<p>foo[bar]baz</p>\": execCommand(\"defaultparagraphseparator\", false, \"div\") return value":true,
-  "[[\"defaultparagraphseparator\",\"div\"],[\"inserthorizontalrule\",\"\"]] \"<p>foo[bar]baz</p>\" queryCommandValue(\"defaultparagraphseparator\") before":true,
-  "[[\"defaultparagraphseparator\",\"div\"],[\"inserthorizontalrule\",\"\"]] \"<p>foo[bar]baz</p>\" queryCommandValue(\"defaultparagraphseparator\") after":true,
-  "[[\"defaultparagraphseparator\",\"p\"],[\"inserthorizontalrule\",\"\"]] \"<p>foo[bar]baz</p>\": execCommand(\"defaultparagraphseparator\", false, \"p\") return value":true,
-  "[[\"defaultparagraphseparator\",\"p\"],[\"inserthorizontalrule\",\"\"]] \"<p>foo[bar]baz</p>\" queryCommandValue(\"defaultparagraphseparator\") before":true,
-  "[[\"defaultparagraphseparator\",\"p\"],[\"inserthorizontalrule\",\"\"]] \"<p>foo[bar]baz</p>\" queryCommandValue(\"defaultparagraphseparator\") after":true,
   "[[\"inserthorizontalrule\",\"\"]] \"<ruby>foo[bar]baz<rt>quz</rt></ruby>\" compare innerHTML":true,
   "[[\"inserthorizontalrule\",\"\"]] \"<ruby>foo<rt>bar[baz]quz</rt></ruby>\" compare innerHTML":true,
   "[[\"inserthorizontalrule\",\"\"]] \"<ruby>foo<rp>bar[baz]quz</rp><rt>qoz</rt><rp>qiz</rp></ruby>\" compare innerHTML":true,
   "[[\"inserthorizontalrule\",\"\"]] \"fo[o<span contenteditable=false>bar</span>b]az\" compare innerHTML":true,
   "[[\"stylewithcss\",\"true\"],[\"inserthtml\",\"ab<b>c</b>d\"]] \"[foo<span style=color:#aBcDeF>bar]</span>baz\" compare innerHTML":true,
   "[[\"stylewithcss\",\"false\"],[\"inserthtml\",\"ab<b>c</b>d\"]] \"[foo<span style=color:#aBcDeF>bar]</span>baz\" compare innerHTML":true,
   "[[\"stylewithcss\",\"true\"],[\"inserthtml\",\"ab<b>c</b>d\"]] \"{foo<span style=color:#aBcDeF>bar}</span>baz\" compare innerHTML":true,
   "[[\"stylewithcss\",\"false\"],[\"inserthtml\",\"ab<b>c</b>d\"]] \"{foo<span style=color:#aBcDeF>bar}</span>baz\" compare innerHTML":true,
@@ -6497,57 +6473,40 @@
   "[[\"inserttext\",\" \"]] \"#@x[]\" compare innerHTML":true,
   "[[\"inserttext\",\" \"]] \"a@.[]\" compare innerHTML":true,
   "[[\"inserttext\",\" \"]] \"!\\\"#$%&amp;'()*+,-./:;&lt;=>?^_`|~a@b!\\\"#$%&amp;'()*+,-./:;&lt;=>?^_`|~[]\" compare innerHTML":true,
   "[[\"inserttext\",\" \"]] \"<b>a@b</b>{}\" compare innerHTML":true,
   "[[\"inserttext\",\" \"]] \"<b>a</b><i>@</i><u>b</u>{}\" compare innerHTML":true,
   "[[\"inserttext\",\" \"]] \"a@b<b>[]c</b>\" compare innerHTML":true,
   "[[\"inserttext\",\"\\t\"]] \"http://a[]\" compare innerHTML":true,
   "[[\"inserttext\",\"\\f\"]] \"http://a[]\" compare innerHTML":true,
-  "[[\"inserttext\",\" \"]] \"http://a[]\" compare innerHTML":true,
+  "[[\"inserttext\",\"\u00a0\"]] \"http://a[]\" compare innerHTML":true,
   "[[\"inserttext\",\"   \"]] \"foo[]\" compare innerHTML":true,
   "[[\"defaultparagraphseparator\",\"div\"],[\"inserttext\",\"a\"]] \"<p>fo[o<p>b]ar\": execCommand(\"defaultparagraphseparator\", false, \"div\") return value":true,
   "[[\"defaultparagraphseparator\",\"div\"],[\"inserttext\",\"a\"]] \"<p>fo[o<p>b]ar\" queryCommandValue(\"defaultparagraphseparator\") before":true,
   "[[\"defaultparagraphseparator\",\"div\"],[\"inserttext\",\"a\"]] \"<p>fo[o<p>b]ar\" queryCommandValue(\"defaultparagraphseparator\") after":true,
   "[[\"defaultparagraphseparator\",\"p\"],[\"inserttext\",\"a\"]] \"<p>fo[o<p>b]ar\": execCommand(\"defaultparagraphseparator\", false, \"p\") return value":true,
   "[[\"defaultparagraphseparator\",\"p\"],[\"inserttext\",\"a\"]] \"<p>fo[o<p>b]ar\" queryCommandValue(\"defaultparagraphseparator\") before":true,
   "[[\"defaultparagraphseparator\",\"p\"],[\"inserttext\",\"a\"]] \"<p>fo[o<p>b]ar\" queryCommandValue(\"defaultparagraphseparator\") after":true,
   "[[\"defaultparagraphseparator\",\"div\"],[\"inserttext\",\"a\"]] \"<p>fo[o<p>bar<p>b]az\": execCommand(\"defaultparagraphseparator\", false, \"div\") return value":true,
   "[[\"defaultparagraphseparator\",\"div\"],[\"inserttext\",\"a\"]] \"<p>fo[o<p>bar<p>b]az\" queryCommandValue(\"defaultparagraphseparator\") before":true,
   "[[\"defaultparagraphseparator\",\"div\"],[\"inserttext\",\"a\"]] \"<p>fo[o<p>bar<p>b]az\" queryCommandValue(\"defaultparagraphseparator\") after":true,
   "[[\"defaultparagraphseparator\",\"p\"],[\"inserttext\",\"a\"]] \"<p>fo[o<p>bar<p>b]az\": execCommand(\"defaultparagraphseparator\", false, \"p\") return value":true,
   "[[\"defaultparagraphseparator\",\"p\"],[\"inserttext\",\"a\"]] \"<p>fo[o<p>bar<p>b]az\" queryCommandValue(\"defaultparagraphseparator\") before":true,
   "[[\"defaultparagraphseparator\",\"p\"],[\"inserttext\",\"a\"]] \"<p>fo[o<p>bar<p>b]az\" queryCommandValue(\"defaultparagraphseparator\") after":true,
   "[[\"inserttext\",\"a\"]] \"{}<br>\" compare innerHTML":true,
   "[[\"inserttext\",\"a\"]] \"<p>{}<br>\" compare innerHTML":true,
   "[[\"inserttext\",\"a\"]] \"<p><span>{}<br></span>\" compare innerHTML":true,
-  "[[\"inserttext\",\"a\"]] \"<p>foo<span style=color:#aBcDeF>[bar]</span>baz\" compare innerHTML":true,
-  "[[\"inserttext\",\"a\"]] \"<p>foo<span style=color:#aBcDeF>{bar}</span>baz\" compare innerHTML":true,
   "[[\"inserttext\",\"a\"]] \"<p>foo{<span style=color:#aBcDeF>bar</span>}baz\" compare innerHTML":true,
   "[[\"stylewithcss\",\"true\"],[\"inserttext\",\"a\"]] \"<p>[foo<span style=color:#aBcDeF>bar]</span>baz\" compare innerHTML":true,
   "[[\"stylewithcss\",\"false\"],[\"inserttext\",\"a\"]] \"<p>[foo<span style=color:#aBcDeF>bar]</span>baz\" compare innerHTML":true,
   "[[\"stylewithcss\",\"true\"],[\"inserttext\",\"a\"]] \"<p>{foo<span style=color:#aBcDeF>bar}</span>baz\" compare innerHTML":true,
   "[[\"stylewithcss\",\"false\"],[\"inserttext\",\"a\"]] \"<p>{foo<span style=color:#aBcDeF>bar}</span>baz\" compare innerHTML":true,
-  "[[\"inserttext\",\"a\"]] \"<p>foo<span style=color:#aBcDeF>[bar</span>baz]\" compare innerHTML":true,
-  "[[\"inserttext\",\"a\"]] \"<p>foo<span style=color:#aBcDeF>{bar</span>baz}\" compare innerHTML":true,
   "[[\"stylewithcss\",\"true\"],[\"inserttext\",\"a\"]] \"<p>foo<span style=color:#aBcDeF>[bar</span><span style=color:#fEdCbA>baz]</span>quz\" compare innerHTML":true,
   "[[\"stylewithcss\",\"false\"],[\"inserttext\",\"a\"]] \"<p>foo<span style=color:#aBcDeF>[bar</span><span style=color:#fEdCbA>baz]</span>quz\" compare innerHTML":true,
-  "[[\"inserttext\",\"a\"]] \"foo<s>[bar]</s>baz\" compare innerHTML":true,
-  "[[\"inserttext\",\"a\"]] \"foo<a href=http://www.google.com>[bar]</a>baz\" compare innerHTML":true,
-  "[[\"inserttext\",\"a\"]] \"foo<font color=#0000FF>[bar]</font>baz\" compare innerHTML":true,
-  "[[\"inserttext\",\"a\"]] \"foo<span style=background-color:#00FFFF>[bar]</span>baz\" compare innerHTML":true,
-  "[[\"inserttext\",\"a\"]] \"foo<a href=http://www.google.com><font color=blue>[bar]</font></a>baz\" compare innerHTML":true,
-  "[[\"inserttext\",\"a\"]] \"foo<font color=blue><a href=http://www.google.com>[bar]</a></font>baz\" compare innerHTML":true,
-  "[[\"inserttext\",\"a\"]] \"foo<a href=http://www.google.com><font color=brown>[bar]</font></a>baz\" compare innerHTML":true,
-  "[[\"inserttext\",\"a\"]] \"foo<font color=brown><a href=http://www.google.com>[bar]</a></font>baz\" compare innerHTML":true,
-  "[[\"inserttext\",\"a\"]] \"foo<a href=http://www.google.com><font color=black>[bar]</font></a>baz\" compare innerHTML":true,
-  "[[\"inserttext\",\"a\"]] \"foo<a href=http://www.google.com><u>[bar]</u></a>baz\" compare innerHTML":true,
-  "[[\"inserttext\",\"a\"]] \"foo<u><a href=http://www.google.com>[bar]</a></u>baz\" compare innerHTML":true,
-  "[[\"inserttext\",\"a\"]] \"foo<font size=2><sub>[bar]</sub></font>baz\" compare innerHTML":true,
-  "[[\"inserttext\",\"a\"]] \"foo<font size=3><sub>[bar]</sub></font>baz\" compare innerHTML":true,
   "[[\"stylewithcss\",\"true\"],[\"inserttext\",\"a\"]] \"[foo<b>bar]</b>baz\" compare innerHTML":true,
   "[[\"stylewithcss\",\"false\"],[\"inserttext\",\"a\"]] \"[foo<b>bar]</b>baz\" compare innerHTML":true,
   "[[\"stylewithcss\",\"true\"],[\"inserttext\",\"a\"]] \"[foo<i>bar]</i>baz\" compare innerHTML":true,
   "[[\"stylewithcss\",\"false\"],[\"inserttext\",\"a\"]] \"[foo<i>bar]</i>baz\" compare innerHTML":true,
   "[[\"stylewithcss\",\"true\"],[\"inserttext\",\"a\"]] \"[foo<s>bar]</s>baz\" compare innerHTML":true,
   "[[\"stylewithcss\",\"false\"],[\"inserttext\",\"a\"]] \"[foo<s>bar]</s>baz\" compare innerHTML":true,
   "[[\"stylewithcss\",\"true\"],[\"inserttext\",\"a\"]] \"[foo<sub>bar]</sub>baz\" compare innerHTML":true,
   "[[\"stylewithcss\",\"false\"],[\"inserttext\",\"a\"]] \"[foo<sub>bar]</sub>baz\" compare innerHTML":true,
@@ -6581,38 +6540,16 @@
   "[[\"stylewithcss\",\"true\"],[\"inserttext\",\"a\"]] \"[foo<sub><font size=2>bar]</font></sub>baz\" compare innerHTML":true,
   "[[\"stylewithcss\",\"false\"],[\"inserttext\",\"a\"]] \"[foo<sub><font size=2>bar]</font></sub>baz\" compare innerHTML":true,
   "[[\"stylewithcss\",\"true\"],[\"inserttext\",\"a\"]] \"[foo<font size=2><sub>bar]</sub></font>baz\" compare innerHTML":true,
   "[[\"stylewithcss\",\"false\"],[\"inserttext\",\"a\"]] \"[foo<font size=2><sub>bar]</sub></font>baz\" compare innerHTML":true,
   "[[\"stylewithcss\",\"true\"],[\"inserttext\",\"a\"]] \"[foo<sub><font size=3>bar]</font></sub>baz\" compare innerHTML":true,
   "[[\"stylewithcss\",\"false\"],[\"inserttext\",\"a\"]] \"[foo<sub><font size=3>bar]</font></sub>baz\" compare innerHTML":true,
   "[[\"stylewithcss\",\"true\"],[\"inserttext\",\"a\"]] \"[foo<font size=3><sub>bar]</sub></font>baz\" compare innerHTML":true,
   "[[\"stylewithcss\",\"false\"],[\"inserttext\",\"a\"]] \"[foo<font size=3><sub>bar]</sub></font>baz\" compare innerHTML":true,
-  "[[\"inserttext\",\"a\"]] \"foo<b>[bar</b>baz]\" compare innerHTML":true,
-  "[[\"inserttext\",\"a\"]] \"foo<i>[bar</i>baz]\" compare innerHTML":true,
-  "[[\"inserttext\",\"a\"]] \"foo<s>[bar</s>baz]\" compare innerHTML":true,
-  "[[\"inserttext\",\"a\"]] \"foo<sub>[bar</sub>baz]\" compare innerHTML":true,
-  "[[\"inserttext\",\"a\"]] \"foo<sup>[bar</sup>baz]\" compare innerHTML":true,
-  "[[\"inserttext\",\"a\"]] \"foo<u>[bar</u>baz]\" compare innerHTML":true,
-  "[[\"inserttext\",\"a\"]] \"foo<a href=http://www.google.com>[bar</a>baz]\" compare innerHTML":true,
-  "[[\"inserttext\",\"a\"]] \"foo<font face=sans-serif>[bar</font>baz]\" compare innerHTML":true,
-  "[[\"inserttext\",\"a\"]] \"foo<font size=4>[bar</font>baz]\" compare innerHTML":true,
-  "[[\"inserttext\",\"a\"]] \"foo<font color=#0000FF>[bar</font>baz]\" compare innerHTML":true,
-  "[[\"inserttext\",\"a\"]] \"foo<span style=background-color:#00FFFF>[bar</span>baz]\" compare innerHTML":true,
-  "[[\"inserttext\",\"a\"]] \"foo<a href=http://www.google.com><font color=blue>[bar</font></a>baz]\" compare innerHTML":true,
-  "[[\"inserttext\",\"a\"]] \"foo<font color=blue><a href=http://www.google.com>[bar</a></font>baz]\" compare innerHTML":true,
-  "[[\"inserttext\",\"a\"]] \"foo<a href=http://www.google.com><font color=brown>[bar</font></a>baz]\" compare innerHTML":true,
-  "[[\"inserttext\",\"a\"]] \"foo<font color=brown><a href=http://www.google.com>[bar</a></font>baz]\" compare innerHTML":true,
-  "[[\"inserttext\",\"a\"]] \"foo<a href=http://www.google.com><font color=black>[bar</font></a>baz]\" compare innerHTML":true,
-  "[[\"inserttext\",\"a\"]] \"foo<a href=http://www.google.com><u>[bar</u></a>baz]\" compare innerHTML":true,
-  "[[\"inserttext\",\"a\"]] \"foo<u><a href=http://www.google.com>[bar</a></u>baz]\" compare innerHTML":true,
-  "[[\"inserttext\",\"a\"]] \"foo<sub><font size=2>[bar</font></sub>baz]\" compare innerHTML":true,
-  "[[\"inserttext\",\"a\"]] \"foo<font size=2><sub>[bar</sub></font>baz]\" compare innerHTML":true,
-  "[[\"inserttext\",\"a\"]] \"foo<sub><font size=3>[bar</font></sub>baz]\" compare innerHTML":true,
-  "[[\"inserttext\",\"a\"]] \"foo<font size=3><sub>[bar</sub></font>baz]\" compare innerHTML":true,
   "[[\"insertunorderedlist\",\"\"]] \"foo<br>[bar]\" compare innerHTML":true,
   "[[\"insertunorderedlist\",\"\"]] \"[foo<ol><li>bar]</ol>baz\" queryCommandIndeterm(\"insertunorderedlist\") before":true,
   "[[\"insertunorderedlist\",\"\"]] \"foo<ol><li>[bar</ol>baz]\" queryCommandIndeterm(\"insertunorderedlist\") before":true,
   "[[\"defaultparagraphseparator\",\"div\"],[\"insertunorderedlist\",\"\"]] \"<p>foo<p>[bar]<p>baz\": execCommand(\"defaultparagraphseparator\", false, \"div\") return value":true,
   "[[\"defaultparagraphseparator\",\"div\"],[\"insertunorderedlist\",\"\"]] \"<p>foo<p>[bar]<p>baz\" queryCommandValue(\"defaultparagraphseparator\") before":true,
   "[[\"defaultparagraphseparator\",\"div\"],[\"insertunorderedlist\",\"\"]] \"<p>foo<p>[bar]<p>baz\" queryCommandValue(\"defaultparagraphseparator\") after":true,
   "[[\"defaultparagraphseparator\",\"p\"],[\"insertunorderedlist\",\"\"]] \"<p>foo<p>[bar]<p>baz\": execCommand(\"defaultparagraphseparator\", false, \"p\") return value":true,
   "[[\"defaultparagraphseparator\",\"p\"],[\"insertunorderedlist\",\"\"]] \"<p>foo<p>[bar]<p>baz\" queryCommandValue(\"defaultparagraphseparator\") before":true,
@@ -11213,20 +11150,16 @@
   "[[\"stylewithcss\",\"false\"],[\"strikethrough\",\"\"]] \"foo<u style=\\\"text-decoration: line-through\\\">[bar]</u>baz\" compare innerHTML":true,
   "[[\"stylewithcss\",\"true\"],[\"strikethrough\",\"\"]] \"foo<u style=\\\"text-decoration: line-through\\\">b[a]r</u>baz\" compare innerHTML":true,
   "[[\"stylewithcss\",\"false\"],[\"strikethrough\",\"\"]] \"foo<u style=\\\"text-decoration: line-through\\\">b[a]r</u>baz\" compare innerHTML":true,
   "[[\"stylewithcss\",\"false\"],[\"strikethrough\",\"\"]] \"foo<u style=\\\"text-decoration: line-through\\\">b[a]r</u>baz\" queryCommandState(\"strikethrough\") after":true,
   "[[\"stylewithcss\",\"false\"],[\"strikethrough\",\"\"]] \"foo<s style=\\\"text-decoration: overline\\\">[bar]</s>baz\" compare innerHTML":true,
   "[[\"stylewithcss\",\"false\"],[\"strikethrough\",\"\"]] \"foo<s style=\\\"text-decoration: overline\\\">b[a]r</s>baz\" compare innerHTML":true,
   "[[\"stylewithcss\",\"false\"],[\"strikethrough\",\"\"]] \"foo<u style=\\\"text-decoration: overline\\\">[bar]</u>baz\" compare innerHTML":true,
   "[[\"stylewithcss\",\"false\"],[\"strikethrough\",\"\"]] \"foo<u style=\\\"text-decoration: overline\\\">b[a]r</u>baz\" compare innerHTML":true,
-  "[[\"stylewithcss\",\"true\"],[\"strikethrough\",\"\"]] \"<p style=\\\"text-decoration: line-through\\\">foo[bar]baz</p>\" compare innerHTML":true,
-  "[[\"stylewithcss\",\"true\"],[\"strikethrough\",\"\"]] \"<p style=\\\"text-decoration: line-through\\\">foo[bar]baz</p>\" queryCommandState(\"strikethrough\") after":true,
-  "[[\"stylewithcss\",\"false\"],[\"strikethrough\",\"\"]] \"<p style=\\\"text-decoration: line-through\\\">foo[bar]baz</p>\" compare innerHTML":true,
-  "[[\"stylewithcss\",\"false\"],[\"strikethrough\",\"\"]] \"<p style=\\\"text-decoration: line-through\\\">foo[bar]baz</p>\" queryCommandState(\"strikethrough\") after":true,
   "[[\"stylewithcss\",\"false\"],[\"strikethrough\",\"\"]] \"<p style=\\\"text-decoration: overline\\\">foo[bar]baz</p>\" compare innerHTML":true,
   "[[\"stylewithcss\",\"false\"],[\"strikethrough\",\"\"]] \"foo<span class=\\\"underline\\\">[bar]</span>baz\" compare innerHTML":true,
   "[[\"stylewithcss\",\"false\"],[\"strikethrough\",\"\"]] \"foo<span class=\\\"underline\\\">b[a]r</span>baz\" compare innerHTML":true,
   "[[\"stylewithcss\",\"true\"],[\"strikethrough\",\"\"]] \"fo[o<s>bar</s>b]az\" compare innerHTML":true,
   "[[\"stylewithcss\",\"true\"],[\"strikethrough\",\"\"]] \"foo[<s>b]ar</s>baz\" compare innerHTML":true,
   "[[\"stylewithcss\",\"true\"],[\"strikethrough\",\"\"]] \"foo<s>ba[r</s>]baz\" compare innerHTML":true,
   "[[\"stylewithcss\",\"true\"],[\"strikethrough\",\"\"]] \"<strike>fo[o</strike><s>b]ar</s>\" compare innerHTML":true,
   "[[\"stylewithcss\",\"false\"],[\"strikethrough\",\"\"]] \"<strike>fo[o</strike><s>b]ar</s>\" compare innerHTML":true,
--- a/dom/interfaces/events/nsIWifiEventInits.idl
+++ b/dom/interfaces/events/nsIWifiEventInits.idl
@@ -15,9 +15,10 @@ dictionary MozWifiStatusChangeEventInit 
 };
 
 dictionary MozWifiConnectionInfoEventInit : EventInit
 {
   nsIVariant network;
   short signalStrength;
   short relSignalStrength;
   long linkSpeed;
+  DOMString ipAddress;
 };
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -1555,16 +1555,25 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_
   NS_INTERFACE_MAP_ENTRY(nsIScriptContextPrincipal)
   NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(ContentFrameMessageManager)
 NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
 
 NS_IMPL_ADDREF_INHERITED(TabChildGlobal, nsDOMEventTargetHelper)
 NS_IMPL_RELEASE_INHERITED(TabChildGlobal, nsDOMEventTargetHelper)
 
+/* [notxpcom] boolean markForCC (); */
+// This method isn't automatically forwarded safely because it's notxpcom, so
+// the IDL binding doesn't know what value to return.
+NS_IMETHODIMP_(bool)
+TabChildGlobal::MarkForCC()
+{
+  return mMessageManager ? mMessageManager->MarkForCC() : false;
+}
+
 NS_IMETHODIMP
 TabChildGlobal::GetContent(nsIDOMWindow** aContent)
 {
   *aContent = nullptr;
   if (!mTabChild)
     return NS_ERROR_NULL_POINTER;
   nsCOMPtr<nsIDOMWindow> window = do_GetInterface(mTabChild->WebNavigation());
   window.swap(*aContent);
--- a/dom/plugins/base/nsPluginHost.cpp
+++ b/dom/plugins/base/nsPluginHost.cpp
@@ -26,17 +26,17 @@
 #include "nsIUploadChannel.h"
 #include "nsIByteRangeRequest.h"
 #include "nsIStreamListener.h"
 #include "nsIInputStream.h"
 #include "nsIOutputStream.h"
 #include "nsIURL.h"
 #include "nsXPIDLString.h"
 #include "nsReadableUtils.h"
-#include "nsIProtocolProxyService.h"
+#include "nsIProtocolProxyService2.h"
 #include "nsIStreamConverterService.h"
 #include "nsIFile.h"
 #if defined(XP_MACOSX)
 #include "nsILocalFileMac.h"
 #endif
 #include "nsIInputStream.h"
 #include "nsIIOService.h"
 #include "nsIURL.h"
@@ -738,34 +738,40 @@ nsresult nsPluginHost::FindProxyForURL(c
 {
   if (!url || !result) {
     return NS_ERROR_INVALID_ARG;
   }
   nsresult res;
 
   nsCOMPtr<nsIURI> uriIn;
   nsCOMPtr<nsIProtocolProxyService> proxyService;
+  nsCOMPtr<nsIProtocolProxyService2> proxyService2;
   nsCOMPtr<nsIIOService> ioService;
 
   proxyService = do_GetService(NS_PROTOCOLPROXYSERVICE_CONTRACTID, &res);
   if (NS_FAILED(res) || !proxyService)
     return res;
 
+  proxyService2 = do_QueryInterface(proxyService, &res);
+  if (NS_FAILED(res) || !proxyService)
+    return res;
+
   ioService = do_GetService(NS_IOSERVICE_CONTRACTID, &res);
   if (NS_FAILED(res) || !ioService)
     return res;
 
   // make an nsURI from the argument url
   res = ioService->NewURI(nsDependentCString(url), nullptr, nullptr, getter_AddRefs(uriIn));
   if (NS_FAILED(res))
     return res;
 
   nsCOMPtr<nsIProxyInfo> pi;
 
-  res = proxyService->Resolve(uriIn, 0, getter_AddRefs(pi));
+  // Remove this with bug 778201
+  res = proxyService2->DeprecatedBlockingResolve(uriIn, 0, getter_AddRefs(pi));
   if (NS_FAILED(res))
     return res;
 
   nsAutoCString host, type;
   int32_t port = -1;
 
   // These won't fail, and even if they do... we'll be ok.
   if (pi) {
--- a/dom/wifi/DOMWifiManager.js
+++ b/dom/wifi/DOMWifiManager.js
@@ -70,16 +70,17 @@ DOMWifiManager.prototype = {
 
     // Maintain this state for synchronous APIs.
     this._currentNetwork = null;
     this._connectionStatus = "disconnected";
     this._enabled = false;
     this._lastConnectionInfo = null;
 
     const messages = ["WifiManager:getNetworks:Return:OK", "WifiManager:getNetworks:Return:NO",
+                      "WifiManager:getKnownNetworks:Return:OK", "WifiManager:getKnownNetworks:Return:NO",
                       "WifiManager:associate:Return:OK", "WifiManager:associate:Return:NO",
                       "WifiManager:forget:Return:OK", "WifiManager:forget:Return:NO",
                       "WifiManager:wps:Return:OK", "WifiManager:wps:Return:NO",
                       "WifiManager:setPowerSavingMode:Return:OK", "WifiManager:setPowerSavingMode:Return:NO",
                       "WifiManager:wifiDown", "WifiManager:wifiUp",
                       "WifiManager:onconnecting", "WifiManager:onassociate",
                       "WifiManager:onconnect", "WifiManager:ondisconnect",
                       "WifiManager:onwpstimeout", "WifiManager:onwpsfail",
@@ -91,21 +92,23 @@ DOMWifiManager.prototype = {
     var state = this._mm.sendSyncMessage("WifiManager:getState")[0];
     if (state) {
       this._currentNetwork = state.network;
       if (this._currentNetwork)
         exposeCurrentNetwork(this._currentNetwork);
       this._lastConnectionInfo = state.connectionInfo;
       this._enabled = state.enabled;
       this._connectionStatus = state.status;
+      this._macAddress = state.macAddress;
     } else {
       this._currentNetwork = null;
       this._lastConnectionInfo = null;
       this._enabled = false;
       this._connectionStatus = "disconnected";
+      this._macAddress = "";
     }
   },
 
   uninit: function() {
     this._onStatusChange = null;
     this._onConnectionInfoUpdate = null;
     this._onEnabled = null;
     this._onDisabled = null;
@@ -130,16 +133,26 @@ DOMWifiManager.prototype = {
         Services.DOMRequest.fireSuccess(request, exposeReadOnly(msg.data));
         break;
 
       case "WifiManager:getNetworks:Return:NO":
         request = this.takeRequest(msg.rid);
         Services.DOMRequest.fireError(request, "Unable to scan for networks");
         break;
 
+      case "WifiManager:getKnownNetworks:Return:OK":
+        request = this.takeRequest(msg.rid);
+        Services.DOMRequest.fireSuccess(request, exposeReadOnly(msg.data));
+        break;
+
+      case "WifiManager:getKnownNetworks:Return:NO":
+        request = this.takeRequest(msg.rid);
+        Services.DOMRequest.fireError(request, "Unable to get known networks");
+        break;
+
       case "WifiManager:associate:Return:OK":
         request = this.takeRequest(msg.rid);
         Services.DOMRequest.fireSuccess(request, true);
         break;
 
       case "WifiManager:associate:Return:NO":
         request = this.takeRequest(msg.rid);
         Services.DOMRequest.fireError(request, "Unable to add the network");
@@ -261,17 +274,18 @@ DOMWifiManager.prototype = {
 
   _fireConnectionInfoUpdate: function connectionInfoUpdate(info) {
     if (this._onConnectionInfoUpdate) {
       debug("ConnectionInfoEvent");
       var evt = new this._window.MozWifiConnectionInfoEvent("connectionInfoEvent",
                                                             { network: this._currentNetwork,
                                                               signalStrength: info.signalStrength,
                                                               relSignalStrength: info.relSignalStrength,
-                                                              linkSpeed: info.linkSpeed
+                                                              linkSpeed: info.linkSpeed,
+                                                              ipAddress: info.ipAddress,
                                                             });
       this._onConnectionInfoUpdate.handleEvent(evt);
     }
   },
 
   _fireEnabledOrDisabled: function enabledDisabled(enabled) {
     var handler = enabled ? this._onEnabled : this._onDisabled;
     if (handler) {
@@ -284,16 +298,24 @@ DOMWifiManager.prototype = {
   getNetworks: function nsIDOMWifiManager_getNetworks() {
     if (!this._hasPrivileges)
       throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
     var request = this.createRequest();
     this._sendMessageForRequest("WifiManager:getNetworks", null, request);
     return request;
   },
 
+  getKnownNetworks: function nsIDOMWifiManager_getKnownNetworks() {
+    if (!this._hasPrivileges)
+      throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
+    var request = this.createRequest();
+    this._sendMessageForRequest("WifiManager:getKnownNetworks", null, request);
+    return request;
+  },
+
   associate: function nsIDOMWifiManager_associate(network) {
     if (!this._hasPrivileges)
       throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
     var request = this.createRequest();
     this._sendMessageForRequest("WifiManager:associate", network, request);
     return request;
   },
 
@@ -322,16 +344,22 @@ DOMWifiManager.prototype = {
   },
 
   get enabled() {
     if (!this._hasPrivileges)
       throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
     return this._enabled;
   },
 
+  get macAddress() {
+    if (!this._hasPrivileges)
+      throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
+    return this._macAddress;
+  },
+
   get connection() {
     if (!this._hasPrivileges)
       throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
     return exposeReadOnly({ status: this._connectionStatus,
                             network: this._currentNetwork });
   },
 
   get connectionInformation() {
--- a/dom/wifi/WifiWorker.js
+++ b/dom/wifi/WifiWorker.js
@@ -1274,42 +1274,62 @@ function calculateSignal(strength) {
 
   if (strength <= MIN_RSSI)
     return 0;
   if (strength >= MAX_RSSI)
     return 100;
   return Math.floor(((strength - MIN_RSSI) / (MAX_RSSI - MIN_RSSI)) * 100);
 }
 
-function ScanResult(ssid, bssid, flags, signal) {
+function Network(ssid, capabilities, password) {
   this.ssid = ssid;
+  this.capabilities = capabilities;
+
+  if (typeof password !== "undefined")
+    this.password = password;
+  // TODO connected here as well?
+
+  this.__exposedProps__ = Network.api;
+}
+
+Network.api = {
+  ssid: "r",
+  capabilities: "r",
+  known: "r",
+
+  password: "rw",
+  keyManagement: "rw",
+  psk: "rw",
+  identity: "rw",
+  wep: "rw"
+};
+
+// Note: We never use ScanResult.prototype, so the fact that it's unrelated to
+// Network.prototype is OK.
+function ScanResult(ssid, bssid, flags, signal) {
+  Network.call(this, ssid, getKeyManagement(flags));
   this.bssid = bssid;
-  this.capabilities = getKeyManagement(flags);
   this.signalStrength = signal;
   this.relSignalStrength = calculateSignal(Number(signal));
 
   this.__exposedProps__ = ScanResult.api;
 }
 
 // XXX This should probably live in the DOM-facing side, but it's hard to do
 // there, so we stick this here.
 ScanResult.api = {
-  ssid: "r",
   bssid: "r",
-  capabilities: "r",
   signalStrength: "r",
   relSignalStrength: "r",
-  connected: "r",
+  connected: "r"
+};
 
-  keyManagement: "rw",
-  psk: "rw",
-  identity: "rw",
-  password: "rw",
-  wep: "rw"
-};
+for (let i in Network.api) {
+  ScanResult.api[i] = Network.api[i];
+}
 
 function quote(s) {
   return '"' + s + '"';
 }
 
 function dequote(s) {
   if (s[0] != '"' || s[s.length - 1] != '"')
     throw "Invalid argument, not a quoted string: " + s;
@@ -1374,17 +1394,17 @@ let WifiNetworkInterface = {
 let netToDOM;
 let netFromDOM;
 
 function WifiWorker() {
   var self = this;
 
   this._mm = Cc["@mozilla.org/parentprocessmessagemanager;1"]
                .getService(Ci.nsIMessageListenerManager);
-  const messages = ["WifiManager:getNetworks",
+  const messages = ["WifiManager:getNetworks", "WifiManager:getKnownNetworks",
                     "WifiManager:associate", "WifiManager:forget",
                     "WifiManager:wps", "WifiManager:getState",
                     "WifiManager:setPowerSavingMode",
                     "WifiManager:managerFinished"];
 
   messages.forEach((function(msgName) {
     this._mm.addMessageListener(msgName, this);
   }).bind(this));
@@ -1403,28 +1423,44 @@ function WifiWorker() {
   // lists networks known to the wpa_supplicant. The SSID field (and other
   // fields) are quoted for ease of use with WifiManager commands.
   // Note that we don't have to worry about escaping embedded quotes since in
   // all cases, the supplicant will take the last quotation that we pass it as
   // the end of the string.
   this.configuredNetworks = Object.create(null);
 
   this.currentNetwork = null;
+  this.ipAddress = "";
 
   this._lastConnectionInfo = null;
   this._connectionInfoTimer = null;
   this._reconnectOnDisconnect = false;
 
   // A list of requests to turn wifi on or off.
   this._stateRequests = [];
 
   // Given a connection status network, takes a network from
   // self.configuredNetworks and prepares it for the DOM.
   netToDOM = function(net) {
-    var pub = { ssid: dequote(net.ssid) };
+    var ssid = dequote(net.ssid);
+    var capabilities = (net.key_mgmt === "NONE" && net.wep_key0)
+                       ? ["WEP"]
+                       : (net.key_mgmt && net.key_mgmt !== "NONE")
+                       ? [net.key_mgmt]
+                       : [];
+    var password;
+    if (("psk" in net && net.psk) ||
+        ("password" in net && net.password) ||
+        ("wep_key0" in net && net.wep_key0)) {
+      password = "*";
+    }
+
+    var pub = new Network(ssid, capabilities, password);
+    if (net.identity)
+      pub.identity = dequote(net.identity);
     if (net.netId)
       pub.known = true;
     return pub;
   };
 
   netFromDOM = function(net, configured) {
     // Takes a network from the DOM and makes it suitable for insertion into
     // self.configuredNetworks (that is calling addNetwork will do the right
@@ -1481,16 +1517,17 @@ function WifiWorker() {
     return net;
   };
 
   WifiManager.onsupplicantconnection = function() {
     debug("Connected to supplicant");
     WifiManager.enabled = true;
     self._updateWifiSetting(true);
     WifiManager.getMacAddress(function (mac) {
+      self.macAddress = mac;
       debug("Got mac: " + mac);
     });
 
     self._reloadConfiguredNetworks(function(ok) {
       // Prime this.networks.
       if (!ok)
         return;
       self.waitForScan(function firstScan() {});
@@ -1602,16 +1639,17 @@ function WifiWorker() {
         self._startConnectionInfoTimer();
         self._fireEvent("onassociate", { network: netToDOM(self.currentNetwork) });
         break;
       case "CONNECTED":
         break;
       case "DISCONNECTED":
         self._fireEvent("ondisconnect", {});
         self.currentNetwork = null;
+        self.ipAddress = "";
 
         WifiManager.connectionDropped(function() {
           // We've disconnected from a network because of a call to forgetNetwork.
           // Reconnect to the next available network (if any).
           if (self._reconnectOnDisconnect) {
             self._reconnectOnDisconnect = false;
             WifiManager.reconnect(function(){});
           }
@@ -1651,16 +1689,23 @@ function WifiWorker() {
       WifiNetworkInterface.broadcast = this.info.broadcast_str;
       WifiNetworkInterface.gateway = this.info.gateway_str;
       WifiNetworkInterface.dns1 = this.info.dns1_str;
       WifiNetworkInterface.dns2 = this.info.dns2_str;
       Services.obs.notifyObservers(WifiNetworkInterface,
                                    kNetworkInterfaceStateChangedTopic,
                                    null);
 
+      self.ipAddress = this.info.ipaddr_str;
+
+      // We start the connection information timer when we associate, but
+      // don't have our IP address until here. Make sure that we fire a new
+      // connectionInformation event with the IP address the next time the
+      // timer fires.
+      self._lastConnectionInfo = null;
       self._fireEvent("onconnect", { network: netToDOM(self.currentNetwork) });
     } else {
       WifiManager.reassociate(function(){});
     }
   };
 
   WifiManager.onscanresultsavailable = function() {
     if (self.wantScanResults.length === 0) {
@@ -1819,17 +1864,18 @@ WifiWorker.prototype = {
           rssi -= 256;
         if (rssi <= MIN_RSSI)
           rssi = MIN_RSSI;
         else if (rssi >= MAX_RSSI)
           rssi = MAX_RSSI;
 
         let info = { signalStrength: rssi,
                      relSignalStrength: calculateSignal(rssi),
-                     linkSpeed: linkspeed };
+                     linkSpeed: linkspeed,
+                     ipAddress: self.ipAddress };
         let last = self._lastConnectionInfo;
 
         // Only fire the event if the link speed changed or the signal
         // strength changed by more than 10%.
         function tensPlace(percent) ((percent / 10) | 0)
 
         if (last && last.linkSpeed === info.linkSpeed &&
             tensPlace(last.relSignalStrength) === tensPlace(info.relSignalStrength)) {
@@ -1981,16 +2027,19 @@ WifiWorker.prototype = {
   receiveMessage: function MessageManager_receiveMessage(aMessage) {
     let msg = aMessage.json || {};
     msg.manager = aMessage.target;
 
     switch (aMessage.name) {
       case "WifiManager:getNetworks":
         this.getNetworks(msg);
         break;
+      case "WifiManager:getKnownNetworks":
+        this.getKnownNetworks(msg);
+        break;
       case "WifiManager:associate":
         this.associate(msg);
         break;
       case "WifiManager:forget":
         this.forget(msg);
         break;
       case "WifiManager:wps":
         this.wps(msg);
@@ -2011,17 +2060,18 @@ WifiWorker.prototype = {
 
         if (i === this._domManagers.length) {
           this._domManagers.push({ manager: msg.manager, count: 1 });
         }
 
         return { network: net,
                  connectionInfo: this._lastConnectionInfo,
                  enabled: WifiManager.enabled,
-                 status: translateState(WifiManager.state) };
+                 status: translateState(WifiManager.state),
+                 macAddress: this.macAddress };
       }
       case "WifiManager:managerFinished": {
         for (let i = 0; i < this._domManagers.length; ++i) {
           let obj = this._domManagers[i];
           if (obj.manager === msg.manager) {
             if (--obj.count === 0) {
               this._domManagers.splice(i, 1);
             }
@@ -2055,16 +2105,38 @@ WifiWorker.prototype = {
       this.wantScanResults.splice(this.wantScanResults.indexOf(callback), 1);
 
       // Otherwise, let the client know that it failed, it's responsible for
       // trying again in a few seconds.
       this._sendMessage(message, false, "ScanFailed", msg);
     }).bind(this));
   },
 
+  getKnownNetworks: function(msg) {
+    const message = "WifiManager:getKnownNetworks:Return";
+    if (!WifiManager.enabled) {
+      this._sendMessage(message, false, "Wifi is disabled", msg);
+      return;
+    }
+
+    this._reloadConfiguredNetworks((function(ok) {
+      if (!ok) {
+        this._sendMessage(message, false, "Failed", msg);
+        return;
+      }
+
+      var networks = {};
+      for (let ssid in this.configuredNetworks) {
+        networks[ssid] = netToDOM(this.configuredNetworks[ssid]);
+      }
+
+      this._sendMessage(message, true, networks, msg);
+    }).bind(this));
+  },
+
   _notifyAfterStateChange: function(success, newState) {
     if (!this._stateRequests.length)
       return;
 
     // First, notify all of the requests that were trying to make this change.
     let state = this._stateRequests[0].enabled;
 
     // It is callback function's responsibility to handle the pending request.
--- a/dom/wifi/nsIWifi.idl
+++ b/dom/wifi/nsIWifi.idl
@@ -12,30 +12,38 @@ interface nsIVariant;
 interface nsIWifi : nsISupports
 {
     /**
      * Shutdown the wifi system.
      */
     void shutdown();
 };
 
-[scriptable, uuid(e3a967e0-015e-11e2-a21f-0800200c9a66)]
+[scriptable, uuid(caa76ee3-8ffe-4ea5-bc59-3b53a9df0d07)]
 interface nsIDOMWifiManager : nsISupports
 {
     /**
-     * Returns the list of currently available networks as well as the list of
-     * currently configured networks.
+     * Returns the list of currently available networks.
      * onsuccess: We have obtained the current list of networks. request.value
      *            is an object whose property names are SSIDs and values are
      *            network objects.
      * onerror: We were unable to obtain a list of property names.
      */
     nsIDOMDOMRequest getNetworks();
 
     /**
+     * Returns the list of networks known to the system that will be
+     * automatically connected to if they're in range.
+     * onsuccess: request.value is an object whose property names are
+     *            SSIDs and values are network objects.
+     * onerror: We were unable to obtain a list of known networks.
+     */
+    nsIDOMDOMRequest getKnownNetworks();
+
+    /**
      * Takes one of the networks returned from getNetworks and tries to
      * connect to it.
      * @param network A network object with information about the network,
      *                such as the SSID, key management desired, etc.
      * onsuccess: We have started attempting to associate with the network.
      *            request.value is true.
      * onerror: We were unable to select the network. This most likely means a
      *          configuration error.
@@ -77,16 +85,21 @@ interface nsIDOMWifiManager : nsISupport
     nsIDOMDOMRequest setPowerSavingMode(in boolean enabled);
 
     /**
      * Returns whether or not wifi is currently enabled.
      */
     readonly attribute boolean enabled;
 
     /**
+     * Returns the MAC address of the wifi adapter.
+     */
+    readonly attribute DOMString macAddress;
+
+    /**
      * An non-null object containing the following information:
      *  - status ("disconnected", "connecting", "associated", "connected")
      *  - network
      *
      *  Note that the object returned is read only. Any changes required must
      *  be done by calling other APIs.
      */
     readonly attribute jsval connection;
@@ -149,17 +162,17 @@ interface nsIDOMMozWifiStatusChangeEvent
 
     [noscript] void initMozWifiStatusChangeEvent(in DOMString aType,
                                                  in boolean aCanBubble,
                                                  in boolean aCancelable,
                                                  in nsIVariant aNetwork,
                                                  in DOMString status);
 };
 
-[scriptable, builtinclass, uuid(34994296-d694-4aed-953d-fc25ee25c050)]
+[scriptable, builtinclass, uuid(1717f9d9-5fd8-43d8-a098-55924c6d37de)]
 interface nsIDOMMozWifiConnectionInfoEvent : nsIDOMEvent
 {
     /**
      * Network object with an SSID field.
      */
     readonly attribute nsIVariant network;
 
     /**
@@ -172,16 +185,22 @@ interface nsIDOMMozWifiConnectionInfoEve
      */
     readonly attribute short relSignalStrength;
 
     /**
      * Link speed in Mb/s.
      */
     readonly attribute long linkSpeed;
 
+    /**
+     * IP address in the dotted quad format.
+     */
+    readonly attribute DOMString ipAddress;
+
     [noscript] void initMozWifiConnectionInfoEvent(in DOMString aType,
                                                    in boolean aCanBubble,
                                                    in boolean aCancelable,
                                                    in nsIVariant aNetwork,
                                                    in short signalStrength,
                                                    in short relSignalStrength,
-                                                   in long linkSpeed);
+                                                   in long linkSpeed,
+                                                   in DOMString ipAddress);
 };
--- a/editor/libeditor/html/nsHTMLEditRules.cpp
+++ b/editor/libeditor/html/nsHTMLEditRules.cpp
@@ -1266,19 +1266,20 @@ nsHTMLEditRules::WillInsertText(EditActi
   
   // initialize out param
   *aCancel = false;
   *aHandled = true;
   nsresult res;
   nsCOMPtr<nsIDOMNode> selNode;
   int32_t selOffset;
 
-  // if the selection isn't collapsed, delete it.
+  // If the selection isn't collapsed, delete it.  Don't delete existing inline
+  // tags, because we're hopefully going to insert text (bug 787432).
   if (!aSelection->Collapsed()) {
-    res = mHTMLEditor->DeleteSelection(nsIEditor::eNone, nsIEditor::eStrip);
+    res = mHTMLEditor->DeleteSelection(nsIEditor::eNone, nsIEditor::eNoStrip);
     NS_ENSURE_SUCCESS(res, res);
   }
 
   res = WillInsert(aSelection, aCancel);
   NS_ENSURE_SUCCESS(res, res);
   // initialize out param
   // we want to ignore result of WillInsert()
   *aCancel = false;
--- a/editor/libeditor/html/tests/Makefile.in
+++ b/editor/libeditor/html/tests/Makefile.in
@@ -75,16 +75,17 @@ MOCHITEST_FILES = \
 		test_keypress_untrusted_event.html \
 		test_select_all_without_body.html \
 		file_select_all_without_body.html \
 		test_root_element_replacement.html \
 		test_bug738366.html \
 		test_bug757371.html \
 		test_bug767684.html \
 		test_bug780035.html \
+		test_bug787432.html \
 		$(NULL)
 
 ifneq (mobile,$(MOZ_BUILD_APP))
 MOCHITEST_FILES +=  test_spellcheck_pref.html \
 		$(NULL)
 endif
 
 _DATA_FILES = \
new file mode 100644
--- /dev/null
+++ b/editor/libeditor/html/tests/test_bug787432.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=787432
+-->
+<title>Test for Bug 787432</title>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" href="/tests/SimpleTest/test.css">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=787432">Mozilla Bug 787432</a>
+<div id="test" contenteditable><span class="insert">%</span><br></div>
+<script>
+var div = document.getElementById("test");
+getSelection().collapse(div.firstChild, 0);
+getSelection().extend(div.firstChild, 1);
+document.execCommand("inserttext", false, "x");
+is(div.innerHTML, '<span class="insert">x</span><br>',
+   "Empty <span> needs to not be removed");
+</script>
--- a/extensions/gio/Makefile.in
+++ b/extensions/gio/Makefile.in
@@ -18,17 +18,17 @@ IS_COMPONENT	= 1
 CPPSRCS		= \
 		nsGIOProtocolHandler.cpp \
 		$(NULL)
 
 LOCAL_INCLUDES	= $(MOZ_GIO_CFLAGS)
 
 EXTRA_DSO_LDOPTS = \
 		   $(XPCOM_GLUE_LDOPTS) \
-		   $(NSPR_LIBS) \
+		   $(MOZ_COMPONENT_LIBS) \
 		   $(MOZ_GIO_LIBS) \
 		   $(NULL)
 
 # make sure this component is never statically linked into the main
 # application.  this is necessary since we don't want to force users
 # to install gio in order to use the rest of mozilla ;-)
 FORCE_SHARED_LIB= 1
 
--- a/gfx/layers/opengl/ImageLayerOGL.cpp
+++ b/gfx/layers/opengl/ImageLayerOGL.cpp
@@ -996,19 +996,17 @@ ShadowImageLayerOGL::RenderLayer(int aPr
     program->SetLayerQuadRect(nsIntRect(0, 0,
                                         mSize.width, mSize.height));
     program->SetLayerTransform(GetEffectiveTransform());
     program->SetLayerOpacity(GetEffectiveOpacity());
     program->SetRenderOffset(aOffset);
     program->SetTextureUnit(0);
     program->LoadMask(GetMaskLayer());
 
-    mOGLManager->BindAndDrawQuadWithTextureRect(program,
-                                                GetVisibleRegion().GetBounds(),
-                                                nsIntSize(mSize.width, mSize.height));
+    mOGLManager->BindAndDrawQuad(program);
     gl()->fBindTexture(LOCAL_GL_TEXTURE_EXTERNAL, 0);
 #endif
   } else if (mSharedHandle) {
     GLContext::SharedHandleDetails handleDetails;
     if (!gl()->GetSharedHandleDetails(mShareType, mSharedHandle, handleDetails)) {
       NS_ERROR("Failed to get shared handle details");
       return;
     }
--- a/js/src/ion/CodeGenerator.cpp
+++ b/js/src/ion/CodeGenerator.cpp
@@ -9,16 +9,18 @@
 #include "IonLinker.h"
 #include "IonSpewer.h"
 #include "MIRGenerator.h"
 #include "shared/CodeGenerator-shared-inl.h"
 #include "jsnum.h"
 #include "jsmath.h"
 #include "jsinterpinlines.h"
 
+#include "vm/StringObject-inl.h"
+
 using namespace js;
 using namespace js::ion;
 
 namespace js {
 namespace ion {
 
 CodeGenerator::CodeGenerator(MIRGenerator *gen, LIRGraph &graph)
   : CodeGeneratorSpecific(gen, graph)
@@ -192,21 +194,35 @@ CodeGenerator::visitPolyInlineDispatch(L
         }
     }
     return true;
 }
 
 bool
 CodeGenerator::visitIntToString(LIntToString *lir)
 {
+    Register input = ToRegister(lir->input());
+    Register output = ToRegister(lir->output());
+
     typedef JSFlatString *(*pf)(JSContext *, int);
     static const VMFunction IntToStringInfo = FunctionInfo<pf>(Int32ToString);
 
-    pushArg(ToRegister(lir->input()));
-    return callVM(IntToStringInfo, lir);
+    OutOfLineCode *ool = oolCallVM(IntToStringInfo, lir, (ArgList(), input),
+                                   StoreRegisterTo(output));
+    if (!ool)
+        return false;
+
+    masm.branch32(Assembler::AboveOrEqual, input, Imm32(StaticStrings::INT_STATIC_LIMIT),
+                  ool->entry());
+
+    masm.movePtr(ImmWord(&gen->compartment->rt->staticStrings.intStaticTable), output);
+    masm.loadPtr(BaseIndex(output, input, ScalePointer), output);
+
+    masm.bind(ool->rejoin());
+    return true;
 }
 
 bool
 CodeGenerator::visitRegExp(LRegExp *lir)
 {
     JSObject *proto = lir->mir()->getRegExpPrototype();
 
     typedef JSObject *(*pf)(JSContext *, JSObject *, JSObject *);
@@ -1510,16 +1526,45 @@ CodeGenerator::visitNewCallObject(LNewCa
 
     if (lir->slots()->isRegister())
         masm.storePtr(ToRegister(lir->slots()), Address(obj, JSObject::offsetOfSlots()));
     masm.bind(ool->rejoin());
     return true;
 }
 
 bool
+CodeGenerator::visitNewStringObject(LNewStringObject *lir)
+{
+    Register input = ToRegister(lir->input());
+    Register output = ToRegister(lir->output());
+    Register temp = ToRegister(lir->temp());
+
+    typedef JSObject *(*pf)(JSContext *, HandleString);
+    static const VMFunction NewStringObjectInfo = FunctionInfo<pf>(NewStringObject);
+
+    StringObject *templateObj = lir->mir()->templateObj();
+
+    OutOfLineCode *ool = oolCallVM(NewStringObjectInfo, lir, (ArgList(), input),
+                                   StoreRegisterTo(output));
+    if (!ool)
+        return false;
+
+    masm.newGCThing(output, templateObj, ool->entry());
+    masm.initGCThing(output, templateObj);
+
+    masm.loadStringLength(input, temp);
+
+    masm.storeValue(JSVAL_TYPE_STRING, input, Address(output, StringObject::offsetOfPrimitiveValue()));
+    masm.storeValue(JSVAL_TYPE_INT32, temp, Address(output, StringObject::offsetOfLength()));
+
+    masm.bind(ool->rejoin());
+    return true;
+}
+
+bool
 CodeGenerator::visitInitProp(LInitProp *lir)
 {
     Register objReg = ToRegister(lir->getObject());
 
     typedef bool(*pf)(JSContext *, HandleObject, HandlePropertyName, HandleValue);
     static const VMFunction InitPropInfo = FunctionInfo<pf>(InitProp);
 
     pushArg(ToValue(lir, LInitProp::ValueIndex));
@@ -1633,21 +1678,20 @@ CodeGenerator::visitTypedArrayElements(L
     Register out = ToRegister(lir->output());
     masm.loadPtr(Address(obj, TypedArray::dataOffset()), out);
     return true;
 }
 
 bool
 CodeGenerator::visitStringLength(LStringLength *lir)
 {
-    Address lengthAndFlags(ToRegister(lir->string()), JSString::offsetOfLengthAndFlags());
+    Register input = ToRegister(lir->string());
     Register output = ToRegister(lir->output());
 
-    masm.loadPtr(lengthAndFlags, output);
-    masm.rshiftPtr(Imm32(JSString::LENGTH_SHIFT), output);
+    masm.loadStringLength(input, output);
     return true;
 }
 
 bool
 CodeGenerator::visitMinMaxI(LMinMaxI *ins)
 {
     Register first = ToRegister(ins->first());
     Register output = ToRegister(ins->output());
--- a/js/src/ion/CodeGenerator.h
+++ b/js/src/ion/CodeGenerator.h
@@ -84,16 +84,17 @@ class CodeGenerator : public CodeGenerat
     bool visitNewSlots(LNewSlots *lir);
     bool visitNewArrayCallVM(LNewArray *lir);
     bool visitNewArray(LNewArray *lir);
     bool visitOutOfLineNewArray(OutOfLineNewArray *ool);
     bool visitNewObjectVMCall(LNewObject *lir);
     bool visitNewObject(LNewObject *lir);
     bool visitOutOfLineNewObject(OutOfLineNewObject *ool);
     bool visitNewCallObject(LNewCallObject *lir);
+    bool visitNewStringObject(LNewStringObject *lir);
     bool visitInitProp(LInitProp *lir);
     bool visitCreateThis(LCreateThis *lir);
     bool visitCreateThisVM(LCreateThisVM *lir);
     bool visitReturnFromCtor(LReturnFromCtor *lir);
     bool visitArrayLength(LArrayLength *lir);
     bool visitTypedArrayLength(LTypedArrayLength *lir);
     bool visitTypedArrayElements(LTypedArrayElements *lir);
     bool visitStringLength(LStringLength *lir);
--- a/js/src/ion/IonBuilder.h
+++ b/js/src/ion/IonBuilder.h
@@ -377,16 +377,17 @@ class IonBuilder : public MIRGenerator
     InliningStatus inlineMathRound(uint32 argc, bool constructing);
     InliningStatus inlineMathSqrt(uint32 argc, bool constructing);
     InliningStatus inlineMathMinMax(bool max, uint32 argc, bool constructing);
     InliningStatus inlineMathPow(uint32 argc, bool constructing);
     InliningStatus inlineMathFunction(MMathFunction::Function function, uint32 argc,
                                       bool constructing);
 
     // String natives.
+    InliningStatus inlineStringObject(uint32 argc, bool constructing);
     InliningStatus inlineStrCharCodeAt(uint32 argc, bool constructing);
     InliningStatus inlineStrFromCharCode(uint32 argc, bool constructing);
     InliningStatus inlineStrCharAt(uint32 argc, bool constructing);
 
     InliningStatus inlineNativeCall(JSNative native, uint32 argc, bool constructing);
 
     bool jsop_call_inline(HandleFunction callee, uint32 argc, bool constructing,
                           MConstant *constFun, MBasicBlock *bottom,
--- a/js/src/ion/IonMacroAssembler.h
+++ b/js/src/ion/IonMacroAssembler.h
@@ -144,16 +144,21 @@ class MacroAssembler : public MacroAssem
         loadPtr(Address(obj, JSObject::getPrivateDataOffset(nfixed)), dest);
     }
 
     void loadObjProto(Register obj, Register dest) {
         loadPtr(Address(obj, JSObject::offsetOfType()), dest);
         loadPtr(Address(dest, offsetof(types::TypeObject, proto)), dest);
     }
 
+    void loadStringLength(Register str, Register dest) {
+        loadPtr(Address(str, JSString::offsetOfLengthAndFlags()), dest);
+        rshiftPtr(Imm32(JSString::LENGTH_SHIFT), dest);
+    }
+
     void loadJSContext(const Register &dest) {
         movePtr(ImmWord(GetIonContext()->cx->runtime), dest);
         loadPtr(Address(dest, offsetof(JSRuntime, ionJSContext)), dest);
     }
     void loadIonActivation(const Register &dest) {
         movePtr(ImmWord(GetIonContext()->cx->runtime), dest);
         loadPtr(Address(dest, offsetof(JSRuntime, ionActivation)), dest);
     }
--- a/js/src/ion/LIR-Common.h
+++ b/js/src/ion/LIR-Common.h
@@ -287,16 +287,37 @@ class LNewCallObject : public LInstructi
     const LAllocation *slots() {
         return getOperand(0);
     }
     MNewCallObject *mir() const {
         return mir_->toNewCallObject();
     }
 };
 
+class LNewStringObject : public LInstructionHelper<1, 1, 1>
+{
+  public:
+    LIR_HEADER(NewStringObject);
+
+    LNewStringObject(const LAllocation &input, const LDefinition &temp) {
+        setOperand(0, input);
+        setTemp(0, temp);
+    }
+
+    const LAllocation *input() {
+        return getOperand(0);
+    }
+    const LDefinition *temp() {
+        return getTemp(0);
+    }
+    MNewStringObject *mir() const {
+        return mir_->toNewStringObject();
+    }
+};
+
 // Takes in an Object and a Value.
 class LInitProp : public LCallInstructionHelper<0, 1 + BOX_PIECES, 0>
 {
   public:
     LIR_HEADER(InitProp);
 
     LInitProp(const LAllocation &object) {
         setOperand(0, object);
@@ -1608,17 +1629,17 @@ class LTruncateDToInt32 : public LInstru
 
     const LDefinition *tempFloat() {
         return getTemp(0);
     }
 };
 
 // Convert a any input type hosted on one definition to a string with a function
 // call.
-class LIntToString : public LCallInstructionHelper<1, 1, 0>
+class LIntToString : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(IntToString);
 
     LIntToString(const LAllocation &input) {
         setOperand(0, input);
     }
 
--- a/js/src/ion/LOpcodes.h
+++ b/js/src/ion/LOpcodes.h
@@ -20,16 +20,17 @@
     _(Parameter)                    \
     _(Callee)                       \
     _(TableSwitch)                  \
     _(Goto)                         \
     _(NewArray)                     \
     _(NewObject)                    \
     _(NewSlots)                     \
     _(NewCallObject)                \
+    _(NewStringObject)              \
     _(InitProp)                     \
     _(CheckOverRecursed)            \
     _(RecompileCheck)               \
     _(DefVar)                       \
     _(CallKnown)                    \
     _(CallGeneric)                  \
     _(CallNative)                   \
     _(CallConstructor)              \
--- a/js/src/ion/Lowering.cpp
+++ b/js/src/ion/Lowering.cpp
@@ -134,16 +134,25 @@ LIRGenerator::visitNewCallObject(MNewCal
 
     if (!assignSafepoint(lir, ins))
         return false;
 
     return true;
 }
 
 bool
+LIRGenerator::visitNewStringObject(MNewStringObject *ins)
+{
+    JS_ASSERT(ins->input()->type() == MIRType_String);
+
+    LNewStringObject *lir = new LNewStringObject(useRegister(ins->input()), temp());
+    return define(lir, ins) && assignSafepoint(lir, ins);
+}
+
+bool
 LIRGenerator::visitInitProp(MInitProp *ins)
 {
     LInitProp *lir = new LInitProp(useRegisterAtStart(ins->getObject()));
     if (!useBoxAtStart(lir, LInitProp::ValueIndex, ins->getValue()))
         return false;
 
     return add(lir, ins) && assignSafepoint(lir, ins);
 }
@@ -1080,19 +1089,19 @@ LIRGenerator::visitToString(MToString *i
       case MIRType_Double:
       case MIRType_Null:
       case MIRType_Undefined:
       case MIRType_Boolean:
         JS_NOT_REACHED("NYI: Lower MToString");
         break;
 
       case MIRType_Int32: {
-        LIntToString *lir = new LIntToString(useRegisterAtStart(opd));
+        LIntToString *lir = new LIntToString(useRegister(opd));
 
-        if (!defineVMReturn(lir, ins))
+        if (!define(lir, ins))
             return false;
         return assignSafepoint(lir, ins);
       }
 
       default:
         // Objects might be effectful. (see ToPrimitive)
         JS_NOT_REACHED("unexpected type");
         break;
--- a/js/src/ion/Lowering.h
+++ b/js/src/ion/Lowering.h
@@ -76,16 +76,17 @@ class LIRGenerator : public LIRGenerator
     // intercept without a bunch of explicit gunk in the .cpp.
     bool visitParameter(MParameter *param);
     bool visitCallee(MCallee *callee);
     bool visitGoto(MGoto *ins);
     bool visitNewSlots(MNewSlots *ins);
     bool visitNewArray(MNewArray *ins);
     bool visitNewObject(MNewObject *ins);
     bool visitNewCallObject(MNewCallObject *ins);
+    bool visitNewStringObject(MNewStringObject *ins);
     bool visitInitProp(MInitProp *ins);
     bool visitCheckOverRecursed(MCheckOverRecursed *ins);
     bool visitDefVar(MDefVar *ins);
     bool visitPrepareCall(MPrepareCall *ins);
     bool visitPassArg(MPassArg *arg);
     bool visitCreateThis(MCreateThis *ins);
     bool visitReturnFromCtor(MReturnFromCtor *ins);
     bool visitCall(MCall *call);
--- a/js/src/ion/MCallOptimize.cpp
+++ b/js/src/ion/MCallOptimize.cpp
@@ -7,16 +7,18 @@
 
 #include "jslibmath.h"
 #include "jsmath.h"
 
 #include "MIR.h"
 #include "MIRGraph.h"
 #include "IonBuilder.h"
 
+#include "vm/StringObject-inl.h"
+
 namespace js {
 namespace ion {
 
 IonBuilder::InliningStatus
 IonBuilder::inlineNativeCall(JSNative native, uint32 argc, bool constructing)
 {
     // Array natives.
     if (native == js_Array)
@@ -48,16 +50,18 @@ IonBuilder::inlineNativeCall(JSNative na
     if (native == js::math_cos)
         return inlineMathFunction(MMathFunction::Cos, argc, constructing);
     if (native == js::math_tan)
         return inlineMathFunction(MMathFunction::Tan, argc, constructing);
     if (native == js::math_log)
         return inlineMathFunction(MMathFunction::Log, argc, constructing);
 
     // String natives.
+    if (native == js_String)
+        return inlineStringObject(argc, constructing);
     if (native == js_str_charCodeAt)
         return inlineStrCharCodeAt(argc, constructing);
     if (native == js::str_fromCharCode)
         return inlineStrFromCharCode(argc, constructing);
     if (native == js_str_charAt)
         return inlineStrCharAt(argc, constructing);
 
     return InliningStatus_NotInlined;
@@ -552,16 +556,46 @@ IonBuilder::inlineMathMinMax(bool max, u
 
     MMinMax *ins = MMinMax::New(argv[1], argv[2], returnType, max);
     current->add(ins);
     current->push(ins);
     return InliningStatus_Inlined;
 }
 
 IonBuilder::InliningStatus
+IonBuilder::inlineStringObject(uint32 argc, bool constructing)
+{
+    if (argc != 1 || !constructing)
+        return InliningStatus_NotInlined;
+
+    // MToString only supports int32 or string values.
+    MIRType type = getInlineArgType(argc, 1);
+    if (type != MIRType_Int32 && type != MIRType_String)
+        return InliningStatus_NotInlined;
+
+    MDefinitionVector argv;
+    if (!discardCall(argc, argv, current))
+        return InliningStatus_Error;
+
+    RootedString emptyString(cx, cx->runtime->emptyString);
+    RootedObject templateObj(cx, StringObject::create(cx, emptyString));
+    if (!templateObj)
+        return InliningStatus_Error;
+
+    MNewStringObject *ins = MNewStringObject::New(argv[1], templateObj);
+    current->add(ins);
+    current->push(ins);
+
+    if (!resumeAfter(ins))
+        return InliningStatus_Error;
+
+    return InliningStatus_Inlined;
+}
+
+IonBuilder::InliningStatus
 IonBuilder::inlineStrCharCodeAt(uint32 argc, bool constructing)
 {
     if (argc != 1 || constructing)
         return InliningStatus_NotInlined;
 
     if (getInlineReturnType() != MIRType_Int32)
         return InliningStatus_NotInlined;
     if (getInlineArgType(argc, 0) != MIRType_String)
--- a/js/src/ion/MIR.h
+++ b/js/src/ion/MIR.h
@@ -5283,16 +5283,47 @@ class MNewCallObject : public MUnaryInst
     JSObject *templateObj() {
         return templateObj_;
     }
     AliasSet getAliasSet() const {
         return AliasSet::None();
     }
 };
 
+class MNewStringObject :
+  public MUnaryInstruction,
+  public StringPolicy
+{
+    CompilerRootObject templateObj_;
+
+    MNewStringObject(MDefinition *input, HandleObject templateObj)
+      : MUnaryInstruction(input),
+        templateObj_(templateObj)
+    {
+        setResultType(MIRType_Object);
+    }
+
+  public:
+    INSTRUCTION_HEADER(NewStringObject);
+
+    static MNewStringObject *New(MDefinition *input, HandleObject templateObj) {
+        return new MNewStringObject(input, templateObj);
+    }
+
+    MDefinition *input() const {
+        return getOperand(0);
+    }
+    StringObject *templateObj() const {
+        return &templateObj_->asString();
+    }
+    TypePolicy *typePolicy() {
+        return this;
+    }
+};
+
 // Node that represents that a script has begun executing. This comes at the
 // start of the function and is called once per function (including inline
 // ones)
 class MFunctionBoundary : public MNullaryInstruction
 {
   public:
     enum Type {
         Enter,        // a function has begun executing and it is not inline
--- a/js/src/ion/MOpcodes.h
+++ b/js/src/ion/MOpcodes.h
@@ -65,16 +65,17 @@ namespace ion {
     _(ToDouble)                                                             \
     _(ToInt32)                                                              \
     _(TruncateToInt32)                                                      \
     _(ToString)                                                             \
     _(NewSlots)                                                             \
     _(NewArray)                                                             \
     _(NewObject)                                                            \
     _(NewCallObject)                                                        \
+    _(NewStringObject)                                                      \
     _(InitProp)                                                             \
     _(Start)                                                                \
     _(OsrEntry)                                                             \
     _(RegExp)                                                               \
     _(Lambda)                                                               \
     _(ImplicitThis)                                                         \
     _(Slots)                                                                \
     _(Elements)                                                             \
--- a/js/src/ion/TypePolicy.cpp
+++ b/js/src/ion/TypePolicy.cpp
@@ -277,17 +277,25 @@ PowPolicy::adjustInputs(MInstruction *in
 
 bool
 StringPolicy::staticAdjustInputs(MInstruction *def)
 {
     MDefinition *in = def->getOperand(0);
     if (in->type() == MIRType_String)
         return true;
 
-    MUnbox *replace = MUnbox::New(in, MIRType_String, MUnbox::Fallible);
+    MInstruction *replace;
+    if (in->type() == MIRType_Int32) {
+        replace = MToString::New(in);
+    } else {
+        if (in->type() != MIRType_Value)
+            in = boxAt(def, in);
+        replace = MUnbox::New(in, MIRType_String, MUnbox::Fallible);
+    }
+
     def->block()->insertBefore(def, replace);
     def->replaceOperand(0, replace);
     return true;
 }
 
 template <unsigned Op>
 bool
 IntPolicy<Op>::staticAdjustInputs(MInstruction *def)
--- a/js/src/ion/VMFunctions.cpp
+++ b/js/src/ion/VMFunctions.cpp
@@ -6,16 +6,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "Ion.h"
 #include "IonCompartment.h"
 #include "jsinterp.h"
 #include "ion/IonFrames.h"
 #include "ion/IonFrames-inl.h" // for GetTopIonJSScript
 
+#include "vm/StringObject-inl.h"
+
 #include "jsinterpinlines.h"
 
 using namespace js;
 using namespace js::ion;
 
 namespace js {
 namespace ion {
 
@@ -380,16 +382,22 @@ NewSlots(JSRuntime *rt, unsigned nslots)
 }
 
 JSObject *
 NewCallObject(JSContext *cx, HandleShape shape, HandleTypeObject type, HeapSlot *slots)
 {
     return CallObject::create(cx, shape, type, slots);
 }
 
+JSObject *
+NewStringObject(JSContext *cx, HandleString str)
+{
+    return StringObject::create(cx, str);
+}
+
 bool SPSEnter(JSContext *cx, HandleScript script)
 {
     return cx->runtime->spsProfiler.enter(cx, script, script->function());
 }
 
 bool SPSExit(JSContext *cx, HandleScript script)
 {
     cx->runtime->spsProfiler.exit(cx, script, script->function());
--- a/js/src/ion/VMFunctions.h
+++ b/js/src/ion/VMFunctions.h
@@ -434,16 +434,17 @@ JSFlatString *StringFromCharCode(JSConte
 
 bool SetProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, HandleValue value,
                  bool strict, bool isSetName);
 
 bool InterruptCheck(JSContext *cx);
 
 HeapSlot *NewSlots(JSRuntime *rt, unsigned nslots);
 JSObject *NewCallObject(JSContext *cx, HandleShape shape, HandleTypeObject type, HeapSlot *slots);
+JSObject *NewStringObject(JSContext *cx, HandleString str);
 
 bool SPSEnter(JSContext *cx, HandleScript script);
 bool SPSExit(JSContext *cx, HandleScript script);
 
 
 } // namespace ion
 } // namespace js
 
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -1310,16 +1310,26 @@ TypeConstraintCall::newType(JSContext *c
                 if (callsite->argumentCount >= 2) {
                     for (unsigned i = 0; i < callsite->argumentCount; i++) {
                         PropertyAccess<PROPERTY_WRITE>(cx, script, pc, res,
                                                        callsite->argumentTypes[i], JSID_VOID);
                     }
                 }
             }
 
+            if (native == js_String && callsite->isNew) {
+                // Note that "new String()" returns a String object and "String()"
+                // returns a primitive string.
+                TypeObject *res = TypeScript::StandardType(cx, script, JSProto_String);
+                if (!res)
+                    return;
+
+                callsite->returnTypes->addType(cx, Type::ObjectType(res));
+            }
+
             return;
         }
 
         callee = obj->toFunction();
     } else if (type.isTypeObject()) {
         callee = type.typeObject()->interpretedFunction;
         if (!callee)
             return;
--- a/js/src/methodjit/PolyIC.cpp
+++ b/js/src/methodjit/PolyIC.cpp
@@ -860,19 +860,17 @@ class GetPropCompiler : public PICStubCo
 
     LookupStatus generateStringObjLengthStub()
     {
         MJITInstrumentation sps(&f.cx->runtime->spsProfiler);
         Assembler masm(&sps, &f);
 
         Jump notStringObj = masm.guardShape(pic.objReg, obj);
 
-        masm.loadPayload(Address(pic.objReg, StringObject::getPrimitiveValueOffset()), pic.objReg);
-        masm.loadPtr(Address(pic.objReg, JSString::offsetOfLengthAndFlags()), pic.objReg);
-        masm.urshift32(Imm32(JSString::LENGTH_SHIFT), pic.objReg);
+        masm.loadPayload(Address(pic.objReg, StringObject::offsetOfLength()), pic.objReg);
         masm.move(ImmType(JSVAL_TYPE_INT32), pic.shapeReg);
         Jump done = masm.jump();
 
         pic.updatePCCounters(f, masm);
 
         PICLinker buffer(masm, pic);
         if (!buffer.init(cx))
             return error();
--- a/js/src/vm/String.h
+++ b/js/src/vm/String.h
@@ -677,32 +677,32 @@ namespace js {
 
 class StaticStrings
 {
   private:
     /* Bigger chars cannot be in a length-2 string. */
     static const size_t SMALL_CHAR_LIMIT    = 128U;
     static const size_t NUM_SMALL_CHARS     = 64U;
 
-    static const size_t INT_STATIC_LIMIT    = 256U;
-
     JSAtom *length2StaticTable[NUM_SMALL_CHARS * NUM_SMALL_CHARS];
-    JSAtom *intStaticTable[INT_STATIC_LIMIT];
 
     void clear() {
         PodArrayZero(unitStaticTable);
         PodArrayZero(length2StaticTable);
         PodArrayZero(intStaticTable);
     }
 
   public:
-    /* We keep these public for the methodjit. */
+    /* We keep these public for the JITs. */
     static const size_t UNIT_STATIC_LIMIT   = 256U;
     JSAtom *unitStaticTable[UNIT_STATIC_LIMIT];
 
+    static const size_t INT_STATIC_LIMIT    = 256U;
+    JSAtom *intStaticTable[INT_STATIC_LIMIT];
+
     StaticStrings() {
         clear();
     }
 
     bool init(JSContext *cx);
     void trace(JSTracer *trc);
     void finish() {
         clear();
--- a/js/src/vm/StringObject.h
+++ b/js/src/vm/StringObject.h
@@ -36,19 +36,22 @@ class StringObject : public JSObject
     JSString *unbox() const {
         return getFixedSlot(PRIMITIVE_VALUE_SLOT).toString();
     }
 
     inline size_t length() const {
         return size_t(getFixedSlot(LENGTH_SLOT).toInt32());
     }
 
-    static size_t getPrimitiveValueOffset() {
+    static size_t offsetOfPrimitiveValue() {
         return getFixedSlotOffset(PRIMITIVE_VALUE_SLOT);
     }
+    static size_t offsetOfLength() {
+        return getFixedSlotOffset(LENGTH_SLOT);
+    }
 
   private:
     inline bool init(JSContext *cx, HandleString str);
 
     void setStringThis(JSString *str) {
         JS_ASSERT(getReservedSlot(PRIMITIVE_VALUE_SLOT).isUndefined());
         setFixedSlot(PRIMITIVE_VALUE_SLOT, StringValue(str));
         setFixedSlot(LENGTH_SLOT, Int32Value(int32_t(str->length())));
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -1874,17 +1874,17 @@ struct NS_STACK_CLASS ExceptionArgParser
         JSString *str = JS_ValueToString(cx, v);
         if (!str)
            return false;
         eMsg = messageBytes.encode(cx, str);
         return !!eMsg;
     }
 
     bool parseResult(JS::Value &v) {
-        return JS_ValueToECMAInt32(cx, v, (int32_t*) &eResult);
+        return JS_ValueToECMAUint32(cx, v, (uint32_t*) &eResult);
     }
 
     bool parseStack(JS::Value &v) {
         if (!v.isObject()) {
             // eStack has already been initialized to null, which is what we want
             // for any non-object values (including null).
             return true;
         }
--- a/js/xpconnect/src/qsgen.py
+++ b/js/xpconnect/src/qsgen.py
@@ -183,17 +183,17 @@ def addStubMember(memberId, member):
 def checkStubMember(member, isCustom):
     memberId = member.iface.name + "." + member.name
     if member.kind not in ('method', 'attribute'):
         raise UserError("Member %s is %r, not a method or attribute."
                         % (memberId, member.kind))
     if member.noscript:
         raise UserError("%s %s is noscript."
                         % (member.kind.capitalize(), memberId))
-    if member.notxpcom:
+    if member.kind == 'method' and member.notxpcom:
         raise UserError(
             "%s %s: notxpcom methods are not supported."
             % (member.kind.capitalize(), memberId))
 
     if (member.kind == 'attribute'
           and not member.readonly
           and isSpecificInterfaceType(member.realtype, 'nsIVariant')
           and not isCustom):
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -4956,17 +4956,17 @@ nsLayoutUtils::FontSizeInflationEnabled(
   // object.
 
   // TODO:
   // Once bug 716575 has been resolved, this code should be changed so that it
   // does the right thing on all platforms.
   nsresult rv;
   nsCOMPtr<nsIScreenManager> screenMgr =
     do_GetService("@mozilla.org/gfx/screenmanager;1", &rv);
-  NS_ENSURE_SUCCESS(rv, rv);
+  NS_ENSURE_SUCCESS(rv, false);
 
   nsCOMPtr<nsIScreen> screen;
   screenMgr->GetPrimaryScreen(getter_AddRefs(screen));
   if (screen) {
     int32_t screenLeft, screenTop, screenWidth, screenHeight;
     screen->GetRect(&screenLeft, &screenTop, &screenWidth, &screenHeight);
 
     ViewportInfo vInf =
--- a/layout/build/Makefile.in
+++ b/layout/build/Makefile.in
@@ -114,16 +114,23 @@ SHARED_LIBRARY_LIBS += \
 	$(DEPTH)/dom/plugins/base/android/$(LIB_PREFIX)gkpluginandroid_s.$(LIB_SUFFIX) \
 	$(NULL)
 LOCAL_INCLUDES	+= \
 	-I$(topsrcdir)/dom/system/android \
 	-I$(topsrcdir)/dom/system \
 	$(NULL)
 endif
 
+ifeq (gonk,$(MOZ_WIDGET_TOOLKIT)) #{
+# include OMX decoder
+SHARED_LIBRARY_LIBS 	+= \
+	$(DEPTH)/content/media/omx/$(LIB_PREFIX)gkconomx_s.$(LIB_SUFFIX) \
+	$(NULL)
+endif #}
+
 ifdef MOZ_B2G_FM #{
 SHARED_LIBRARY_LIBS	+= \
   $(DEPTH)/dom/fm/$(LIB_PREFIX)domfm_s.$(LIB_SUFFIX) \
   $(NULL)
 endif #}
 
 ifdef MOZ_B2G_BT #{
 SHARED_LIBRARY_LIBS += $(DEPTH)/dom/bluetooth/$(LIB_PREFIX)dombluetooth_s.$(LIB_SUFFIX)
@@ -178,16 +185,35 @@ SHARED_LIBRARY_LIBS 	+= \
 endif
 
 ifdef MOZ_MEDIA_PLUGINS
 SHARED_LIBRARY_LIBS 	+= \
 	$(DEPTH)/content/media/plugins/$(LIB_PREFIX)gkconmediaplugins_s.$(LIB_SUFFIX) \
 	$(NULL)
 endif
 
+ifeq (gonk,$(MOZ_WIDGET_TOOLKIT))
+INCLUDES	+= \
+		-I$(srcdir)/../../base/src \
+		-I$(srcdir)/../../html/content/src \
+		-I$(ANDROID_SOURCE)/dalvik/libnativehelper/include/nativehelper \
+		-I$(ANDROID_SOURCE)/frameworks/base/include/ \
+		-I$(ANDROID_SOURCE)/frameworks/base/include/binder/ \
+		-I$(ANDROID_SOURCE)/frameworks/base/include/utils/ \
+		-I$(ANDROID_SOURCE)/frameworks/base/include/media/ \
+		-I$(ANDROID_SOURCE)/frameworks/base/include/media/stagefright/openmax \
+		-I$(ANDROID_SOURCE)/frameworks/base/media/libstagefright/include \
+		$(NULL)
+
+EXTRA_DSO_LDOPTS += \
+		-lutils -lstagefright -lmedia -lstagefright_omx -lbinder -lui \
+		-lhardware -lcutils \
+		$(NULL)
+endif
+
 ifdef NS_PRINTING
 SHARED_LIBRARY_LIBS += \
 		../printing/$(LIB_PREFIX)gkprinting_s.$(LIB_SUFFIX) \
 		$(NULL)
 endif
 
 ifdef MOZ_XUL
 SHARED_LIBRARY_LIBS += \
--- a/mobile/android/base/BrowserApp.java
+++ b/mobile/android/base/BrowserApp.java
@@ -49,17 +49,29 @@ abstract public class BrowserApp extends
                                             PropertyAnimator.PropertyAnimationListener {
     private static final String LOGTAG = "GeckoBrowserApp";
 
     public static BrowserToolbar mBrowserToolbar;
     private AboutHomeContent mAboutHomeContent;
     private boolean mAboutHomeShowing;
 
     private static final int ADDON_MENU_OFFSET = 1000;
-    static Vector<MenuItem> sAddonMenuItems = new Vector<MenuItem>();
+    private class MenuItemInfo {
+        int id;
+        String label;
+        String icon;
+
+        public MenuItemInfo(int id, String label, String icon) {
+            this.id = id;
+            this.label = label;
+            this.icon = icon;
+        }
+    }
+
+    private Vector<MenuItemInfo> mAddonMenuItemsCache;
 
     private PropertyAnimator mMainLayoutAnimator;
 
     private FindInPageBar mFindInPageBar;
 
     // We'll ask for feedback after the user launches the app this many times.
     private static final int FEEDBACK_LAUNCH_COUNT = 10;
 
@@ -632,18 +644,23 @@ abstract public class BrowserApp extends
                 mAboutHomeContent.setVisibility(View.VISIBLE);
             } else {
                 findViewById(R.id.abouthome_content).setVisibility(View.GONE);
             }
         } 
     }
 
     private void addAddonMenuItem(final int id, final String label, final String icon) {
-        if (mMenu == null)
+        if (mMenu == null) {
+            if (mAddonMenuItemsCache == null)
+                mAddonMenuItemsCache = new Vector<MenuItemInfo>();
+
+            mAddonMenuItemsCache.add(new MenuItemInfo(id, label, icon));
             return;
+        }
 
         final MenuItem item = mMenu.add(Menu.NONE, id, Menu.NONE, label);
 
         item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
             @Override
             public boolean onMenuItemClick(MenuItem item) {
                 Log.i(LOGTAG, "menu item clicked");
                 GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Menu:Clicked", Integer.toString(id)));
@@ -672,46 +689,57 @@ abstract public class BrowserApp extends
                             }
                         } catch (Exception e) {
                             Log.w(LOGTAG, "Unable to set icon", e);
                         }
                     }
                 });
             }
         }
-        sAddonMenuItems.add(item);
     }
 
     private void removeAddonMenuItem(int id) {
-        for (MenuItem item : sAddonMenuItems) {
-            if (item.getItemId() == id) {
-                sAddonMenuItems.remove(item);
-
-                if (mMenu == null)
-                    break;
-
-                MenuItem menuItem = mMenu.findItem(id);
-                if (menuItem != null)
-                    mMenu.removeItem(id);
-
-                break;
+        // Remove add-on menu item from cache, if available.
+        if (mAddonMenuItemsCache != null && !mAddonMenuItemsCache.isEmpty()) {
+            for (MenuItemInfo item : mAddonMenuItemsCache) {
+                 if (item.id == id) {
+                     mAddonMenuItemsCache.remove(item);
+                     break;
+                 }
             }
         }
+
+        if (mMenu == null)
+            return;
+
+        MenuItem menuItem = mMenu.findItem(id);
+        if (menuItem != null)
+            mMenu.removeItem(id);
     }
 
     @Override
     public boolean onCreateOptionsMenu(Menu menu) {
         super.onCreateOptionsMenu(menu);
 
         // Inform the menu about the action-items bar. 
         if (menu instanceof GeckoMenu && isTablet())
             ((GeckoMenu) menu).setActionItemBarPresenter(mBrowserToolbar);
 
         MenuInflater inflater = getMenuInflater();
         inflater.inflate(R.menu.browser_app_menu, mMenu);
+
+        // Add add-on menu items if any.
+        if (mAddonMenuItemsCache != null && !mAddonMenuItemsCache.isEmpty()) {
+            for (MenuItemInfo item : mAddonMenuItemsCache) {
+                 addAddonMenuItem(item.id, item.label, item.icon);
+            }
+
+            mAddonMenuItemsCache.clear();
+        }
+
         return true;
     }
 
     @Override
     public void openOptionsMenu() {
         if (!hasTabsSideBar() && areTabsShown())
             return;
 
@@ -765,27 +793,22 @@ abstract public class BrowserApp extends
             share.setEnabled(false);
             saveAsPDF.setEnabled(false);
             findInPage.setEnabled(false);
             return true;
         }
 
         bookmark.setEnabled(!tab.getURL().startsWith("about:reader"));
         bookmark.setCheckable(true);
-        
-        if (tab.isBookmark()) {
-            bookmark.setChecked(true);
-            bookmark.setIcon(R.drawable.ic_menu_bookmark_remove);
-        } else {
-            bookmark.setChecked(false);
-            bookmark.setIcon(R.drawable.ic_menu_bookmark_add);
-        }
+        bookmark.setChecked(tab.isBookmark());
+        bookmark.setIcon(tab.isBookmark() ? R.drawable.ic_menu_bookmark_remove : R.drawable.ic_menu_bookmark_add);
 
         forward.setEnabled(tab.canDoForward());
         desktopMode.setChecked(tab.getDesktopMode());
+        desktopMode.setIcon(tab.getDesktopMode() ? R.drawable.ic_menu_desktop_mode_on : R.drawable.ic_menu_desktop_mode_off);
 
         String url = tab.getURL();
         if (ReaderModeUtils.isAboutReader(url))
             url = ReaderModeUtils.getUrlFromAboutReader(url);
 
         // Disable share menuitem for about:, chrome:, file:, and resource: URIs
         String scheme = Uri.parse(url).getScheme();
         share.setEnabled(!(scheme.equals("about") || scheme.equals("chrome") ||
--- a/mobile/android/base/GeckoApp.java
+++ b/mobile/android/base/GeckoApp.java
@@ -1433,16 +1433,17 @@ abstract public class GeckoApp
                 (((screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_LARGE) || 
                  ((screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_XLARGE)));
     }
 
     /** Called when the activity is first created. */
     @Override
     public void onCreate(Bundle savedInstanceState)
     {
+        ((GeckoApplication)getApplication()).initialize();
         GeckoAppShell.registerGlobalExceptionHandler();
 
         mAppContext = this;
         Tabs.getInstance().attachToActivity(this);
 
         // Check to see if the activity is restarted after configuration change.
         if (getLastNonConfigurationInstance() != null) {
             // Restart the application as a safe way to handle the configuration change.
--- a/mobile/android/base/GeckoApplication.java
+++ b/mobile/android/base/GeckoApplication.java
@@ -5,32 +5,34 @@
 package org.mozilla.gecko;
 
 import android.app.Application;
 
 import java.util.ArrayList;
 
 public class GeckoApplication extends Application {
 
+    private boolean mInited;
     private boolean mInBackground;
 
-    @Override
-    public void onCreate() {
+    protected void initialize() {
+        if (mInited)
+            return;
+
         // workaround for http://code.google.com/p/android/issues/detail?id=20915
         try {
             Class.forName("android.os.AsyncTask");
         } catch (ClassNotFoundException e) {}
 
-        super.onCreate();
-
         GeckoConnectivityReceiver.getInstance().init(getApplicationContext());
         GeckoBatteryManager.getInstance().init(getApplicationContext());
         GeckoBatteryManager.getInstance().start();
         GeckoNetworkManager.getInstance().init(getApplicationContext());
         MemoryMonitor.getInstance().init(getApplicationContext());
+        mInited = true;
     }
 
     protected void onActivityPause(GeckoActivity activity) {
         mInBackground = true;
 
         GeckoAppShell.sendEventToGecko(GeckoEvent.createPauseEvent(true));
         GeckoConnectivityReceiver.getInstance().stop();
         GeckoNetworkManager.getInstance().stop();
--- a/mobile/android/base/GeckoMenuItem.java
+++ b/mobile/android/base/GeckoMenuItem.java
@@ -20,16 +20,17 @@ public class GeckoMenuItem implements Me
         public void setId(int id);
         public void setIcon(Drawable icon);
         public void setIcon(int iconRes);
         public void setTitle(CharSequence title);
         public void setEnabled(boolean enabled);
         public void setCheckable(boolean checkable);
         public void setChecked(boolean checked);
         public void setOnClickListener(View.OnClickListener listener);
+        public void setSubMenuIndicator(boolean hasSubMenu);
         public void setVisibility(int visible);
         public View getLayout();
     }
 
     public static interface OnShowAsActionChangedListener {
         public boolean hasActionItemBar();
         public void onShowAsActionChanged(GeckoMenuItem item, boolean isActionItem);
     }
@@ -311,16 +312,17 @@ public class GeckoMenuItem implements Me
 
     @Override
     public MenuItem setShowAsActionFlags(int actionEnum) {
         return this;
     }
 
     public MenuItem setSubMenu(GeckoSubMenu subMenu) {
         mSubMenu = subMenu;
+        mLayout.setSubMenuIndicator(subMenu != null);
         return this;
     }
 
     @Override
     public MenuItem setTitle(CharSequence title) {
         mTitle = title;
         mLayout.setTitle(mTitle);
         return this;
--- a/mobile/android/base/Makefile.in
+++ b/mobile/android/base/Makefile.in
@@ -460,20 +460,23 @@ RES_DRAWABLE_BASE = \
   res/drawable/ic_addons_empty.png \
   res/drawable/ic_awesomebar_go.png \
   res/drawable/ic_awesomebar_reader.png \
   res/drawable/ic_awesomebar_search.png \
   res/drawable/ic_awesomebar_star.png \
   res/drawable/ic_menu_back.xml \
   res/drawable/ic_menu_bookmark_add.png \
   res/drawable/ic_menu_bookmark_remove.png \
+  res/drawable/ic_menu_desktop_mode_off.xml \
+  res/drawable/ic_menu_desktop_mode_on.xml \
+  res/drawable/ic_menu_forward.png \
   res/drawable/ic_menu_reload.png \
   res/drawable/ic_menu_save_as_pdf.png \
   res/drawable/ic_menu_share.png \
-  res/drawable/ic_menu_forward.png \
+  res/drawable/ic_menu_quit.xml \
   res/drawable/remote_tabs_off.png \
   res/drawable/remote_tabs_on.png \
   res/drawable/tab_new.png \
   res/drawable/tab_close.png \
   res/drawable/tab_thumbnail_default.png \
   res/drawable/tab_thumbnail_shadow.png \
   res/drawable/tabs_carat.png \
   res/drawable/address_bar_back_button.xml \
@@ -636,72 +639,96 @@ RES_DRAWABLE_XHDPI = \
   res/drawable-xhdpi/handle_middle.png \
   res/drawable-xhdpi/handle_start.png \
   $(NULL)
 
 RES_DRAWABLE_MDPI_V11 = \
   res/drawable-mdpi-v11/alert_addon.png \
   res/drawable-mdpi-v11/alert_app.png \
   res/drawable-mdpi-v11/alert_download.png \
+  res/drawable-mdpi-v11/ic_menu_addons.png \
+  res/drawable-mdpi-v11/ic_menu_apps.png \
   res/drawable-mdpi-v11/ic_menu_back.png \
   res/drawable-mdpi-v11/ic_menu_bookmark_add.png \
   res/drawable-mdpi-v11/ic_menu_bookmark_remove.png \
-  res/drawable-mdpi-v11/ic_menu_desktop_mode.png \
+  res/drawable-mdpi-v11/ic_menu_desktop_mode_off.png \
+  res/drawable-mdpi-v11/ic_menu_desktop_mode_on.png \
+  res/drawable-mdpi-v11/ic_menu_downloads.png \
   res/drawable-mdpi-v11/ic_menu_find_in_page.png \
   res/drawable-mdpi-v11/ic_menu_forward.png \
   res/drawable-mdpi-v11/ic_menu_reload.png \
   res/drawable-mdpi-v11/ic_menu_save_as_pdf.png \
+  res/drawable-mdpi-v11/ic_menu_settings.png \
   res/drawable-mdpi-v11/ic_menu_share.png \
+  res/drawable-mdpi-v11/ic_menu_tools.png \
+  res/drawable-mdpi-v11/ic_menu_quit.png \
   res/drawable-mdpi-v11/menu.png \
   res/drawable-mdpi-v11/menu_panel_bg.9.png \
   res/drawable-mdpi-v11/menu_popup_bg.9.png \
   res/drawable-mdpi-v11/menu_popup_arrow.png \
   res/drawable-mdpi-v11/menu_item_check.png \
+  res/drawable-mdpi-v11/menu_item_more.png \
   res/drawable-mdpi-v11/menu_item_uncheck.png \
   $(NULL)
 
 RES_DRAWABLE_HDPI_V11 = \
   res/drawable-hdpi-v11/alert_addon.png \
   res/drawable-hdpi-v11/alert_app.png \
   res/drawable-hdpi-v11/alert_download.png \
+  res/drawable-hdpi-v11/ic_menu_addons.png \
+  res/drawable-hdpi-v11/ic_menu_apps.png \
   res/drawable-hdpi-v11/ic_menu_back.png \
   res/drawable-hdpi-v11/ic_menu_bookmark_add.png \
   res/drawable-hdpi-v11/ic_menu_bookmark_remove.png \
-  res/drawable-hdpi-v11/ic_menu_desktop_mode.png \
+  res/drawable-hdpi-v11/ic_menu_desktop_mode_off.png \
+  res/drawable-hdpi-v11/ic_menu_desktop_mode_on.png \
+  res/drawable-hdpi-v11/ic_menu_downloads.png \
   res/drawable-hdpi-v11/ic_menu_find_in_page.png \
   res/drawable-hdpi-v11/ic_menu_forward.png \
   res/drawable-hdpi-v11/ic_menu_reload.png \
   res/drawable-hdpi-v11/ic_menu_save_as_pdf.png \
+  res/drawable-hdpi-v11/ic_menu_settings.png \
   res/drawable-hdpi-v11/ic_menu_share.png \
+  res/drawable-hdpi-v11/ic_menu_tools.png \
+  res/drawable-hdpi-v11/ic_menu_quit.png \
   res/drawable-hdpi-v11/menu.png \
   res/drawable-hdpi-v11/menu_panel_bg.9.png \
   res/drawable-hdpi-v11/menu_popup_bg.9.png \
   res/drawable-hdpi-v11/menu_popup_arrow.png \
   res/drawable-hdpi-v11/menu_item_check.png \
+  res/drawable-hdpi-v11/menu_item_more.png \
   res/drawable-hdpi-v11/menu_item_uncheck.png \
   $(NULL)
 
 RES_DRAWABLE_XHDPI_V11 = \
   res/drawable-xhdpi-v11/alert_addon.png \
   res/drawable-xhdpi-v11/alert_app.png \
   res/drawable-xhdpi-v11/alert_download.png \
+  res/drawable-xhdpi-v11/ic_menu_addons.png \
+  res/drawable-xhdpi-v11/ic_menu_apps.png \
   res/drawable-xhdpi-v11/ic_menu_back.png \
   res/drawable-xhdpi-v11/ic_menu_bookmark_add.png \
   res/drawable-xhdpi-v11/ic_menu_bookmark_remove.png \
-  res/drawable-xhdpi-v11/ic_menu_desktop_mode.png \
+  res/drawable-xhdpi-v11/ic_menu_desktop_mode_off.png \
+  res/drawable-xhdpi-v11/ic_menu_desktop_mode_on.png \
+  res/drawable-xhdpi-v11/ic_menu_downloads.png \
   res/drawable-xhdpi-v11/ic_menu_find_in_page.png \
   res/drawable-xhdpi-v11/ic_menu_forward.png \
   res/drawable-xhdpi-v11/ic_menu_reload.png \
   res/drawable-xhdpi-v11/ic_menu_save_as_pdf.png \
+  res/drawable-xhdpi-v11/ic_menu_settings.png \
   res/drawable-xhdpi-v11/ic_menu_share.png \
+  res/drawable-xhdpi-v11/ic_menu_tools.png \
+  res/drawable-xhdpi-v11/ic_menu_quit.png \
   res/drawable-xhdpi-v11/menu.png \
   res/drawable-xhdpi-v11/menu_panel_bg.9.png \
   res/drawable-xhdpi-v11/menu_popup_bg.9.png \
   res/drawable-xhdpi-v11/menu_popup_arrow.png \
   res/drawable-xhdpi-v11/menu_item_check.png \
+  res/drawable-xhdpi-v11/menu_item_more.png \
   res/drawable-xhdpi-v11/menu_item_uncheck.png \
   $(NULL)
 
 RES_DRAWABLE_LAND_V14 = \
   res/drawable-land-v14/address_bar_bg.xml \
   $(NULL)
 
 RES_DRAWABLE_LAND_MDPI_V14 = \
--- a/mobile/android/base/MemoryMonitor.java
+++ b/mobile/android/base/MemoryMonitor.java
@@ -29,16 +29,17 @@ import android.util.Log;
   * Synchronization note: MemoryMonitor contains an inner class PressureDecrementer. Both
   * of these classes may be accessed from various threads, and have both been designed to
   * be thread-safe. In terms of lock ordering, code holding the PressureDecrementer lock
   * is allowed to pick up the MemoryMonitor lock, but not vice-versa.
   */
 class MemoryMonitor extends BroadcastReceiver {
     private static final String LOGTAG = "GeckoMemoryMonitor";
     private static final String ACTION_MEMORY_DUMP = "org.mozilla.gecko.MEMORY_DUMP";
+    private static final String ACTION_FORCE_PRESSURE = "org.mozilla.gecko.FORCE_MEMORY_PRESSURE";
 
     private static final int MEMORY_PRESSURE_NONE = 0;
     private static final int MEMORY_PRESSURE_CLEANUP = 1;
     private static final int MEMORY_PRESSURE_LOW = 2;
     private static final int MEMORY_PRESSURE_MEDIUM = 3;
     private static final int MEMORY_PRESSURE_HIGH = 4;
 
     private static MemoryMonitor sInstance = new MemoryMonitor();
@@ -57,16 +58,17 @@ class MemoryMonitor extends BroadcastRec
         mStoragePressure = false;
     }
 
     public void init(Context context) {
         IntentFilter filter = new IntentFilter();
         filter.addAction(Intent.ACTION_DEVICE_STORAGE_LOW);
         filter.addAction(Intent.ACTION_DEVICE_STORAGE_OK);
         filter.addAction(ACTION_MEMORY_DUMP);
+        filter.addAction(ACTION_FORCE_PRESSURE);
         context.getApplicationContext().registerReceiver(this, filter);
     }
 
     public void onLowMemory() {
         Log.d(LOGTAG, "onLowMemory() notification received");
         increaseMemoryPressure(MEMORY_PRESSURE_HIGH);
     }
 
@@ -110,16 +112,18 @@ class MemoryMonitor extends BroadcastRec
             Log.d(LOGTAG, "Device storage is ok");
             mStoragePressure = false;
         } else if (ACTION_MEMORY_DUMP.equals(intent.getAction())) {
             String label = intent.getStringExtra("label");
             if (label == null) {
                 label = "default";
             }
             GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Memory:Dump", label));
+        } else if (ACTION_FORCE_PRESSURE.equals(intent.getAction())) {
+            increaseMemoryPressure(MEMORY_PRESSURE_HIGH);
         }
     }
 
     private void increaseMemoryPressure(int level) {
         int oldLevel;
         synchronized (this) {
             // bump up our level if we're not already higher
             if (mMemoryPressure > level) {
--- a/mobile/android/base/MenuItemActionBar.java
+++ b/mobile/android/base/MenuItemActionBar.java
@@ -67,9 +67,13 @@ public class MenuItemActionBar extends I
 
     @Override
     public void setCheckable(boolean checkable) {
     }
 
     @Override
     public void setChecked(boolean checked) {
     }
+
+    @Override
+    public void setSubMenuIndicator(boolean hasSubMenu) {
+    }
 }
--- a/mobile/android/base/MenuItemDefault.java
+++ b/mobile/android/base/MenuItemDefault.java
@@ -17,34 +17,38 @@ import android.widget.TextView;
 
 public class MenuItemDefault extends LinearLayout
                              implements GeckoMenuItem.Layout {
     private static final String LOGTAG = "GeckoMenuItemDefault";
 
     private ImageView mIcon;
     private TextView mTitle;
     private CheckBox mCheck;
+    private ImageView mMore;
 
     private boolean mCheckable;
     private boolean mChecked;
+    private boolean mHasSubMenu;
 
     public MenuItemDefault(Context context, AttributeSet attrs) {
         super(context, attrs);
 
         Resources res = context.getResources();
         setLayoutParams(new AbsListView.LayoutParams((int) (res.getDimension(R.dimen.menu_item_row_width)),
                                                      (int) (res.getDimension(R.dimen.menu_item_row_height))));
 
         inflate(context, R.layout.menu_item, this);
         mIcon = (ImageView) findViewById(R.id.icon);
         mTitle = (TextView) findViewById(R.id.title);
         mCheck = (CheckBox) findViewById(R.id.check);
+        mMore = (ImageView) findViewById(R.id.more);
 
         mCheckable = false;
         mChecked = false;
+        mHasSubMenu = false;
     }
 
     @Override
     public View getLayout() {
         return this;
     }
 
     @Override
@@ -73,22 +77,30 @@ public class MenuItemDefault extends Lin
     }
 
     @Override
     public void setEnabled(boolean enabled) {
         super.setEnabled(enabled);
         mTitle.setEnabled(enabled);
         mCheck.setEnabled(enabled);
         mIcon.setColorFilter(enabled ? 0 : 0xFF999999);
+        mMore.setColorFilter(enabled ? 0 : 0xFF999999);
     }
 
     @Override
     public void setCheckable(boolean checkable) {
         mCheckable = checkable;
-        mCheck.setVisibility(mCheckable ? VISIBLE : GONE);
+        mCheck.setVisibility(mCheckable && !mHasSubMenu ? VISIBLE : GONE);
     }
 
     @Override
     public void setChecked(boolean checked) {
         mChecked = checked;
         mCheck.setChecked(mChecked);
     }
+
+    @Override
+    public void setSubMenuIndicator(boolean hasSubMenu) {
+        mHasSubMenu = hasSubMenu;
+        mMore.setVisibility(mHasSubMenu ? VISIBLE : GONE);
+        mCheck.setVisibility(mCheckable && !mHasSubMenu ? VISIBLE : GONE);
+    }
 }
--- a/mobile/android/base/ScreenshotHandler.java
+++ b/mobile/android/base/ScreenshotHandler.java
@@ -299,16 +299,19 @@ public final class ScreenshotHandler imp
                                         final int right, final int bottom,
                                         final int bufferWidth, final int bufferHeight, final int token) {
         GeckoAppShell.getHandler().post(new Runnable() {
             public void run() {
                 switch (token) {
                     case SCREENSHOT_CHECKERBOARD:
                     {
                         ScreenshotHandler handler = getInstance();
+                        if (handler == null) {
+                            break;
+                        }
                         if (Tabs.getInstance().getSelectedTab().getId() == tabId) {
                             PendingScreenshot current;
                             synchronized (handler.mPendingScreenshots) {
                                 current = handler.mPendingScreenshots.element();
                                 current.slicePainted(left, top, right, bottom);
                                 if (current.sendNextEventToGecko()) {
                                     break;
                                 }
--- a/mobile/android/base/UpdateService.java
+++ b/mobile/android/base/UpdateService.java
@@ -114,17 +114,17 @@ public class UpdateService extends Inten
 
         return Service.START_REDELIVER_INTENT;
     }
 
     @Override
     protected void onHandleIntent (Intent intent) {
         if (UpdateServiceHelper.ACTION_REGISTER_FOR_UPDATES.equals(intent.getAction())) {
             registerForUpdates(false);
-        } if (UpdateServiceHelper.ACTION_CHECK_FOR_UPDATE.equals(intent.getAction())) {
+        } else if (UpdateServiceHelper.ACTION_CHECK_FOR_UPDATE.equals(intent.getAction())) {
             startUpdate(intent.getIntExtra(UpdateServiceHelper.EXTRA_UPDATE_FLAGS_NAME, 0));
         } else if (UpdateServiceHelper.ACTION_APPLY_UPDATE.equals(intent.getAction())) {
             applyUpdate(intent.getStringExtra(UpdateServiceHelper.EXTRA_PACKAGE_PATH_NAME));
         }
     }
 
     private static boolean hasFlag(int flags, int flag) {
         return (flags & flag) == flag;
--- a/mobile/android/base/db/LocalBrowserDB.java
+++ b/mobile/android/base/db/LocalBrowserDB.java
@@ -19,16 +19,17 @@ import android.content.ContentValues;
 import android.database.ContentObserver;
 import android.database.Cursor;
 import android.database.CursorWrapper;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.drawable.BitmapDrawable;
 import android.net.Uri;
 import android.provider.Browser;
+import android.text.TextUtils;
 import android.util.Log;
 
 import java.io.ByteArrayOutputStream;
 import java.util.Collection;
 import java.util.HashMap;
 
 public class LocalBrowserDB implements BrowserDB.BrowserDBIface {
     // Calculate these once, at initialization. isLoggable is too expensive to
@@ -133,23 +134,25 @@ public class LocalBrowserDB implements B
 
     private Cursor filterAllSites(ContentResolver cr, String[] projection, CharSequence constraint,
             int limit, CharSequence urlFilter) {
         String selection = "";
         String[] selectionArgs = null;
 
         // The combined history/bookmarks selection queries for sites with a url or title containing
         // the constraint string(s), treating space-separated words as separate constraints
-        String[] constraintWords = constraint.toString().split(" ");
-        for (int i = 0; i < constraintWords.length; i++) {
-            selection = DBUtils.concatenateWhere(selection, "(" + Combined.URL + " LIKE ? OR " +
-                                                                  Combined.TITLE + " LIKE ?)");
-            String constraintWord =  "%" + constraintWords[i] + "%";
-            selectionArgs = DBUtils.appendSelectionArgs(selectionArgs,
-                new String[] { constraintWord, constraintWord });
+        if (!TextUtils.isEmpty(constraint)) {
+          String[] constraintWords = constraint.toString().split(" ");
+          for (int i = 0; i < constraintWords.length; i++) {
+              selection = DBUtils.concatenateWhere(selection, "(" + Combined.URL + " LIKE ? OR " +
+                                                                    Combined.TITLE + " LIKE ?)");
+              String constraintWord =  "%" + constraintWords[i] + "%";
+              selectionArgs = DBUtils.appendSelectionArgs(selectionArgs,
+                  new String[] { constraintWord, constraintWord });
+          }
         }
 
         if (urlFilter != null) {
             selection = DBUtils.concatenateWhere(selection, "(" + Combined.URL + " NOT LIKE ?)");
             selectionArgs = DBUtils.appendSelectionArgs(selectionArgs, new String[] { urlFilter.toString() });
         }
 
         // Our version of frecency is computed by scaling the number of visits by a multiplier
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..c2982ff31b95dd21d6e1b9b46abc3cb2d8cdbb6d
GIT binary patch
literal 3190
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
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..3e0d241c9e390a1dcbc2f3fa75bb866ccfd5a2a5
GIT binary patch
literal 2896
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
V&>7-#dgUM2&1Db%x^r;izW_ZO^;-Y{
index b058b7b04e861507a48268bfaaac51eaf4e588d1..a15957925b7a058a3ed88714ffdf4a22eec49bee
GIT binary patch
literal 3946
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
Z2LNt$dWgz8d~f&f*TT%kw8F$Q?q5nu@Qwfg
index d5f3f8d1e0abfa9c8da9be031da1dc5bcf6b2328..58a63b2bb340aa718d2c5aac0b43bc09bf7b828c
GIT binary patch
literal 2933
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
deleted file mode 100644
index 5d3516a15b7c7ebc5cba19b10fb5cf9218f59007..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..7c85994aba9852bd8b337b0a09fa5448c46af1aa
GIT binary patch
literal 1868
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
E0PP6y_y7O^
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..f57d40d4c56b2ab4f48f422732ab0ad3eaba3f2b
GIT binary patch
literal 2022
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
L^>bP0l+XkK{l75@
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..191828d50fca2446dbe7bdcd7c1cb6b5a0fb40c1
GIT binary patch
literal 2383
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
Rc;4bKjsxA9R%jO(|4%UO>YD%n
index 2a30325b355926c2a4c53db9151443620787d240..3bb54108bbd8268417c94e277bcf448addc61a75
GIT binary patch
literal 3603
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
CkZuJ4
index 1d3c9c989af2259fff59021cb4a6117d3ad8809d..e3b09f8b4ff249d880dd9a92f0d1581d4bdb488f
GIT binary patch
literal 2451
zc$}S9dpK0<8Xu;RT+5|gG7Y<}Vy@<DX2gtPYR{NlGCH-HW|mBui<yZ*#AsJ^aTF#I
zspzWOx~P;)J0*pjq9RNo6*3W0(H@<2&U5yD`r~}hTI>71cm00v`+o0bJu98f@-sEI
zGX{Y`rVM{tpl<e>x{VBU&(Ls-PTe$L?#qz}i6iB4TqywZ=8M+>5QdPu9tZ@u{P>u=
z00{&FM+t&Cat`wsB2O%Yai=gag-`;T8YC};gv;9q$RX>1^#TzYI#_uF3K8(h&`=B$
z!IV&eD1m>16bMRS1@jU%@(6sW7X?C65OoTKfSe0a2%|+ZqJj+ls+Xu+Pl@4B$XAGb
zBN_T{r#MVDgesN-5DX0M&O;!P5G)pk^uS=TNH+)yfkeR(x(n-$^dMreL=+D4Z9sL_
zr2I%?AdUXbmTpIeM#<$8A{-tU7YB<&!^G0{a3q01n9_klx$6+_vUri4t8f>|oToL=
z02xmzkjMpM5oBu5T_@foCqtprM-WPw%<qatvTuRXg$%CXO5jKs0xlH7r_nNbAQ1Uu
zv@AGY0>A?SnRt_wr^`pA^M9H8F?9;4^M)8873h+}ji!ltn}mQ!&Y+Q@x;HSsfKR03
zadadS=YhbX5Li4CiAUhkbRQJKn?UtNq0q=_9e>BAq6iqQhc|&v_rM^LzDRE>)t8E-
zqkPalXe<@)J<Vl^WOA;E2TXGX|KZ|)$R$#x09P)S28+ef(-pvu63fN1D6s@W4Z=cP
znOvSgG$mL(m7s6F0#ZRNz^6;aLde$$69s?c0iE#Illu^S&~$<?-kX5;fPUlh|DUMA
zb<V*5r(C8*x*D8XelLFA=6m}9B3;i&b<GjDRR#fpW~v!9?_fo1e?BAHK4jjVqKaE9
zf~{Iz-1M_EpsBBF7N+LfxESTMx|P)bYthjqY<5<$A?$tiELM-t*=Ng+TNJZd{?>fK
zLz{)E2WAI)FJ`{@i4k;Mm>U^c5cXjU&y!g@dK=BVvpf9#-F;yl_Xj^sb|w}T3AdLD
zqK{yIZmTYv5w3)*RT|tcvf+Ym37+#0zf1zWa*dnC@k3RYo_Cs~_I$Aj8fbpn_66m;
za@F<8=+61nv97$E?FI>G!?)%LLta}`BP2EiFdI-;sXk9uTQ4xQD(O$6IQee&#M&x@
zPHi3O;v953DN!@}<`nX?Pc4ioywwLey&<nF=Uj3@aBmv1fc4lo$!bo=ts>W1MVgBn
za%4-m6SX^u;nj@}u-?7sj8&tu6OU|GTI_E)R~~ZnqvQRRw%X8F#vHG595<czIcV`u
z0wumOcX_$7(MNE$e#1B=1KSHXNg5MEllyoKCHPPZrr{Ve0#sr0h6gHrs_eZ+Y3|vu
zt9>5jOOkkwnLp!jE-N+UthaF#c)vl~euKPw&)wwRvWga!dApBo)AQLA*V7fGBcPbF
zzC$2`nRxk3tFr#Pt4HHHTnyJZYy;29))&mwmM%;6ORT?ev48M^qeP%Mgv;9s4wR(0
zYE6{jcE1iI8)5hPmS?SnG1U+&3*6C^Gle|$3w!P4`g(WaRWK~vp`UqE&%<arv=j1V
zq^?hW_&~4feCcU0%yeYY-dRZ&kAhODdfO|*XWNwY+qPD{OuGtBP66*tzr4`U;Y|XD
z^GM52%r`sgC>bXis6Pmt&0di<KgtF>kecVZM_#xPiwFqIs}lNow#Aj&!OgEfxLi?L
zE*-9P6~>FQQ!t}RBjf(Co%5e%!N(FtR_AL5&W$!WU)A4c(2$gFg)b|ySLsWH4_ay~
zHod>V8zw)A^z0Nok6&~0<khvX(A}vyi`MF~8+T;Y%G84!i62rL2hHtQkJfE@=%}rK
z9KMUQB+)2(DN)vjc@@S_Fm{OQd&$x}<KIvcC_4K%)Z|oCcZzIx;sK|cQLo(UV=rAY
zOHcF_7Fa=y&NnMs?z|fe$gN&lei**=VbqO6^=q>7bnTYOiO`|YdwlbNljqM@<h2cO
zvCQEWP9|e7HpSYkS=mj)lakl<e>}cn{%5}1(29W;;XbW8Z5-5S6GU>pWVR=Roz+8g
zAuX`8uZ*>>oVm1jJi|Q%<GCRD=q1Z0?Nj?0+_0kV)seEu`y&_EXfh6`WoE8*zLGiT
z8Zb=KFt!A+i&dGmg9&eIj^tz8WlCF;T^?tKNRYMfMDJqXw-*!3oGwmy_Vjd&?M?~U
z^`*+_ne;<@Bd%4|_0RbELk<Hj{Z?>=+j7lgRm$*9nd($**}=J&?{pPUnku(bpQrbz
z-OIEuRlggX!BEx@!`$c^UTL){y<>yKTxJhafmoJBF4}YP5}wv3d0p<@%gZ%c>|0Q+
zviq9ZTPz4x;!MFXG+nu=y^fSPZIr9s?>3~f;039PpoU$_0Lu?sdo=MoNxq({9RUF~
zK268Tnr$|S`pwIV%|)&e5yw_}29&%u(UdQE=czGm?7!qd5|@XD^e~S-tg(*Cfl?f2
z7w=%Cd0k%-fwkrsXk<4S%lEPl{~8`s|HbU`0fS7S+TQ3{)tF`cIM!w;j-EZEcJ*56
zuF>?T4&k6*JGG}Jp_}ddZolvLvkF<V$|EE{K-!v1W2lG?VKWLdd+Szo>y6l#p6&`R
z$<pWhZmVw^8)jd*yAwJY{0EDBg<@<UkN$(qv$R@rWdGGY`}7e85f1*Z2^2JW1Y6hQ
zp_pKCb123*P2RiYwG(FV>KeWF+|-*l-pp&pj9ve&eaH#7o{~n5GIOdSC~psa;{E)#
z#)MSxI$y1KVRGz={;_*ul06$u+wZ*r+)f>^jolKNXt$`<GUT3Suw~W9-OO24U%#5-
dt)oRCFz8@{;U`Qrkudd}#PDU&&iF(q{{-q3{}uoM
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..c370a6c82fbd56e8e19ea4187ff47da76519cc60
GIT binary patch
literal 3213
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
U;I$HxH-8Wu?c6Yxw!w-21eJcC9{>OV
index 2dda75d16e014e71b1b43b3c872cf123c6118c91..2f981a1052636ac75102302c490e1b00da4b3dac
GIT binary patch
literal 3179
zc$}S9cT|(v5~nOhx(F_UNC;I0(jbr!YKlZ@50IkELLh|zNgxR%5tXV)5i!_hrHBh+
zL8J=;N)th&ARt8%q^cA_K&8E~D|_B~Z_obm?!Di4@60#9nYmNW`I20n_sPqs%ZP}G
z$m1O_Zo=JW<B^sWzP<dE28G)WHrAW%&LFcn1SUzuj>rfg0q`^eh2%ye5P9LPB$SAV
zco5aYo9*r7hzw-VOb8n?CR|#W$i_g~aKi|JAtW{+fJC9vt$;JtbwB`>Xa)2#a{@bs
zp-Dkhha*gq`w?f4z#}1n2qMtN8i3*=g$igSHUYq;h0<9_t`+bPy-4ACgAD=#{t#h@
zSONcZ%G=2mfMzgB05cPqaUd810l?uV5K}Wa9AX53f+0{4Sh(QE5L2WX90@fC{1`x?
zH71dabi?3&*b-7!z#uj|3<&~pI2;oW%!I+DfFKA2VnYWMYAlp6X7T830@s+%(%IC2
zA+Z9P)G#)cK?iKmgaAea+X@KWyaFxE$>}e}bk>hR2}1_r62d?b6EKKI18qvP*lr~9
zKTESbcwr=v8;Qk;U<L~FLDu;XQ~wOz5EOcYbYW73Ng;${7=aNq5}l35SOJA!Oo&t>
z5@%tKgFwtp!RAmf+yVlz09(Lt_E3Z!0*!@2VUSH7e}_dw5#~577K+1}nn55~h#eY@
zMMH2<dzd{8j<&Gd#Nz2JHh~^U+Qd@-#G1iP?a=>-MWUG`0-M3~U@$^AE5J2~!Dg_6
z7-0akI~-u>L<pqPHyFD&67<7Y5|bK9BI1|~8sLuzBdLGm0S@uMH@8RF!*B?!g&o4e
z6!-&6{C}bb5;_C=uX5RB32SiU_*d}@iND&1L>Kl9Q`j6=<yRy`M5Hg{F?Jr@zE6jb
zg{qL$qbZRTvQ4sU@ZopPyCr0}M}p6LW*hDT$asF%VP4`&F`E^q<2bFOD-9!G6j@d8
z15$PMn-eY-P^1$f2FdEL&UMGFf<0&wGK=DU5_zR;8w!WqGYGTPt85RYw1rkkEz^(J
zbYA8R9*drtuMr5BWmpm>&iCdCidR@`hTzAnQ%>#-Zb;PP8Rd(=DVv`v6_~FLoiXvK
z8(3>Dzh0g}xu_-=juPxtkb3_w*3NwGUYb1`wTn_%c>kvlj&03OSMzf-&V(am4a<L9
z@h-5;bk>&!vU2r1JY}5Xlv9emjS8KbgGdd(Khsm|&#$b3gak8u=F$rQ(vJLJYz#6T
z+8gW4MO1CKfRhf1H^eAfNS4m+9N&gLyY<vjj|*i<VBNK^u+En=l*(VyyUeog0iyW#
z+NO4BKYMR!R?s8P5hrbrPVWAcSl?e0&j{xYIJ!2asIRVl&M(5QM};HITe`0Wnq0if
zLrJ8La}CC*IxiGniMoiA`UZR&cKXY{kSi5awB$-H!G<-muH9I&TFRZF#G|MWx1OqO
zdEeCym+N6>%fD7=*Mg8Q#_abuc=5Gb-sR2yx|2tCt=*M+npz8^2cKDJMg0o8S(Pxp
z{`ii~<j2?3OpSZ%#qut-$%8zVp3dejLH_eSReKH%78Es?ys11$yOUK(ewpz`uk<+g
zZTQ=T)6nj^5#1;FvPHTQXLbd|4zUEi@oEjuX!2CS>d+^)Zxxqzj@^<Qlcbha&vN8n
z)J>8+d@3rcW2-^#SqE>OV~-w+I^sa40Nao)j|3{*B*a7;dJ4$AloZ#9Sve^|Q}b(e
z&(lv<PJFbsZ>j&}30=)3OzF(cLT2O4(t6PhhOw$>!(R0L1eB=F4Oq+Upu#-sx!rqe
z+>D?}B+I4?#Us9actPEV+Wvb_m>5~-;qZm8lkNt7^wkG9MF}6JGt|s-y0R?|@^c#p
zG&KizX;%(Rn_n=l4$=H&d|P@ACm`M6<K3q5=e>aSIG^euQ<*uaY+}QVd34t-qb^!)
zm_m3b7e;rQLNh;btXKSho~+O?OigIO#>Z3YvQRf(KytcKC+-wfd=NJ?4J~c9`&#z>
z!NdNDEn0rZX5z=&Ya~@sF7+o9{4wYth?L}vs@wf7*B478wHGwN*=1y>$3sf8l46X>
zMtn!hjL*F7QB!5&<ZgS6okjZ;E@~;^{^Cf=zu<xXnZ>awFAp)6?+?w>zLu;{cZD1y
z^Wi#a<ytu=m%>`*LZP~H(-mVOzMj?9X%Bzmj2?~<tXl8gbJhN+fU7Jxh3X!fQhP^)
zMJdThT3hw;CNx%hDWv5C&F%)Z>>535$+-bda!1~~k(SQ<wUoBE)t+7Yw;g=X3}5)5
zT+wu+3Dz!#fK60(7!A9rk|t({(jJ_@72M!C1v?sbqA)osTeN&@{#T%7_qF0Gvhw-s
za}@yAo^3q|7kVV(MGwcTIod{Fcw&%D-A6WT^1dDQ?P-^2$vAE_uc)XvkKG61p6y*!
z@`^fEyY_R5>WE4nengI_o?aT=vt6RQH?(2oc6!Sg#xDImINWDI&F%Sdt50QnvvVW{
zGmPi#3JQpsl`1kr<FKbwgWs+mEG?eA*SD4;uxb76R!VDehI67t*9!`3Kuii)FS|6g
zuGqwUib=y&w=18X?KQXiE&<myaysii_xg_JtF(+%DFc8cH~n!}8-HcCD(Bd_-|(<{
z<2V3QXK0#)tu2{fj=yiTqzfx*Mnsw(c4_g5bhhot7~?+6n2i@*UoH+hG+8IMkOhH?
z{%)YT-EPQqL9c3{O0O<&?70JHshBewL{y`@wAE?E<kl~N$68G;ri7#NH6v3;<Bdx%
z=;8csTuPcm=(+GU)sg+0G7^J1@)-3=uaA~xK>iiOQ&)x$9c1w%=gxV`?w)WcRIs=o
zFnVQN1hQ|W>_dAFdWz8;u)oM?UnlhwFk998sbywgtuKE-MQ(D3_H<l)(@2uM)pht!
z*PbJ{g&MyQYZrfq>$Qnl9NpVJ5b`tcd7++fDe<zWR?zLMzgkxZMBpdC^k{2K$sakF
zH&b1IU<ZaJ8#^Am+)?_?LjAOL|2@VGp+u$n&Isf1(L~SavS=-8TinNJ->TM+#$RDK
zCk(fNp<AS46bocyB&}|1%-xFl);gkhOJdKykEtE+U)y)qzVlLZ@#=2%0zFt=iRg?y
z(l>N)fII)Vj^Jx!znf;K<Wnwt`uwSkN7(wZ8)a3WyAGU137|e-kcEXIV&`rxkNLNG
zB9wda(=KTV8K7;xxlu6m&X;<tCkq>g?bc^Km5N%_@;-l_-_5Y~IN0SnHpcFMG!}g_
z?h&mpw|O_Cs7Z7z*0ni1J2|a(0<3$t8I6vQ7nD_0Ow}7Y6CXrtmGpTX1ew(g4!jC8
zE*$n5Rjp7_^<CwJGRZIY>s#8+Or$R4o!3u~Op@`))Yk}p`*Lt_c?Iw1cgA_8w727l
z*f;e~$}=awj;qQr)LStIkJltw(f{zcF8)zg^m<zTWyxDQ{NJCsqwZc4G!DOY1*>r%
z&O5Y3U6MnNe3F#x?3L(m1>OFYzsNh_uJiDar{t-Od==-au`Bl@_y-<nU2)~}#VB9!
z&qed^P^L1V3h6UV(7y1R{16V{o#OEJoDkE40)=mdde_UTRJyK){UO&YDoBAK)8}|e
zg?~o?H-3MRh~8c+{rFuc8_ztxQsFP<6FrO(Xs?RIKy}ZZw`wq|VVqZ;tMD`~AE1WJ
zAAhQJwlT$Fo5@jlSwZFN_n#e`FqPS=Vy3-{W!5lmq<=lYU`YoY*7g{?=X>cV1=fCR
z5>S6Kwq5s)!X=&>)+NX-V1B1`qTBaYO`gW!nXT;E2MgCRWXD9~*z~CpPz!%OYdddl
gb6(_q!^en<By1m?HXJS)+W7s)W1TT~?fv8a4IQ+Mp8x;=
index 30434d4cd7d48b517d64fa2c7e5b225f3539fa03..78f882baf034c64fbb60c02d950b8a77fb7b65bf
GIT binary patch
literal 1809
zc$}S8eNYou5Dz#iA`}o1h1MQH1qG5^5<(IZn9COg3@{KN$f$(m0s)eXmxCl|{VGtk
zejth<f?7*OK+wTr?N|j7QOh8xRirlHR0VXXR6#|h*oy*oTE{>7X7AqHz5VU(+mE>|
z(UGC{w(hnB0>NG!CWyiJ5X)mT1Aiy1a_q&o`Iu0K#Ud)qAV*;Wq(o9+K&+9c!ZEO1
zX<B^+<`4+e($rEJCX*~<D-aDyZqXqbH9CT2aYBqbxgrC`fD|}Yt>qGj&NLDMwUSFr
z2#`=DIzF7H4$DE|*qlhIA}2$^QW8Ug0gjQ48_>X*958A!wR*OZOMGjWjh`)IG7)&I
zf@N@t?}Cy^q5(dF!ax9t=C7cDAi!XdKzaa!0r~+{3P>eWaANp_banuPO$`Jl77_P`
zDpl+lfoQ@P&T)xp7^Y*B$p(XgWT24{G?fgpSS*VTD%Bs?@YkEPnB3^E)q71^5Wso`
zs@7p@L<?AWc?yz+af!sqD`<2Q$&_KOej-tL%E(5!jtr70WQ~SAsjbIiVAaR9^-_}#
zCda^fBnwsG^-y{J!_~*37DYT7b`+|{iz3eyAc`yvti{9vE)oAiQmU0~5i?K(f`N2O
zAeF*kf*_N^q=|S`7R2HUsZ<&`Y2!m!J{1b21n{XM5j_9|g&@S|3;Cdk%A@gU3_cT@
z#EP|gOs-YHlUVh8Ecj6@n~%bB3_+y`k~!G{(P;>V=+h7#z>j4BJ`%Y?t+fc2SPC=|
zD~zhMVWkK~G{D;ov(+DnK*aj*&3P;yO~ev1Ar_NPoWLsoPu9qIFyw!=%cKbJLCbNf
z`Eh1yd|)j;GblbB5oNXe@R<t{3m~cS*TMZA8P1T)rPST#K~=1OI(e?JHb%hNd{@jd
zIbDkv`qus>Uw&tC+?el3e9P|9nZ{k$zqE<@-fg<DB3=^_!5jYep~Lxf$lP${>f>#Q
zyDjUNw(F8x_a&o+-R0$jYkSrVD~h+Yu)G^ett;}Ko4q&|>f#lerG*Q(2oQ6(Rri`h
zpG03^H1vB9EE@0}`0Tqq$KHT}wxZAjV<!vmG;H<l2z{*`$_t9z@OYE^=F=~qA6<ai
zkIWsB?Sd1#vNrbDoLEmte|{L+8wYG-5rb@UmbQh5b$N|%{ECv{^i5x$;HXC{@;h?}
z^PIK2{fq|%>+jC$Vm;|ol(yQ;0~966gv|t|!D{4KW#EG6p||xzBlliE+P~9zXr?Co
z<Po`JA7%CUrvs)adfn^u!w0??32Tw9{JC~*>6l|Bqa9k9DQZgWlo{yp2@ivZ_DLnq
z`Xm%AUNQF6L=;su_}MjWRW!}-ly$YAe`TA`eX*<zta|n|YpGp9+Yz_Q%EgM#>E~>x
z>A=~#b?zh8HL1x7d7PoM%So>G1??5}Cuy;(!~a0?<;`>-Vs4rBc0;zqU{&=Ax0*}s
zV;65RBIW@_;T8R=%0sg|<D8E`ttCDov)qxPft%H;rdXcm;k<yu)sOP)PGz~;Qx29y
zRnFl<!bIO6$8%lm?4;ZKU4`o0ICH)e<7Q8Hg5!*m{pFF1`&219bB?%tygvB0qr<A4
zYR_lEW8>iEx}pO}<2B#CXVKt;y$%nu#n+zHH?J9MP4H8``e9wEU4c&4dx|mY)YIEB
zY_s#vcNFK)(fOX6qBs5=sH1Bs$8+FiX|5qNd=u2|M%bY!b~~4xXp$7smqd4)Ys$bB
zDCxIbhMPI*t}FY8O)0S+?oC{Cc|%bP_u^ThhhJJmBKKg@WxLNa+321d%~m|$epBmh
z9;tYKcG4=8W)v4<K69$>bYZ7WJ}xmG7oJ?L&kyQvY`RCjUUlE=27T{cW^AM}&*eo=
zy6b`=!TKocY5v|njoNN<ht8}x?qc=^TfQ#$@J(ql1U(BMZDi+$8ZC7E@kqi3E5ed?
Va(T_7wl>R8N-T^N)bWxx{SD5S!VUlc
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..02d097104f51cef4f433bd3f2607894b691c88ea
GIT binary patch
literal 3359
zc$}SAc{r478z=ixlp;nNW2?_Ht6|1c%#x|bHbjz)nUSg4%nT;mNcOemv?)s}BB!z>
z$&v_Vq)nEP<%A9fQ6%ac=d1Ib>-)az{P8{4`@YZf-0$yq-}iGb*Y&>1uFkvGD(fgq
zNlC3GIAPr-^N!V9QC{-&I;8$iGHLU1-h2`}kRL|o(xe=y>;M{&z$720xzothW5G{o
zwo+0uL39sqzBh3%n!;vUkXJDl0wzalb=d9@aLAOSG(IqZc9_nx15H1u2Lb6+JCK(p
z5kll(XhC$Ra4wA$?(9JcKT1JSK|Ab$wgR+70h7ij0|iV5i-#82f&S2omaJFBU=Z*R
z2>+-Z=wD8G6J3EAHkSspw1AsaAW$d}iL`(sERjg484w16!oU#8g*1mE(3VIv%nJBp
zfF#zq)IhX57XQPRWM>Bo;`2FZFgPqM%pweK!R8(YLs2Nysty>;T!Jv?9b@sy0&^D6
z;HL&GjYr|qIea>s1zg>e1K1&aI}qsS5ttkz@lVAp-j6^@LIxI)Ibf&-1k7ZDf1-JO
zcUs`zqj?_3I5e<3jmHk*QY85ZH290Dzo)JOCElQ2xO7QU$P6r-62hdh_ynvSNb<&l
zN~fan)>e2Z)CvKyf<chhP^dM;8jg2_p&U>c91I4B{?zfmxEPot%-R8IjmIM_p->#u
z0fWI|pm>-g+!2n%SUddW5?DMwnMI-f<kJ7mwfb8w8pEZL`E0HSo6Y!H0j@!8KARWB
z<^VAyByby%Orf(@1>08>^ut#gmmW%^;<;=l@Q(<i>Hot6JnFws?uc@P<54(k2b47e
z^n*+Nf1(DKI0OEVa``Ee)Zps!&*GPC{%ju_OVTr3NpooLiPDskQX&$t4jzKu$pgn2
z8@sfH56W#Ky5md>)`f21=x<Xvj%<#ResN8fp-V|b`VxwtC+%}{z3x%`aaYmn;!WE;
zNk*Poh~3IJ^mnIXPX>^<&#(E<tj9#gNK*hU3i6EG#Lt&|da|dc0hyj7-Q{dD@?5L^
zL}5?=vFY}&17SioBl&T_<lEko$pd}vO@&D=>vKW&xX6^n12sJYn{R@~SCJaMQ=%zn
zz_%<JTbbvByq)yT#B)ZPq|ONiA2ZPqN6J~HZe>%qY>i5da)tQV*Sm3wBT54$N}^`D
zlD^mp{Gdjj+~Qh@$~IX)%~I5vmnL+8Vaht=Ufd}6{@r)Fiy8LdH67BV<5N4~GYxMJ
z=L!Xnn(UjCZxo*!UUKo@<i90EXftDca(g#JG{lD`wp}NvSPKEsLZxoh5!H4#)yV4L
zxi?G=(C0L`g4CEv%ZIP<!Tp2qEr+B{V?aQ=XP`2ZxW&yQ2KMSRYSn#WLBFj3*>z%L
z!j+ulAzQ63a}i6c-;9u)|2W{TOWHGDx6O+oLri6?856dX=W?<E@LkO>1x2o!%#TX(
z*Qjjr=6-{OJ$co!y!?#qHx^<Lm`JPi`E_sSO2yiJfPDMD!&(L>&ezBvYW*h5K;Y5^
zrYNIKHWk^>+()NV`k$@w8{O}L&>^34iYszETLks&qN!-eN(1O!w{)k7{w;OFnoc3y
zVV%|N#BQsdV|^75O=d%o&kOcEQ~MMoA|rAX3tBC7(sdq4J8k+R>`k(6SF4fJm8Qn@
z<tcQa=5H^2ZWfG}%^vU>&R`lD_n*HZAY4%={c@*S9p|PqRObB9sB#FM^d;Z9@aU27
zrE3xEKbXsPs>#bp6VJA0Y(}Ig`8}Wg-mW2gx^AW5cUyCLl_-6;M<*JjQe!8Q#!aiM
z(cePFlOINdtMyEr2jJ6nm-m-*b6U#x;XB7$ZI9n$ju_<}n6zT{pcVSq&P|v&M~4jy
zcUoTEyIK9wyGJqj(@W+~?FQL<EHld^THyU|)+?XWwtzNBIpIM~jhZ)kz@@2zU_Yfq
zAz2H@dSsw;uhHGbr3(!B-8uSJVyWHHtp~R19#-tHU!MNBko@wZW#^_uEi=(n$J4qA
z&l{JV{NlT!8gIES)-)o9G44Ssr!~!|exsLd3|LvItydVbT<mr8p07%5QNFsBfPFiJ
zQ7E*0o$Jx?DO+0`9&LK<`W#fL5_j%ep&)5&)bR8Sx9m-sSxb6T(nN#nIF{L-+_<^d
z{Z8fUGeL+%sLU@dm^Du!UUKc)Y*oXx#quLM$rTrMhN6~o)eg;u->ywqo8%Tl*;}(=
zVzO#cYj`p1(S~>F3FU}$qvK++;KXQJSMCKFo4IJu_b;@F8B?9dpN@R*2h4o^Ox90G
zjZrzuV4}W1&Wa6@sllC`jX~LJJ+tb3dO8yMECF8Cs+JM`dDgkUBck17*z5Loant*k
z7hi=46K}86F_%rfQBW6XgrIJdaS)!>pWSU3KJ=)^>iPNny3_(MuHHdXB#pz#Te~C_
zU6^y<vXmgWxnnlweysY3aLg&SJ%ttv{9F@D{jl@DG$r(%(me-wNhw`(LY!TY`>nV%
z^eU?1q|fO}Ls|&t()}YLZW|jiAj?sr*KPVs>Ed@z8e7&q339#(6yRlvPYCp);gsJf
zr`Buv-l|aTqz<3*Ai|>yBBI^Z%#%1+pD^!|H#Gc`f<^m1pOVQy^A$*t#ifJ3LGybJ
z5jRu!<W!k&Zz555=^N|KD?ALWP``nbK6|yj>~pA_X`Zc4;US%wiEBx<@%t}BE%AjW
zJKm4idEZf1S%0RBL=7cfH)d3If@~Gbb6dz*q33*e<~Cw9A#9_u5i*4<MW6B!*9J_6
zxt`gOB0sVT(hO!OW)**U4;>g2Kk_NMQ`(Ox^?LMlMJZ(h?Vs8>^m;cbIR%}5C1ssG
zTmFqPOjCQ@m=t2aSy^|OV1XxF%_s(EGUPo^45ya{DV%#o&LC+oPhoQi<XeV`Pxl(t
zjk$YizkKW++hh~NJuPL5y^yjY?uzoAJkR4wjgR+$vc#|0o98qJ4IXB<!cX-S_4j8h
z?6nlMmgtn1Pv44v(MHix@SKWkE;jEg2xi!7i4roha`SWnD_Kd;XOCzA2P3H9n1Gzv
zCnxQ+xrzUXf8!*4@Su(X`C9dK<Wp1#r<mCKpicAGoh@dZU7%DFb9<+oT%_XVHB0ln
z2dab8F{(%ESXHXY1^JJ?-w6Hla*@?tuXP5>-m8`WUQC%A9pJI`t*vlMZC>jqyI;M0
zsb!PxtWFC)<JVYQO0B%|@j^-bT$P?uykn<_v?dM;NVrv4R5WB)EPK(Xy5Rm`W%#8I
zE6=p*kbvHbw+o^iy9E^EVfcB|V@*fV=51yrahd$kitqRDEqwIW6~E8UyfnAx{L0P;
z`@HnBOW0ZYsbhu*8NaHTKmBfCICM%jB|SO#pxcFxX*<`j;=uEIO|C_4g~HJBL@k+u
z+-|cchfw0$tYQk5xo>pKewBKg!voP(+o9S`d)!;Q_|?(bT@mTZru~LXRy^MjgD=Zn
zJ_DyWZEOsU^gBpytD6(Ms4Hn2B`?C%ojtRh;iK?{ctZ|GIiYy?(^ad|d_}yIkZgTd
zV@u8#O!zTTN&DWx?8}P>KYl#dcG~Pq`n9<EebPf+9fd)`YiP0f&uenxd@1t)lbn0o
z;^hL#GR?Lu{G%)DU0%TKw<g{^f<=raWc?O9?z?C)HTCNYKpyC1GS(o;NSD;^aaC5t
zO(WUl+f{T!@`6e4WK)_zikVmLO-J?&RKFdYTiT`i)-Ea>FF*MhDY}#6s~BH}S?^1Y
zt97f@aI~F%>-{O@?$^U(qO-;>7t6Hcz-p#tAys9Xs`7q2A_~Zveh06Yqw4jBu1DBL
zLH);;<=$lu?g!vudY3pb^_i_T-Mz~%nm9T2n*pr)ZpX8)dqtv)VKh-|pKO;`3}=3X
zM@)~H{kq9foWDH5U!XFLYSSU*UwmJgF7(#}52%-*Ai(!gQC@Ag{iZ(XA+-ZHbWDx$
z=04sxvGY8DJKho2-Sw{H{`~X&>t4fY*R?VN)0TQ}ZpEu+4P~)!#5{SsGfyq(aSJ@W
zir_0w-L=SBQ*={S4sxEpF6}5Gj`Ip7G_8ES190uHA1o^_G15}f4Hq1AyD~1X{<08o
L&e&Uy{;~fA6g<nG
index 483edc20f9fd6e63cb770359b566f2944ce4dcf5..b8cfc99673363feae00abe5b3e0a8d65da3d0f75
GIT binary patch
literal 3502
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
G*nb0Qk}rh-
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..65087796a727c35a51cce8f52f4fea946b9d64ee
GIT binary patch
literal 4413
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
index 958251d6b48ff5844854e22f41528f90209df545..30eb3592b4c0d9f2fae100a6db02f39f6a2a5f9a
GIT binary patch
literal 1949
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
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..7f344814e0ae7633f575a1a6eb20170c23b95e01
GIT binary patch
literal 1114
zc$}S6PiWIn7_T_StPU?8rUQM;DmYx5zO+r7*gD#@*($cquDb5FG<j>|mOmzMwi`Iy
z#=yZu5D`>l;5>?l9o#`g@#Kz!spv%y&VvpFQ9SC)Y^Uhh!AFw!zAxYJ_kHjCGuxZ(
zZgwAVyIij3bWbuz_EzU@Y9!w)t6$HMZ9h&GaGx=RE0Tp=am6Sikk+IU${|S^JHL#g
zF4xYonlIo&<|Hp0non|Ud{xbKIV;*#H6?i%VNgURRgY1hA3dRfs>G=NP{yAz1yojh
z#x2x0p3TeS!!oB(UB^MR$`b+&VF^^V5#8piF=~UCCuc`ZQ((gc567rqK@~E+Krk!>
zLcV}k_Cp9*)(3+jmW7>w@k568lZW-fARl6RCJbteBHk=zh|eX(nlB>7s4~VTPt%o3
z#a9XV468&#j^i8-hVc>$uRW$?sp{43_Buln*|MdYST%Iu$WqZ5#W9MiUqLf7nN4Ed
zt|f}3jIK&14SjxE)9AXjjdN&dduuyCW+FO=Y-7}tNj-+z|8TWE)G;K{@TV-56h#_I
z8uF-ybevAcDDuars0uGe!Xkv>pg+v`*$9LYe<UC#7%t8UDTWEaI>%O6f#E`IFdh=c
zU<kq#j0-|afFhF!Bm%4uiPy1d-NuqGqdHdojSX&#<pm2#*s$`3F;ee<-m-xWyKI<1
z=wrc=j3leNqv&u7RErf^>II~TmZ5=-4D;$15s2KsH&1YhfXJmHaV`?1YFOoevPP3&
z=)c;ft|C3?95<Vv2%F=BbTTs*8IGmJ$G6B}T}~(C`RbeXm#5uNK~v*9_tp0|`Rk>R
zS#59YdOG-Hxn<Xi@T`04>>c~Y{qkYRK7^s3W6FmK{qEWv91MSYb)sVd#F@dh$>rNE
z`#kc&22Z!%;weou-J3brIX!=<zw&l=Y0kU*OR??w^i12)#>r@3*Pa2`q+BdEyeNHJ
dnqL(z?Qnfx^t@hJxi;WTdpea(K1d8s{RFnFWCZ{K
index 19f04294bedb7e7c7211b3b77ac4d183b0839e22..b87dc098e7c12956a9d1062144f360f1236d2dc9
GIT binary patch
literal 1054
zc$}S6O=#3W6ppMG5qs)MMHy09D!54|+07=QYuQaUcA;C>?TU+fFq_Qorfo7YnYw9D
z>Pf+ZAP8Q(^dcU-co9mGda@{Z@uFvs{#-l?by7D~wDjPR%*=c9eeb<_^WNRY?77h+
z$B!@!Gg_NAnshyp{D(*Ay!!t8MY<d#)i#;KT{5sj#FQP}L7?VYJ=8>&vwVFEO)^ZT
z@3z{cU7yix>~U6t;bJdfk})|I2bR5n2<V`m>zCMX>n~a0Iwkf}p)S+|9rfMml@QIX
z%(m>61zUC4sk2}*)~Epw5evlLq918-iQTcQ(S4%kS+D~k3nlhfQ0;mH=r}~6z)3k<
zfDp(s2lEA4hG&2%K#>>dC+A>ZE6AEy1jE5nZ=uuGnua;_MWqtkCnV5#elQqt1Bt_7
zkB6$NCN@MdM-jPb*(X+<^P}<9f`KACbOYjIA0)EX!AqpXvgsAPpkCiK>_@{y(UkGA
z74VP~c+cZgbVQn{yFWT=EeD8iq6jaAHhquo_#dwJrzSuejdnhC>7!VS2DX<x<dd3F
zV(AIzxQ=EjMH9keUMPx!tU#y;iey$qwXEt@QIue6V=t~QDyA-&ifQHx5LRJX*Q+`-
z#fnssWL+tz+?pQ|%ePU=b$@e<`*JlsL>9qe3**JK0vdfxaMZ^E(C1_@QMYW@PZXz<
z2O7qTLiYx8%n*BEC&QY%M+Bz&@69V}MKaZ@QdX5bJLEe5lQo_O!~az-sfyNMvfV9y
zD(too@@db6v^m~w-ug-#Yo=zDTk*%vkL~TL%my=-Il1`+tvwt)^`?Da&1SQ`3HbT#
zBPnZK8F~KT>bg1hIyqjwEYE*vJnh`cZEPL7xAw)HXKpeX=EbX{2QEB5_$lewT6NZV
IR=IZjCkx|BmH+?%
index 4c79410772546cc90f53a496d2c5f82f4c5ec94f..fd7993f8681a0b42e6c00c2383a4add5201e0f30
GIT binary patch
literal 855
zc$@)O1E~CoP)<h;3K|Lk000e1NJLTq002z@001}$1^@s6xaM`j0009XNkl<Zc-rmU
zTW=aM5C!10<<@XpZdo9NLPAwis<Z(`x&8mYQ>hPqPG_Yv(y8lBfMrQcXQlIs$6q}5
z3ZonyWq+Omj6L?)V~;)dyw3CP0P^ZU?*qtQAlC)@;7Q>P#8=n4kUInOL1}?SO39P*
z9^xC9>vAz)!pj8aV!2R^Qb9gaj`tWIS8HKZAK-I%TcP<@7DF*oQgjumA$3Y4$M85h
zw$^g&K`arTyYe<hO9Lx-z!<7VFilA$X(8=BM#qd$M}r_4(1j~xfpgK)R+nNaR75}>
zNmtU7oFFmM&msERI#v(kcL*{fK*dX2bz7sktIP$f5muX!6lNe9N=_vs$r)w5!|>;h
zFy0X3E2tv239sgXOIvN;uXfVVc$N9UT0ejNehMvEc|N$b)%K5<4^5@HEg7tdfxCgC
zby0uQf#Wvi)%Gl!Z<T3V{<Xp|a6eGAKEd&d^R=nF+FnE}(kWSW!IC{BP_&T;u1cqB
zaa%NPO>N6MHqj0?*JQ(;1d296{W0bfVSd`C+@fovacfp+m9=rCC#TaV$t+N`8R{Qm
zK5bfU6{khlLi4p|4Sx-7%j9@Jm&^l2o1^|SYSRewOl#4N(6lvMc;C@g_F1wB6m5a}
zb+z>{zd9WVTcf$H8DkTjO1?<00!6z*{Zq^*_O$3$XuO{_v0-X!UP!)5t^-B8M*SDm
zq8-eW_qC1C^bm0OvjMf{H_0kcv=!>t79Du@wUTp!Zj8qJ*+g4YauX=p4YlaR+1GZ0
zriZ`@-fgBheZEU>14X+<{d3Ic6!X)=AQPINocew?!cl!G`60Or6zvZ6Ut&HZdSBBM
zbSt#7gBH7ofaD=iv<J^&5Ibn)ENBf6TJoN=lspEC_K5ly9<;_T(e!m=hQU^WqpdKH
z8NGJof;K)-w6UQXnxPq*p&6Q?8JeLPnxPq*p&6Q?8JeLPnxVZ7H2db((DFx%9kfHa
zSefN<v66O$w+#FWZ<)sx9^bI@FNXB8IJq~x4;1Yl_48#hqwV}>3Fo-ZKZF~0{c+#M
hKTF8^{CEFi;t!ej^XTT|Z~y=R002ovPDHLkV1n7xmyQ4c
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..c821b190a8f449934592f940eae95328381b09b1
GIT binary patch
literal 2262
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
BtWW>|
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..5d47a4a1a7df15f60ec3f33ee6c846e54190e6bc
GIT binary patch
literal 2123
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
M9zN_d%!rhK1MaO~u>b%7
index a4b1e6a56bb0eafc04bbbe986d4768e3419b1831..63dd48a1c6b9b8d8dbbdc3fba87f5d0f62b999f7
GIT binary patch
literal 2721
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
index 608da9a77c05165453c9b32b32bc10132f358ae2..c1e0e489af22fe4f1a3b248305eba48e12713e8f
GIT binary patch
literal 2177
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
O0&lht>oQ|+(!T)ZM~hSd
deleted file mode 100644
index 2551f68c5f3c2ad0de07729d9a8338d2b8489288..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..bd106e741f02523c89f4abb1fcfb70be20cfdda3
GIT binary patch
literal 1695
zc%17D@N?(olHy`uVBq!ia0vp^S|H591|*LjJ{b+9BuiW)N`mv#O3D+9QW+dm@{>{(
zJaZG%Q-e|yQz{EjrrIztFlS_jM3hAM`dB6B=jtVb)aX^@7BGN-jeSKyVsdtBi9%9p
zdS;%j()-=}l@u~lY?Z=IeGPmIoKrJ0J*tXQgRA^PlB=?lEmM^2?G$V(tbhjOrj{fs
zROII56<bx<DuK<l0<uBE`br95B_-LmN)Sgy_y#CA=NF|anCcnpCL0(UDwvt+8Jd`y
znHlOR7#SEE=^Fr%nXaLUm8qGPk+}jCC;@FNN=dT{a&d#&1?1T(Wt5Z@Sn2DRmzV36
z8|&p4rRy77T3Uk4Ff!5ws?aU2%qvN((9J7WhMC}!TAW;zSx}OhpQixgCnn{Wme?vO
z!Mu=L;Oh%FIIkEQP{1J5uShJ=H`FuG&&}0`sV*)FN=?JBx;Uh=AXPsowK%`DC>a<Z
zY05}e;nxaM2y~5=e^DkdQWA4q@{>z*Q}aqZU2K(rGI}YQDOPS4=5B_D<|YQ_Mh0dU
zhK3df7RGK)MwX72&aOsA#)dF6u<3PlGBhwSb#``hGch$ZbTxEzc6N0(bTe`?b}}||
zws3^$^~@_SNz6-5h3U;i=yk%Y*UGslHL)bWC?r2W2bKZ?GV)9Ei!<^I6r6+26f}Gj
zlQZ)`0-B%*g1R-eD6=dz#jPkmR{<QtR+(5_;AV;Gb0<qDV>e4z3r9-}6D6qL6mmjM
zALtl;wB!O40;WL_6Q1~i9C-Fg%>(9{B4FlVV(TbpU|>4y>EaktaqG>D-T9XtBo4g&
z{PWF{l81_pPKnGdRtl^tMh>b00?b0|S=j`HJ*FnO%}sd7pRn@Q(x#=-NzObRp|PhJ
zxSe-TX<x+`*cGCA_VkVN8ok2T7Hsz|cdlObY|-TRetrAr@4tRGeXilMw{2}(VlS~R
zs1_4(7k_74vE{zWNfVy+j@v~xSzLG?bG`OQRoW+aB@MF=TaMj$D;pry7-u9<#d>|C
zOMpjscvIo(t1b6Fi9db#a+h1j(wp04*NE)&;m@@=v39CgWmet0!#oVTH(BVOJ|=!l
z@BaDc{k_|#`{-Tx!1m$u?@!(hF?$MMuQQptuhw{V^PDU_b0a+wpTrAyE>8UP@}jZN
zvv;L`pUH09_iyza6=k+5dA+>Mn?J;aJ)ZbEzV}zMXgZ^uW$c0}oB9kFe{!s~oboN9
zYQYtT&^orSPdjGKbMx^RojH$-UHERDvDi#+=BE>c7YE)l3={miPex1TtK#ysuBJ|R
zKc6d?Ke%-E=bc(;QhQ}{hS-Fciw_0LpIht`D3@ycEU;Uk*tp-z?%B*`oxvF;zxkbi
zx6OaC>))Q*U(?DGw&i|{xZ`f^YruH2!s+P8xSI9h0yedp@AlkZ*UZ!WMnqso!*SMK
zfvfAzrnGZ$D1Io8m3(l2vD{Uuug8SMU%YyC>hfXtPr!1^O;N@8&%xE)zhj@=lhP=z
z%w79Q=iASV?Trrmr`f+_w|&pf<;2m(GqHEwb+c8a#|taCo$o*4eW86I#Gl1Bevd|u
znMUb-#gv%dkK6mtrahi?VzZs@nd4DR-;>rY*txFygvsuy?<?c>#V_UQyIUbFE3_r!
z=B&N|29e)Q`|hV1-CSFoxB2RoOJY1LW*h%xmwd<&ptGs0xl&Q%!Xa4)f0pkDQaImP
z&-n5tB=m*-{xnNJ&NH=M0h;Ou)4dt2Z;N04EK(eAr@yED^i7dZ`$W%)UY;AvcK-wW
i0_F?0Y`@$a7#aL~4@(BlF}wq+GCW=VT-G@yGywodwTBe|
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..b8b535bc3f6228f7dba91d41879ecf5d9ee8f82a
GIT binary patch
literal 1846
zc%17D@N?(olHy`uVBq!ia0vp^S|H591|*LjJ{b+9BuiW)N`mv#O3D+9QW+dm@{>{(
zJaZG%Q-e|yQz{EjrrIztFlS_jM3hAM`dB6B=jtVb)aX^@7BGN-jeSKyVsdtBi9%9p
zdS;%j()-=}l@u~lY?Z=IeGPmIoKrJ0J*tXQgRA^PlB=?lEmM^2?G$V(tbhjOrj{fs
zROII56<bx<DuK<l0<uBE`br95B_-LmN)Sgy_y#CA=NF|anCcnpCL0(UDwvt+8Jd`y
znHlOR7#SEE=^Fr%nXaLUm8qGPk+}jCC;@FNN=dT{a&d#&1?1T(Wt5Z@Sn2DRmzV36
z8|&p4rRy77T3Uk4Ff!5ws?aU2%qvN((9J7WhMC}!TAW;zSx}OhpQixgCnn{Wme?vO
z!Mu=L;Oh%FIIkEQP{1J5uShJ=H`FuG&&}0`sV*)FN=?JBx;Uh=AXPsowK%`DC>a<Z
zY05}e;nxaM2y~5=e^DkdQWA4q@{>z*Q}aqZU2K(rGI}YQDOPS4=5B_D<|YQ_Mh0dU
zhK3df7RGK)MwX72&aOsA#)dF6u<3PlGBhwSbun;rGch$ZbTxEzc6N0(bTe`?b}}||
zws3^$^~@_SNz6-5h3U<N>veX+tJli8C^fMpzbGU>KL?fq0y6ST@{2R_3lyA#%@j0z
z6O%LZKmwYe2!gsbwJ5VJHN~wcKUV=9!d97BT;OJj>2oJbCu28DR|`i=3lk-%-V|~|
zO&{nOeYE5P69T3|5EGvGfgE`DNzDW1nId53NV@Yx1(@ejJY5_^DsH`r@b?f2l&ClU
zoK_b0c@o#w*`*UFeb|uTB<H2k!?AEvw``XmtJ~be!Le3XRXa{}UpYFvq?=Fhks@>V
z0SC@4PAw^G#jf1FS@>=5K6C5M@8++pG~O3@r1tdjGu3DQ-Fv_H{`cDV{VtlWyBD6w
zm_EhoqOG?`xOvR(!tDL4vXnpE;upK^rl)qJB{kAKzR&LWJ8u!~3YNgCRCYCA=GVa~
zKUr<6Ydf8GSv}wP{4-m`JX1G!|49>;9i6c5b)Gl>^e+Lk?%bK>r*A)hPK7mB%i0wc
z$C9k<u2z4mGODaNkr}kJW12pL{l2sIjFUD`XImHKdpY65qon?zCZEeL>yI5*d68~9
zF+-Y5#OJAtaQm%k{pHIvjzzRjyx+Dgta0*8wHBMb6_poGq}1vDUOVAN_L96n5uZre
z9Dz3zGj1||Hovjrw*L#s)c0q2l&>#(UHI@H=Z>?R)=c@u=`uwi>Z9Mm2bxp2cWd#4
zJDJ&iI{bhAmyVNtD~ywxj(F!U7XQtuWxI0HJc~^eIEpd_{@jvOovpms@2=@X7s++H
zcAt)ZpAi`J@tn%WdO?r#1*%#%Z>SVpnQm!X+SHkNfurf<G1o0u{12>9e=2&r+@mpM
zTlcKM15+KUcFQ{*a<?sgB`xiC&0v#jKx5;Pf>hPGSL!u#OI<zpovD$_&wrmWS#+sm
z44>-G*4FipSB8`aZe9E2;*4c0&$JuOw6|Zr{JwqK>Qxsan!e6^xO!EW^O+aV<fXow
z-euh>AM-*!VfXuz5b3no<>gJkGnTR(e&Buh_Qt*Z`>wf9&{wv+BWk82+~js!)9C>d
ztKOpQ*Q<>`wjI-poYuNbc^xm;ikYXMJ=@Wtr>lF<y1?M4K=M*yzqmWI1J*mT?!4ZV
ze?8IYd3e~R@3tRTA6(#EHqHJ})4cCZOy`0nj9h&CV&kLF9@^RQJ>i7P`9@u)<!kgW
zPPSdne45Su?)449_U|9&zfTaaSL3+WzS7fQ^+VW`qVCklwX346f3`X)YQBov{4M5u
zGxxg{$4gXBZt^}++;ArU@yE7H_b#81uK8gzJ!Q&ccFBd35odyyJM2AeyI`ucfbFX~
z=BbuH)*a=yzM}bM{`SaaH`$BIS>{Yhez3XLq0Fb_%M|C?{_@N39eC{0@lR~muIfXv
nfmh#uc<u7q<-5ei{Y*RzKchXkGLzY@K{c7DtDnm{r-UW|3s&0Q
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..e4f529c6e0efded7df41e98437b01e9724dca198
GIT binary patch
literal 1795
zc%17D@N?(olHy`uVBq!ia0vp^S|H591|*LjJ{b+9BuiW)N`mv#O3D+9QW+dm@{>{(
zJaZG%Q-e|yQz{EjrrIztFlS_jM3hAM`dB6B=jtVb)aX^@7BGN-jeSKyVsdtBi9%9p
zdS;%j()-=}l@u~lY?Z=IeGPmIoKrJ0J*tXQgRA^PlB=?lEmM^2?G$V(tbhjOrj{fs
zROII56<bx<DuK<l0<uBE`br95B_-LmN)Sgy_y#CA=NF|anCcnpCL0(UDwvt+8Jd`y
znHlOR7#SEE=^Fr%nXaLUm8qGPk+}jCC;@FNN=dT{a&d#&1?1T(Wt5Z@Sn2DRmzV36
z8|&p4rRy77T3Uk4Ff!5ws?aU2%qvN((9J7WhMC}!TAW;zSx}OhpQixgCnn{Wme?vO
z!Mu=L;Oh%FIIkEQP{1J5uShJ=H`FuG&&}0`sV*)FN=?JBx;Uh=AXPsowK%`DC>a<Z
zY05}e;nxaM2y~5=e^DkdQWA4q@{>z*Q}aqZU2K(rGI}YQDOPS4=5B_D<|YQ_Mh0dU
zhK3df7RGK)MwX72&aOsA#)dF6u<3PlGBh`~G%#{=Gch$ZbTxEzc6N0(bTe`?b}}||
zws3^$^~@_SNz6-5h3U;i=rzQv*UGslHL)bWC?r2W2bKZ?GV)9Ei!<^I6r6+26f}Gj
zlQZ)`0-B%*g1R-eD6=dz#jPkmR{<QtR+(5_;AV;Gb0<qDV>e4z3r9-}6D6qL6mmjM
zALtl;wB!O40;WL_6Q1~i9C-Fg%>(9{B4Fl-4Y{xYnCA>VT^vIyZoQdt)?e6B<iPf&
zT?Z~L7E$7e+Q;&>tzn9jYSJEw$0wO@vG%L|vz;ffQ&M=n+A#+K0oPuZEc+KunNi!i
zCwkmm+j8#BuVq_072lTK<d>f0_j!}=x3g#R?;k%id*g{sK6BgBG@GY6`Wvq}nxtvP
z@cGG0?}|Ij8^r?z9qy@oud~-OyY@Q#GVA@w()v|8{f##?KOOwpdhS(#tLws>Uy4t)
zy_(7Hb+YZ%)O(Apo?qnG0x^?Arl~rA^~wuebwzAy$gz1PRWb2d-K$tuEX?k%aJ$4;
z_5a}EuU%ZTgDY<a&Q<A(S4li_=<rI;68o8dLbJD9uf4_<tgYN*cxLPI>~-^AN$Y(n
zDUF}MEVFv{)htuiNjqW$CjGlQH9y(reC^e!XE$HT@UoOmT9(b*e%6WYdf5Kz@*hWx
zHYBV)+4AGaxAY3XlDM6233J^J$~nGkulo@u(eUSy<j(G|X||2AO<!AIzSv{Mx?%d4
zLurcFng3nwl${s-t>T@+DvzLfOAc+fl;Pd`RyH>Hs_B-r2qsOgLv9KizDX!dZ?jpf
z@jdU^-)Lv8nkfvY*_iCyM826D9-7(pLdEHq!~Ncb3)34*`0u*?-)H{oObMINn*CeX
zes(P__1zqGTF84@P*RHRlkZL%x;ySDzu0l^&Kqmz^FEm~G7M!t8EZP;2uhAz#Jnr;
zQu`O#g1b&Xzf75RZH<Ssgigz0MmHbMz!pXEg!AXsBb-DoCf-~y{mV|v2cE+E&xDN~
ziZ^_g&N;!Y*DG{gZob82i$xO5a|`>r&wuCVS)RJ;!}%-4ww;j?ylk_h=S&vZ+`H2*
zCFVy%h038S;h36r>+jb_<SaPa8Yz7KtNXOS8+J;jxde7htewpfQB<vcs89IBy?qA{
zJG~2gU8SruD?2^WR3axQtCBBy+2f5bHnWJ&e)+Ogc9rad%g1;AXPVW>nyI>4kmI$S
zTqvuj1Rvi&jV7(Ug|_A~Q=hL|74{&1_sZv*UALHCp1T)3*T&7zjW6=h+g0y+OE^UC
ziyL~yUyGS?;L)Dyee3MFcKc7B*=jsz_m272f40p_QF6S+8kG6zt9obZ{51tZI`=K6
hJDy&^wsk)f55pqUH}T#Jm==SoB~MpBmvv4FO#tKgyuAPb
index eb44d0af9dede2bed602706f5d2259f4a7db38f3..1e6b89b40ef20a9a315aca7507251a485b622f12
GIT binary patch
literal 2629
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
F`Zwe~V*vmF
index 2653aef400b3d54d8c49115b407e3a3362c94b2d..660af2c4e2b1ac4b259f9ed7b511f662177cfe28
GIT binary patch
literal 1928
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
Q+W(E=%E-`t@}y0F0LriL>Hq)$
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..5f5f1698fe2bd9386368618bef4a76f6d82551cf
GIT binary patch
literal 2383
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
RYVjAx&Do23&S}ryKLN<R;H3Zn
index 452e7d72cc19e8f027300a9140370b57e422ef3f..8f3f71cc58c66376afc51294ba2dbe2c3c1a479d
GIT binary patch
literal 2281
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
P{CsdjquA#{wr2es-CL+g
index e6c1bfea4dd1ebd11c5764a8bed45cab96158e5e..4e58227843bbd4065de254bc5853cd740676fd7d
GIT binary patch
literal 1465
zc%17D@N?(olHy`uVBq!ia0vp^S|H591|*LjJ{b+9BuiW)N`mv#O3D+9QW+dm@{>{(
zJaZG%Q-e|yQz{EjrrIztFlS_jM3hAM`dB6B=jtVb)aX^@7BGN-jeSKyVsdtBi9%9p
zdS;%j()-=}l@u~lY?Z=IeGPmIoKrJ0J*tXQgRA^PlB=?lEmM^2?G$V(tbhjOrj{fs
zROII56<bx<DuK<l0<uBE`br95B_-LmN)Sgy_y#CA=NF|anCcnpCL0(UDwvt+8Jd`y
znHlOR7#SEE=^Fr%nXaLUm8qGPk+}jCC;@FNN=dT{a&d#&1?1T(Wt5Z@Sn2DRmzV36
z8|&p4rRy77T3Uk4Ff!5ws?aU2%qvN((9J7WhMC}!TAW;zSx}OhpQixgCnn{Wme?vO
z!Mu=L;Oh%FIIkEQP{1J5uShJ=H`FuG&&}0`sV*)FN=?JBx;Uh=AXPsowK%`DC>a<Z
zY05}e;nxaM2y~5=e^DkdQWA4q@{>z*Q}aqZU2K(rGI}YQDOPS4=5B_D<|YQ_Mh0dU
zhK3df7RGK)MwX72&aOsA#)dF6u<3PlGBh`~aC3BXGch$ZbTxEzc6N0(bTe`?b}}||
zws3^$^~@_SNz6-5h3U<N=ryshFfzld*UGslHL)bWC?r2W2bKZ?GV)9Ei!<^I6r6+2
z6f}GjlQZ)`0-B%*g1R-eD6=dz#jPkmR{<QtR+(5_;AV;Gb0<qDV>e4z3r9-}6D6qL
z6mmjMALtl;wB!O40;WL_6Q1~i9C-Fg%>(9{B4Fld_*{C9fr0V4r;B4q#jQ6pPJ118
z5NS(4mcU#Z+SL@08Mt9b@#{l-A4KihCVKF-)AdLD{1;ej=dn80Fs-&0UCR~s>aN}q
zZmw;n7tPXb0*`R%CCx};D}FG+z*8;$-+arNlBX=yjaZZ?wQ#>`va%J?Hb2Vd7A>)Q
z#?i|gddu%5tz$TFq$cUvujSHfLgc)=f}DhJM9-KZ`_HI1Y2z&B5(BU6i~cG%7DeCB
zsM|XCis@UG*|k+puCFzhuAX?KU_;J=GR3o3wmhHu<>J2pz3HZj&F?o{T*!93aTC|m
z)co@7pHF@ih$I$sNGnWH`>oX6+sC9T&-}Dfee2GWvRQJ@H*B_DpS5A{#Di)J7tbr+
z5Ffs8-r42b%*8HNsY<Mx|E+3u)&||1H)XSrK0bIqdcDS$C9D5@yY|aTt=KY7W6!IK
zyXPgkxr0Rx{Np+OIPmuFDmF8p6X(s=u&^F(U_Mr1EVkb)J;L8ZR?GZ5Z`{`@-=a1B
z0@=?*uGQpHVAm*^;2P+;hCOo4^Gy-_n<DflE_%13{Pl{}D;5O4_w)L<deNqarbK~L
zr#AbhhO&4sn6+;1>Qz#Urf{~gEP7q#Ch_9#-Lq59Kkt9swb4&S<KL|Ha`Nxgb>G%U
zPL#X;D9&a^wcDzM=cQ-3Q%-O*mOAaQKBu?h@?+lyMg|*&2Os7<D}MnhOg&xwT-G@y
GGywo8R~fAU
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..f4299f26984a7d20604c87162d4be2e77e58295f
GIT binary patch
literal 2599
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
Yi2UAObOcsDGym&GcW|Lf?ROve6Kr!-$^ZZW
index 2bed41b7c1a19fd8df44bfca527b61c272282029..1373110e2be6df7abd556fc1729edc102fcc951a
GIT binary patch
literal 2457
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
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..c3cc4398df5127d28779442eb56228e88ec9b15f
GIT binary patch
literal 3022
zc$}S9c|4Ts9v`PrD20f~G}N)qj+rr&Wss#Y8WI&XD^6x<W*BRBQAvX=722fD5+R%{
zY2jon9cy(+mPyBu?Wl-5&ds^^bMO6}KkoB+-}iZ*-~0Q1f4}Fqyq`DO&2`@<1uX>t
z0I<o)(T*gYjaKgsa?<Csrj{epNt18y#dl{j_yRJQ4zQuIDRiI{lk7()(aE&XlPz>C
z0I<$Kz{890Mc9v_vYBA=st!1W$pNemtW^kyOg%y811WUB02U53Ra*}N2GDSzLuLdh
zfrF>}2RMdt>F!~!9@MZCR5T4_wHJsD!AJ?1bUqmv!VF~bFd;b5pS&39dQ}Vo0smCt
zpTL3s>69124TxuR=|D3u!juYy!GPxGU>MTO+#F^CghOF)2vmBRo5GM7Gjj~w0{DG^
zq}I4J28Lwk@ZFYlhXeWZ`5X)cA`l3`0tA@N^@G6BX!I%v9BwMrFy)1^_~Z~%7Ef=D
z!H&+OasxR005%J_x+hcEL3|ttv~~n0hd}s?n8o`ZC~3$bA!H5&28KeIOvsuxk58gA
z{$88s5z3)MNOT@Mh)b2`gQ53trv4tfswnjaL*xcXlR^%(V^f2ebQa&q4hNFH0n-9#
z7zdPv0}N(?gj&F%<|r5p1w|noY~g4dG~ON#N5IxN{ukE97KTKj;0Ol?q!|om53|AJ
z?eQ=NxGlmKVU9=HtYMv4JU*F4rLSQF{)L7AEf$04(#d=_*MrRtT&n;#e>R`Z^JjB_
zcz1K40f9^nV66%aR}=KzS2{N!m`-!xvYEg?Ba8|7A09ZM|NG>&Xj_B>+8$+tMj=7p
zv9$juY7nV2kpC!`HIcLiSC@YkzjX6g`_Ng^p5aQHLuX#E9srPEa<a4W2zfo>9UkaG
zSFbM#4c=m+rkjzq#pl`Qn|Q+;DFsOzu6rdH*XrMct?x<_{$^Gj_|&ItqGtWE<e_UZ
z0Ot&kxS6*`duVZt@r>YG6$J^E9idfp%#<ZhJWyL-($*l66!2coq<VwV;|r*Ti25l(
z9j}fje>ju=G3yhw3o=qIH@Bj0P&m<nBy^jsNT9njhYij?`vtC4zW%q<y9CyIlCL+P
zp_nHGTfQuPp_%y&D@<D4eW2@TE5-D>k{o{1rF;5LH5OY_&4Ae&*P^BqUPp!-6amDE
zDYr9}9Q0(W0U{#Q0&SJ&I_m-2$=(*<YM99I|A1>Mn+ThzR0$(!0gL3$>ltJUPhr)k
z(ZuD?;>pQ!lE}SYQ|E@&@XzZr5ZevP`^!|Qx?3r;!^h(kWY@i^E3*8&(>om%cib=+
zTfzT2mm^F|+mQ&SKs&TwNYZ$~^p^F5odY#;z+7Sv)>zydzwfqRUSwWhn&LXqc!v@`
z$24>I2W1(jy!!@MR+jsORaxCjuM4$T?gq093&q+ACo2wRK5-?~4Gs=gwRCrJwuE_m
z$Fu~(23>zu>U?wcxxKNbzTaH(TM(nX`l&y%;+psUQycw$Rm>u`(BNr#)}{T=BTmoy
zT%6h`C+FJ~5GrV9G+=%fXoollPrdzmFZKY$1>O;7n;5Ahp}abz*fye{-nj%?CLNx2
z-WA`eCUH9-6I}~wOP~Lw{KqMIANdh=AHOadoGf@wDy^+)nE$#t_Wo9}Wbi%xI#ygj
z>4R<d&KRDQiHqAApAAE9njx0?nj7C#9P1n<mRuzRz(S$9zH$67E_<5XBaEDsMqik8
zSo%NkVjz?VhCvt8w!zc8s2%yT=ZZqCVoxc&QqUxhl}?|JJ;%L5Mg-5_J-iX3IPEnD
zXrmDi2#ac(8MW&s_1t@HHplfFeRy<wlz7$VDY5&LlDD7_t>3S&qKR_b;tvvfk?l#I
zx^Ifx5D+u7o)tyrPS%^T5YF=Ns(bbyjY$!H*?57<;BCI2A@Abuc{WI?@5ql%3C74L
z3==KMPr>=G?}o-_)K+9!`qqx$dKJ}>`?kR6jEBqF6EhD35ZEsdZk%2qp1S=}nA@w7
zT4IY7pI&TmG-KUrq_LkhmAyTH)Jd>bh_x;twY<wYUn#zDEVWq+>{eKKvRtywSSDDH
zYk;?YPU$?qTsIKzyk{WWqpr_wW!PsS>!NO1fAQsvdIM66on=E?nOBiRG&X+7c|I1k
zx4PU&S>cBR>znl?Ow-E|19`g51%+Y-o!cwz$&&JyMvu~xEtbqKi-OH+U2#(j;Uq;3
z++I7F+FaEYtKRt+ISBTf1igkQk_S97rk9Wd|1IfZ#j(tr&hshqxyZ={NJ3zxhE3?M
zbk~L9SpUhXDM{iPjT0L_W!4$<hxA;U_N7KV9v!>vk~{P%0TBEq7Uu1<?)d)rf#vCE
zs(*N&4Rir;gFx!{@THL(-MX88P?32zKJGgloDcHD;lZf)K`L5LGd*)*??n%f4^iVJ
zH8%z?IJR83qUb+-w8Kwm0;sI3Xg@jeyn~W*zcH>_<H)5Q3yr=J`r%%Oj?LS(DTm(G
z^))eA%nFaF%d0eWXHRGJ8wXn-QoY&xraUn^UKFw`yyo7IxI1=Vur)Um-y(H~AJadg
z^N92a-}b|$byZ=F??3x9Q;!bmjep#hzO_*V%?EMvV%?l=<hCsBZP&HkwW5(~>Qg6e
zqO4b86TdSuUR9mwT7UaUpH7+yt|-rCHo|=SO#RS8_(GeZU?QVgc=gT~hx9utCgCL`
zsy^jmM*0qMLWU;G^0jdnFT!ZIY+OvxUSd0|Hgdr8oN1d#WWABAbnsP5{MnbDN5Wz#
z3wjE7dKyR6ALhHa$Cw&+?Fe}(;j(IHi^DCF(jM(E;2CG*<QOiFjrZv*ccDMMJBNJ1
z)xG+dgp(J%jC_1;)8wthRBh!}<;BQ>!y|2_`p!RDR*ADsJ1L%49dEmDsn2|S%AH_L
zd>tk4zZI%k^>WY$EIvJ}eNZFm)Z%#NaC7dxv^#cct#@;3Ra<*v`YBKDb9KI1n=Nm>
z;AnHRH1go%7(RxO&=h&uhtMW4)>fV$9kj9R?(RO>@H@I*q3Xz$49;D_)N@()(}7UW
z>K=omR!9-&Gdw=fdU4@nwbI@k`6u6|YPE8wT8nN^9BikW^mq3^7@U%L=Q{sj^6}us
zwn#_sAV(hcj!m!2p|P;c=n*CMwQsjBIgw;HDaBVsx1@~nbd`K2n~#J0`}?O40^dby
zHfDBp7&c{z$v0Y143FY0+L!C4SB7Mld`h(S(zXKNDg&D@L_Nr|+TziEPZpEhRxYWC
ziJrQsmOo;~AA7&JwB>yE!4;8R@I}>(Gf^Z&bUV#RD|v!zf$qJrVcK|ppUQ{lGJnjv
zK}+RYXS7-|Zt_b^wc>jHoc)KlE0BQsiuu)-J`S3cTSj1DzG^?KT7{3z4Gg$(OxtHQ
z3z%JXpVget$96V0FM3}We(FJ{J&K-9!aD7ybViCM6D@w3n8i9j?%Xhtl8gJbvasIb
zk-E98iZ#f3kLt9lgelrl@}a7*vS&=ky->7W`W0`LS;zFcs@}cwWo2H>?@Q{*$3EEM
znSFA&IO>R6IYCkw6}E9VxoYysm*ui*yxNr?qe@5jo>k30dsH-tC5H!2zK|#F7c|zz
r!$ePs#}?ZYPgs}8JjS#~$!-S}$Iaz6d~G|m`iJdg?`l_Udp!0Z=)^wl
index 48d2e1e322a2a88222e18f5345c7f0272bdd1faa..d4ba66ea7131bb18ac939d867b2fa6282a7faded
GIT binary patch
literal 1653
zc%17D@N?(olHy`uVBq!ia0vp^LLkh+1|-AI^@Rf|$r9IylHmNblJdl&R0hYC{G?O`
z&)mfH)S%SFl*+=BsWuD@%o&*>5hW46K32*3xq68pHF_1f1q>iyV_#8_n4FzjqL7rD
zo|$K>^nUk#C56lsTcvPQUjyF)=hTc$kE){7;3~h6<f`ms%M>MhI|Z8xE1&_nsU?XD
z6}dTi#a0!zN?>!XfNYSkzLEl1NlCV?62wsvz5xo(`9-M;rh3M@$p(go3T9?{h9;(F
zW`;TnMh1pP`UXH`rfX<oWol++WUc@ON<iC+Qqrt~T-=~`0eQAc86_nJR{Hwo<>h+i
z#(Mch>H3D2mX;thjEr=FDs+o0^GXscbn}XpVJ5hw7AF^F7L;V>=P7{riAnjTCALaR
zFfZg5`1-;P&MSrn6fns2D-sLz4fPE4b941!s*6j4Qq%COE)J<INYxKYEzU13N(RP9
znlh4A__cx*0$pR}Uz7=ql*AmD{N&Qy)VvZ;7h5Huj9yA+ij|v%xtpP(xru?fk%5_o
zp`nF=g|VBHk)@-hv#XJju_4S1Y<eA?49wh2OkLf8grT9Up`)|2tFxh-k(05Lv6-`l
zBTTPnUU5lcUUDi-Zze>qiLtST8D70s&PAz-CHX}m`T04p6cCV+Uy@&(kzb(T9Bihb
z;hUJ8nFkWk1Vs?kt*J$sWvMA{Mftf3;1IUT#Nq-sOH7|TSvncJS-M&{T3VPWLG`AP
z6KeWE$LOOa7nl$*4T6~P#1G`avrlRsFwYbLGe>guqO%MPOp85T978H@^-Rh2xa=r%
ze82gBzso#Aw++%*(i)}OR?Dmm*m={%gtzKKc%;+57p@aITEDE)(c)OULMNo-)53cx
zE=w8>G-{$cPA6oxrFkq;d+WON_PX8s%O9I`$o|>!`~Um$`M+)D7H;2|G~x1(_X)pT
zE-o!v%a|xTrTwaDYPFEdRs#jL!W#?LtW<K;i;|eY;i}TZ%*6Dl{YU5Av)3lvlsVwS
z^uyInEzoDt%p)>;`c1rby;j|tpz&>|oT3pM&o%#+|1BqG3N5NPO8oy!{oeKWCvViO
zD42e-Xvw<$<qxg&j<`PN501UEL^Y;z!J)ajc^5^pcc>mav-(E1_w9(P^;y~bE<V3{
z?s;-vJ+l#e)`jEePfJL)h)#^LJFjGB>1aN4w@B*l#yekh)6yS%UT*AIskgS6<z9Ba
z!MC?YHcD|9ru2LeoLR-$*C{Vpwp#VWwNkNpcV?gPyO*-fevOIs$u|?e-C=&eF>S}H
zq6=FR*UDwsR<}*a){#@~^*HI#r~m)gjvYC%O-nQ4ZHp#N()so*xRW&{FQQse;c8{Y
zl>&*$O393-f2#`a_bR`Rd|DIr=ls1JeXqV8ieCT7H(e$>CuNyF%f|GjKVEgYTc!jy
zG+k2iu>ZU*@j@lLt*!Ir$tkO>U)||@DD%H${xwYnaqbJ-9`qL*T#e__P;lJjbTO)N
z<D$12`g^+du4|~J*Bm&_|6!V;$6DdFKF2h#me#Kp+c@uX?B&yQf)1tE|K_aG$#-;r
z$-LlL<CR_4B_0|kUh^q%D7ZOQRAA=T39e3z{(Xl(r}EA3GduX}FBjYO;|ZQ`bWd`J
zcHH{wnD^<O*lO>vEpahw0?#i$^|o->;TrC&P~}}K7glZ=Xk}xvxr}Sq-FKqC>og-5
spE}qOBo<ODGELt2yZ!p3@r-N?t(W=lKeutb1F8r-UHx3vIVCg!0QGEj2LJ#7
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..1d41cc5803d146613ca3c5f6aa76fcd1232891dd
GIT binary patch
literal 1073
zc$}S6L2J}N6b>wwQs}`J4=sp8icrB#GRbZ>30=!3yRi$V*6m_f5H*|3c0-#?Or~yH
zMAU<{6a^28;Kg5{D7|^Ghh8coc<|!MQ_+(rZ$h2a-6~poa7Z%my}a*xZ{EDOHZy&8
zaA0(RVVJ?{RJlg?q4e$Vqu-0~AI#Bhgj5=27Pm;pju2CFaT9^6Z_lF|vfbtD+h~Ge
zGHtKkAPwuB=3t+*Qy(tzLnd7llSybh3y6Rwn)iYt`|b4`7I<!voy%K-6&k4RO|3*|
zc4fNmtSmUH%TAsF6NyF%d_-)J_=`cTB}I0RSEF)j=2@`kLKcebucR8*3@~tnK%SGb
zjsPK$We(=@vJ6iHQGg;Z&_~X~oR*h0u>iV@rO_g{rPa!2Hx|{3Y@3i!<M~df!*wJM
zNAo;XRW;=h#Vqy6#>)Y*lWY)=^%%-1b|Nn%9u7dN+fBSgiY(hZf*)GeK5-Ct3q?!D
zCw9m~PT+l??|H|hhFXVv$Mxk9@ii3VrO2W8(Hi?B)Zx(7k!GWvk34!Q_F@@3OFjxn
zwOnNBAI|k$%~T2|goT_?5CvI*P!SZ#)J3(V8WmBLV2|S<Y)KbnGbf9tnae|1fhEJJ
z7|;}TNta|pDfO_`ASQO;pdQxyjfIC|H6ubc!BHLK#a;)@v@yYP8;8J{mBF}WJ6@0)
zPNf&r%@sx74dj{;_Q76-HSd57O!eQB>#8o9YDFojN{;Pf-T$c?Pm|&QYL}jg_FyXR
zH$PSO#|H&;W+FNqyi;4JgLSo9F4dDy%^$nFlbJj-oO!hQSz0~v^x4|lb`u<1=Wgx1
z8+mnk<H_ii^^+fkn;g3>=y$9Qduwa-!o3gq<5@Evxzu+Q^}qZ&{&?ucLzfDx<D1Ht
cw_~@N40C^H_{8_AwwMlawK83Pu3x+R6IESMJOBUy
index f7f033cf5d7cdb9c4cfd97f404fe3f15467c217b..5b4cc925187531b65cf54e55fed2c0dcc20cbd93
GIT binary patch
literal 1040
zc$}S6&ui2`6pj>2sq|7$D#(ytEVxM~$!0g9X-Tq4yWqCVcCmXjo6PQpHkmY;x@k}1
zNks$?1^)u^Q2Ylx=&9hPc+`U6sRu8;dJyWQZmQJMgF}*;_ws%3y?H;LHkTKtCT~tM
z3^P?<s<r4ooxc;~^n3r{#Twmi5W7QGagPk$1Tlt>y9m@nw~t!L^|v=aqB({c8wBkR
z=``+X9u7G-$8cE~Gx?fZ$YR%9M+9_HKZtbp_}zOJ1isF$l^a4Mw$LD0+DXvr&T`w^
zS@%?*U6==RnMMtSh`1mNH=<O_boSJ)M$fsLXTd3itn2LWpgN5vuyBGvnUhMM03lEm
z4$5Ukfp>u@K#>>dqm-bml@(2_fYD;9x5V#ht(r6PMJ1gb5E5%VKO7FZp~T^&&qGyJ
za~q;qqKHzu9T7JxMd?gop@vc~31Sl92;{Qc#al#Y+2RUe+-RH`j?z)0Xv+A^jd{ok
zd>HZtIwdXCyBwXiw`0V&P>Qz_kJh6%^Ovj3sX35Fqpc(XEsDEQ!`@biB2usEEd9gz
zfv-8$iUVOq7Am5kR3WSiRmm|$)le;46eU>LxQJ_*f-FfD$8qE`gf=uR%eJ5+nvy9g
zR@ErD^(ZB7<e`Ea{NdV{ay2VKF2P9~<Bg&NngdL5I>0foRuyok;d()oD`xWojbcSf
z@DTY<f<thcVJ)~I0!RJ#=B8>&j%rs8wJNhCuKzz-<7qJbxppa3v<LI!S@TojY<y5e
zXC|S;ar7Czq=PkIuNm#^u>14mWMQn#Tp!#0ASh3+?$gd!t-aS$|KQa(d7^h49zEYb
pd}GKfUw%yAf{!*o?JhD`#+heduN^n{X20h%TDO;LZ_Njfe*v-hL!|%!
index 4c79410772546cc90f53a496d2c5f82f4c5ec94f..9566650a6c7d87da939c329d9106a19ab753f9fe
GIT binary patch
literal 606
zc$@)V0-^nhP)<h;3K|Lk000e1NJLTq001-q001Tk1^@s6i)Ofc0006dNkl<Zc-rlm
z+fKqj5QY&%T0kfT0v4j>6eB7L;mrF#kBJvv<81PenQY3T5S?Illkax+|8{oUE@U$4
z#!d-0+_<)JW04i)1h>D0oI}oS=SnRjC3vztaR&+l??PlPuAjFglf+Jvu|@Jiz)bEF
zMWRHM!Tp7Bof2yMLR88niJc_GGA!Z?feKM2Y9J))7ZQqkRm{PHz7UgA2Zi>@cv!Kr
zkZ2H1qD8cc2O=UmXA+@C8#SAlgXPM|;H8n0Lbi<A5&<S@AwZXSB4VOX42a>G3{WFR
z%`WC>Va@;<Y^g+{oe<*g<k4c5F)P*l`25;wfR5FKQ~?=fmwsGqA?}WkRtG2;DGEi%
z5FnGE(4~Vy1sujIT5k4ttSA&CLj##g$aqwUx0{ERs9_&J5+g;S5i+!psf>)g?G6g@
zcB^1TOuKu;SW#$<3=uL_#I`$0sEF1!@x(DJG*J|qAVU|Ks>pa$NS+_wZssxiOiUGp
zrpWLlww*jjM}_$Ov~eI!%jb$hb7Y8-iO*3gp%70N^TK;2mWo14WauMPm`2FM3#^Vq
zXx`%Q#9C2kjSK^1sw1O!NGO{i)WN5TIg}ekp$#$&k;xXyo+GqX6xuo=C**{jkP~u3
zPRI%Ut<cqd%N_gL))q?rwViYyif{*cBUXw+D`e;+Q+UY*uZPRkLQ!ae4861$yqxu$
s0$;&jh?%0$3>oAVeD7}x|LRZUZ|~~BL|UA-*Z=?k07*qoM6N<$f+0H!=l}o!
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..e3836dda6abb174d03cfb972fe5a47fe3b9b91ff
GIT binary patch
literal 3842
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
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..69df9a75e588b631902062f87e826d6ad651a1ca
GIT binary patch
literal 3634
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
index e03b0519c790da95a27a228167be4ea9036077d5..b26e22aa6a1f715f45ebb58c3e0e9605ca7cb052
GIT binary patch
literal 5057
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
index 22cf0f7912318b62e314c40a4d4dcbeef15741a0..0a5603afc62059d75aa890c445a825847bee919d
GIT binary patch
literal 3738
zc$}SAc|6qX8Xrs6P@+O7)1(@eS<NuR#27SFF`5t}#u#S8%$ONl%9`Z}*^;Fq`&uVT
zWnZ!j;T%P%gtC?;MRdoxb?*J#dq3xo`+R=C-}^l8`+T4Gd7tI;d4Io}nI4ysQkDV$
z05T+^Aw@8nZ@v;@g6|&JZS{gdiEm`ZKf`wBdsDe|0N#o1NC%SKsV;O1o$BQ4(MHz=
z07Mu}b1S};$tf(2?GB-C>Og$lIe<;l)$`#{X|8lW(2?%KWZ^*bm9-!s(+LMUi!y<k
za0qk;lX#I!KXcL4oOaQbhH(Pv9Ruq6U<C%;>3k~C$K8#^!}{Prf7-<g_|0i32>7Q8
z-xUY?r&CrYW<Ua)O9!GLNDUec4hN#q5V$4^jfNiuB4BU?6ef7k8gNZ43XMf*0e=uk
zup8IO8A~xV{;`)p!hslkJ_iehdV70Aypa$#*98j4U@)6D5C{!{h6c}<#i#mcuz34_
zS}>&ZXj~?T&t$WJn=;jr?a9Z1KtGS*&M`6h%P@=gBT#~nL4BwkC>#QVy1PSvYV-IM
zy7S*_^UQrYbSQ<+V|#LGf_ymd|F^CF9=fS0@CHlfG6hMYx*4)*p6+xOpJa#w305FZ
zOed_dww5s*uB8dnLcq}4aJV*18)<BSz~C_iBLo5o|7qiYVGWUZB-#LJXl$&Bg2RpA
zcmlzQ05?V$APtacf;Rpqmc-)msVo}(CzkmyEa7jlSOS+$<+HiwY_{9a3NT}^`D`A8
z%>fe5pn+f$Dvin7oKW9P&<|hfT&5S@$(YM_2mTphEc1VOV2t_ilN(?Rkj5AzZ9GO>
z6Z8Y?^#4Q+DsTq+ALa6MN>GEF>|ez%5dLZ(I!n+qTtRb)lQIkd0I61zA>Q0)aK`pB
zN5MsDba-fJ_>w;1i^P_o_^@jyzybaJ+k$#T!A*a7GzVd~mcLM{d5Sf14Nb}9_dh?a
z@I5~(CMK&7>xs?iipVN2AI~x|2=r1|@FYQ=sENu8OG-YeT(4MOnbA0<EzfP6J^#6(
zT8r$(^IID!t6j&b&R2H(6;pSgs(3l@LNkM@-xruGWb)_-cTU;tk#KwIjNSZY=3;p^
z7)*CU1Os)i4W|=ELTZM@#8wrZgCjUgvs!b$H&p@#!p0i7N9&d*Xy3JBZCjmR4PEwu
zs*mbb!DNL}MTd>>*|S0s+V9qH7~$JZlVoX6dEWxDcePsJ=kd0I>ywT#&jRHJLujn0
z$n9auF_B=22kWwiyC=Rp61^82w-q-h-vaPNP=ap-1G}2$r1xJ^yEgXNPB>_;G%2u6
zX9bk;+vP2wkulzA^Q2mcr{#?oXWQY4^fx-y4Q}siXbRzI@$}2}9nuM*ce)~ObSBf!
zi>V;qI&}IAb$P{$9#{))lCF0?_}RO~w@Wu>yxh-s-ieqt6X2^(bxC16>bY*649Wp@
zXIIHR#QbunUgJf|)%9wcuJ^u{Qu{Z)BZ|x&=@PfS${A8mYp(d`MU5?qNPJ;~BMWof
z%t}2wyHW!u9KJVse7+ws_QIw5ynn;3{3E+B++Q?WN=eYyx)+?oE+|w^X;o^IbOBG+
z=Mxq3>fY2QI@DRUb7!2D$MVz&vl-yYPp}jvrT&3q-_l$~@UkEcT(co4HM3Pc>BS-W
zqucv_B`GOcXE#VyJsQmgR&C{)Z98C`h+tBHFY(8ORNJGX@9b$wN!Ytr?%JK4fp4m_
zr<WF?Zb&z^Hat;pemtPruT1HSxpAL)EZQ-$54m1->(=uudEvu{_e!|B&m%-r<JZK>
z!-3XbWO032LL_jlN;lwT$0FgVbludp{alrILk?uMj6`BuU41e5x1Q`~PWSE1UDR!v
z(!edT7O|5+Im}Gg?ND72UzG*fY_VR^s*rb;)Fa-vIMP-knSEXoUt&ZKpHOOSx}4f*
ztFZs-KDj>i9ozQ5CZ^0Ly*gon1xCYr0nDJ26x}3LlW^8FHmjAoCN#V-KIxLIuhi@)
zT^zh`$gO!e`V`~#0Xn>ek*F9Uq!i_RDHaVVIY|k_1^U0add~UROulF(x&BffJfZAU
z(t$X)C`_*YF|m`iS7$3FMGC>~E4q8TEhBqYm^<{d-*U8<TxQ5*ZMo1amSm^_QSZT;
zyvboP$<Sc_dP%w3XGK;2k7u>t9iB>Dz^(?b8G)z7Lqei*3$<*{rTS|YCd8B}9D*W|
zN4}Re70LN+xpU<vvU_nw92tT)^eNHmnHrs5{M|ozWoj0Xm`Mu)llsoyJ-RNbZ>K?$
z*Izchh&&Fg7<tQn)%U7j|MY113c)LCTyohNv!}+=+IK<GD2`l*Z_ERCKK*?+=1^i!
zc(B&5DFff0$y6SNsSN0S<+paVZC8e93iaPEj65UmWbF@CkU|z_9<26hBt3^Cq+}ah
zrsC#uo5OBxOc=M5E>EL%e~EHYcF-M<S|T62#9(=}4XQ?DKBkr?>ut%%A7|P*jL($^
zj*=ac?tT9@yRSE31jAbENtg>%wZC9)ant9a54|8Pt(2r7!`rEzQ=i>W9Dr(}{+OR)
zuyal)+;bbw{b&^#-=d>>Vzfut%&+h;d2jr9&*(m40i`d`7*w$(_m7wFi-sj(>Z5Mp
zb1UZB%;h`uag~A<%N_lZXGZ114FVFVklhwJ=C?@+dlQwJse^Mx_g;DwWNEZ_E<|%F
zMf3UdhuSkU3<`>_D;^4nc-{{e)sXJ*m(bst98^(pRYyRB5h;%$z75VZ14%e$@Wr?5
z0V)>P^ZcXU*|*%+;3s?EC+A?u$nGeH#<J%w!PUX;gPQZ(i;4G-MgJCh=e|s&sDr_<
zOQGp^g~$z(WrLZGcgd*Q`fFsGt1DziIQd3Iil}p@wwl9&_gYr(A@l?4kZ10~()MiC
zfH=D;GBaMBRZw<!BB0Xmu2)LumAMPLlh`Rjcmm2*>%kajAV3e}Z51~ztF>yH`da9S
z{q%<q2Vp81Wfum{kdH?;{gHTgKJcaY=atbfG{XVg@O=5CZmoX%VxY6Z*=LHV&mM{E
z55<L_wJZ}2k-NRCSH)Kuk9SzvRhaTjFk_4w=igHoi1zc#2Td$ohbIVYs~5?H+MrK2
zr!(4+pAv<ZgYTTRb^c^LzkFLc?{M;t<O6%FS1gJ;_%SqbrDh9h{&G;z#`!!x_rcA$
zg9U;{al29CGx0{p#b}9GSp<lllr1X`KYVg05^~O<%kN80Bt%CzKda+{Rm?3(^Snw<
z@q>l}I!ZG6lJ3@VDZ5n>@s3-)9nXW$CBc)B5K)D@)v?hD3T@ISJT8aXy*c4uIwQaH
z!*Rm_nH2!GefZ&Rf(Eak%>`e(rKbc%&#bb(--$@~vX;dzg+W7DB@oB=`9e&{hAHVv
z#*&Z0z(dCN;wOVKsDN<MCneT4$0$MUo0l>MHv+OxnKk6>iqQgYk6o&RmY*7$kzs#G
z6@w`*K1W>_jTX1MIYzAG7wfmdcBw^`7@Y!IEUK%m7cr-f*E@V1uCGsf77`+YBesUB
zpHWS|aSKN;0Y*#<t!i4FdDb#8mM;y?Hc|*PdAN**@%y(oW_>~gCNmHeEoc`YUzP7|
zzp<Qi(tYDax0kp5lPD8UOUuvGU%y^`bb`{1MrAs=MqW7982KndW~)ZvjTK<m^j&gV
zYd3z3o>fnp0fv1@Wu;VD4)^t~ca#U#Hm^qdr```XGl^3+*{3AA0I*8)d(+TT+tJpB
z!v^?oc%6<%ABhBwIJ)g=s+R{%Hiq3@vsE3pj(Yt(De9@26wGN*fpaw7dT79V-7}!<
z-ry=x^&RE;Sh@=9IsiwU);qVp9cR_i=!<=~3+XaZjdGc*`h~Nl8(cc`M*DXgx$!3h
zby?d6Ur4=w98f5;OJ~9E?bp!r_g<^Y5^b({7Rf8;j$mP&v9r-N6)VyCAd#K1A)n3z
z0uN9+!#dT-i?45zHCj8;%ETR#(wZAmYN?1<HtM}&sK==Uno#j-XSiufl?QYVQn{!N
zry%R2gjJp(d=@9zY0A^r#xh$+B<s4mb<g+e*^J(ond}+<pncZvdGu_^4IQ1WtsB0J
zsu!JBqpbZrcvn3!PPsNut!&7sE2bSXX^T$BgX0Uqp;hCJt;MK7=CL?<RE-(u<I1yV
zHCd&54))2U>F>P0)Qr3Ri{y(;`6(!8&dq37Id5>tW*TU3pIn<S;qL`qg{aw^)SxOD
z(FaDW`{z8u_v1;|-c!Jrj=Nug?UAZ^IoP{&FqqV{5Ta0W4`*ra=!%Zmcz^I~cX~;N
zkv;F+w`i9)r8TMczh(2M`fuK=|M1Q=X+A8+XWn7PaJ8o;(lX}D*Xe<ak-XgTy^X%{
znXTVv7}DQ_f<ml_XSrLrijzZWfS8`H^pfoKR~d@_)*rKM>)#$n?;9VK8lDI<sNbKG
zVlCd%t7?04L8!^7vmEl)t59;^nVAM(EK*1YJ8p#~5k_S3={7n-o)@wW-LelvC6?Ll
zw>0=9Y4`5Re4cr+TwQNNiEfysVI##YolpAi#8K|~^Kz&m!`S3LB#CLtFs2@TmxcjE
X=348u#U6}o{w<P>ObzcEI0XL#ECZAa
deleted file mode 100644
index 3b8643bfb94a0a1b49605027a97b85b0e5759732..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..7bcac5da6a6a4c331172c267b4ab8aeb4f1c2c2f
GIT binary patch
literal 2115
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
A9smFU
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..1ff17fc5a452b161a4504807066493b971792575
GIT binary patch
literal 2298
zc$}S9X;c$g77qK;xX}pXhB1JGKte*+g0N(hC^0OtK?hnxs(=ELib-jR$nMCX*bNSg
z4m68)Mg;*C!6h_~h_t9Ewx9xPoK_ZbiH%|l9GgiTapuhQ@yEPVRqx&V?sxBfcX_As
z!`82vW4qWEgTc(<hj1bcv&i^bTN=JgljmPFOp8!%G#ZJ-qbjii!UTgz9E9ad#R*UZ
zBnH)6yC8oI#w-yQMWfMzP(Xr6@nWM4K2<8m7>9pgs$48dhEQxAlmN?^IKB1)4hw@!
zTogs%BapM9L^x!J0*c(RUL@I(EMb7SzyPd&Dqv6`g-|gzRhlAG0;x>g2fct{ZDbR0
z*bgFTG86YNr=kU6ST>@7uoS$nx5S4?#8RnvBAG&^61}h_A0mn1V|b|EL^4330wfyt
z<G>lLDZqFjg2Vf0%Rn)4i6|-u2n3Z%g;)9F5k&%l$Y3yxI!GjMgM_zIEknhr-ZG`j
ztOgFGlqg_13L`SCkru}x+fXJBH+uxBTp;+QSf>0KC_~5ysbV>Si1#5#rG!~&B^m+6
ze_mQCQp+Ji1f)c^DI|t`#Jl{5sn0`=f(CB@p#nA}MV!JxB-^Br4CQl}IKvJegh7Bu
zr}2nH8rg?N@}bg+M7j^%m&YP8f*EWsiR4S1)$w~+j&CrXO=Jc0cw`EZ$R!4|*<3b}
zM`HQ1e5q`D@GO=uQ=(#-1e(Rd|Hd*tiv`#UNQ@#15rU-5RzO%Hf+EU9M2=-gQnBs=
zu>_VG86L(2ee@Mlz}q2^r$D6G4-p37-|>LQ_}`PW7%X2NgG&!)(8;)uSn&Ue8o}TU
z;lIjdmSw0x<MLDS8;DQs1IY|MqcAkb@Clv^24msQ=LCyV2cB2NCOSkpWa(dC?|dLI
z%@+)m1>7sWCwjv_z3GH^#EE8jpGjuz&q8Zf^Sm4jo!7gs+%5Jxn!Amzo9@{({V2B@
z2QTk+Y98MF%Bciw(h~Fg`}+@`W2$<w<%<sV|KRJV8m<@u_xoJ}U!EDMNPBtE@5{r*
z_6`~LYs{@3vT<P!=6iw`xZ9d?tF0Y0q2Lj#&N!k{dt^kr@C3v9yyIy~N6N||B<r_<
zwDEh4JCDG>IxB&)grHyFJl9!XsNDXVyNmP9+e-h8EYF??52hV|eEduKtK`*t8tf{7
z9l~XSH*XF-KB@PpDcUt@ikWoG7&lw%K6zahRpYacT+cbWLhdo2wFy^*?E;fzt?qv*
ziLr7kJX61Tp(bc;?PANS%4cg<m$U#s&uIu+vD@|dz}`KFK;^-zJWFKr^@48&`B$4X
z6WyI}=apvM9~i&0;>1s=#v{H@ofuH{UZcNyxe0fPto;7^yEhlo%Weuo3ud0Ib51Io
zWA{cEmpx@78SJ0fhqwK^G9l9w*&kFsh3L+{x}lZkF|Drh+&sI$&fR|6mi4U}1+M(~
zr8(qvt}ak#VfTpAWqbNiN==LQ)X?<)E^<NfR@~_O3p*)ym#Jh`cd8m`vRl^%u?g?3
zTg-ax94_`Q)4rXX-EeBOR(v<A4UhcVys<fQhiyiS)qVT^iSJBepLZ@}s?^Dq*?E&|
z2V!>9^j2=qw%>9RzKg55ArQUkb0=rv2~%DUu>oYfkf9CT6;lbw)>Mzay5FFy>j*e?
z*#5kKXHQQ@*hqM>tuy!7a`?+{){c(nbcTgKzr`{$=@rbU*v0;Nn!j6YF2^IcZa4;d
zMHkwUMV3uR-J4PM$cx(Ahj+>8MHt7a!q=Rx%L1T$Ft&qL6`<bP(bKH$h|io~9ILzi
z<F^^|zNo;Mhe^6C@|kTt-KGVB+=qBQ?n?N&60rZ!gBboH^Q9}bZE3QpvAut~)7MA2
z)YjSnD<fNkcN@yHyMqehug~qgcq%=8O%z-3I;`*oX5tTpZYzoelx0J~8K9Zp=<;et
zxJSk>P?T><TTX^^{jh(Z(*YZCvWKu$v=!5!yF!Sny~46-o4k1Dw2j8JI;A$g=|G@;
zJM$zBy%ZC&WMlRDi%v&3t-j%^5wS(twVU8Qo;`8li;7*<8n0_bxm{O_xEgttXV1Z>
zPXi%L(kSU{TT1D0`_jnG3pr@4izXt!#Fens0-(#EH4b@x)tKFLKRgGHFE+3KjRuhJ
zJ$n*O6S~lH+wQi3{UZ|-`<86UO3J&y%s(dc($%4JZ}@eOX&#N0VTScvYE(7Sf>mKH
z8#zk@4mpv;mn*}^Fr|YFc3Z?#2bx<e6l<NM6OJEKix1y^{QBJSDB-J<Bc;*#h&@_C
zKd#$A0-H=jUS8Ue?EjPt#Okb;&{oZ)ZGWpiGB~4rF&5bTokw@oU>f=S`P?p$UAXdc
z$*PjCyI*)RkgPGg>}x-98<V=ecMO<k!^VXt+_4<ige<I3J^aG#`mUI~r>DlI+bQQ9
zOTqSHH@%mA+hKY|pvm&Sku!o`5YF@B!;ex;$qADMwQ1fnPlAQHR%F}9<9*SN6g~Ua
z56*AvY|vHL-2MS**~{4_{q1wBrq0-${^R^F>XTfN@ne~D+RyH!gy;+Arkmc5yLoNK
zhq_3rC)i{<0~0CZ>gYOmS)HJ@<7Ro}{fE7ecWtPbxjYj$hwWV9`Qa9_Fx*P!dvbyn
fBw9boG_l0|ZEGWbq5ZZp<KGCMyPng)+LH56CWEx{
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..53a98d6dfc8fb75f9eba39430928213e9ef68041
GIT binary patch
literal 2835
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
index e18d3696d4c08a9da1eb88af4d6af894cf789db0..aad8eb61fd9adc4febf4405eb14abfea04289bcd
GIT binary patch
literal 4531
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
index cfa2e97e76a92eecfe9fd01d795efeae781e89d1..e099c709e66175a80360af1987a4bd3c5926f3d0
GIT binary patch
literal 2944
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
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..6a5778014ab0c199cb4f2a00647c340c629a6fda
GIT binary patch
literal 4029
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
index 2a3f0bcb652cc2b7ce30c5e65685f2facf5db583..a6450a33cca9c199df13076def5cbea77a864782
GIT binary patch
literal 3944
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
O*TU2WU1oAN>VE*Xfa|#c
index 83388ba62800fd60179767ee22a25e2240a6bcba..3d79547ffed0939e85818763daaf2459a624a6e3
GIT binary patch
literal 2008
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
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..b86dfbff80cdbfa79157bba904c05b53a5f99f10
GIT binary patch
literal 4335
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
index 41991961138b4533709225119ae2e0f1525742bb..c74628bd82035cfdff81e41a9e264811ac5a42c5
GIT binary patch
literal 4489
zc$}SBc{r4B_ouPTQiPG1L`|02493VhV>D?jgHkAi!DN}m$QD^b_G~GdEG;BONwTX*
z(qvDOEg^eZlKmau_uKdSUBBOZy?^}f>v^90+~+x;bIyI1=eq7E*3#TmL`YVMi;GJH
ze;iBX%r-l>03YWm=PCY@GXa?<c1&xk8`Gb}AafbHQk}^lyf?|6OeB+B1L-Z~V_aMS
z4~mT)(~fWw?Lzg2kalDs0p2vOopH<{fJSohBr`$IWOs^>p5lCUy&{O>s;78blK>;o
zFk}zP@gN4-I>_9{CCJl7$5qilA9O4L%~9Y@W|BYw-d;Yw=m0&%zx1Lx^bQ-U2>MHe
z>8YpqZ>Q`CmLLq3K?Z3;G}K*Sa5zXy3j#-KYH7jMKnNHd0flicEp<2&t*M1ZXoLP9
ziX3YUS2r{fi~HLaXQij;!DQ0VP^iDZKg3@HLS?u^;W|1xJ30^ub&iC(Z=es86rk?o
zd+3h_EZNtEL7_1zR3FgJn&eFNW9lg?{@H>zjX?NEv5)WHf#QS=8bG2!;Sd<q+Z*~v
z+LuWryZv`*Uz<Q08A>GkQvDb%oP4+)`X8qLJ9I~o;|<z^LE$8Y<b|cW_<56kn0Tz7
zBIganmEwxVp|o*uxHb}|jeu#P;BXWSrGYa>=osl>Ob`eS_#Ykr35(S*LSf*>2pkTn
z35T1&jW8G!3>=3r)-cx4!k~=)VDUb_Op=ca`45)zZ>)xvF%tG)v1kl~Okz?QHdLzD
zp9-+_pfahx9#k3#W32@O6G$!;pB={0odo^uE15yLNOr|BsNSHzB8;Z|2M=&M|99uc
zI>s6}9TSw14hpIGH`ew46E!Hu8R-8imp?2{4epTt6hCM2Py3L4I6cGQG{?*5j;5T3
zt-xcAYy$db90i#+J;2a;cB<=MSG=Wg(?><)Rz;!MYo&Z=uwyT{h)q#N<?_Lno_VGh
zbWUUtEs`B4DGyDG${+3X^n4^NZ*?3dtRlZR^_uw8lc{(_%X?QufB*U>^)TwnL8Y55
z?}cx+t}c!b_z%_k*R9O2)P>vHX5g=X+6NId+S{&_i#JSD7WCMmS~_!_XDkj~C$|+<
zdk?%JZ8i-BY?c%lP^-4rC1?QxHgywGLv>o;!f=q+D3E~5HNuL)r2}=X20!2u-GV2?
zb6-nZd~kA7lM*hQtcwxsQU5KkOGjRTxW6&^29?=#L%=B%DIy7o8ZgUJJ%~mkB1NH6
z1U!LEBoZe_Gj6PBqe4|lIEr2Tu_fi$7abn?IweNz*4z%k@`cwKn8-B*Ys3;ZRA9NR
zWK_&PZ-p#96bQo~kj=Z1;C5J3J&|jFr2Do?(Wx9aK3lRY{xGX(ST>Vq>6r4qwN5Yd
zyyP;jp?caaxlq=`W<rar&*^<SQDZM|#BJy1h>qP`#woEWlu0hts1Mp<`rHIj>gdWU
zJ_pTf1a`OcS^6BJq_$+^XTk?)cD-8wPy^gG50PK;w+sr{uRna`ePBV?6MlypCC2$!
z#0m6MyqmS<`TT_DnyuK;)IsltlmsxosJCm=!R=$yep^3}1)10AC0EUmn{RHscgwO6
z-I@UqrUuMYv9yBZJy^Q`*|UA*;qlg(3tO*G#XP+WRR@-KyP@mFm;%TL{<?x6zf3H{
zQ^B)k6&3O=GMYgyLqP#NQ<jG|T9*=bcV@%JrWA~z5yYShYg-`ht+17}*gh%w-#zK7
z^_3#a(RJ$zBs7wDPCP0FECG+vrqyUIY}mY+SmZvLw?=zu+J9aBd~G<n@&QI~e&i13
zOlPLl3+&;qwI+oJM}1o=v(`6;Pg;2xoC}@lnAC80f9VkdmG5wrd~#`nD{7H#*Qs_E
z97|U)>Vd9h1vkvQD;fQ`RrF}^3yJF4!nWTKnu|9Rcj?x>Oe7wXG(HO(&$0A#KR?SG
z9-}GUc;9XM`n$NNasBh3o^h|R6YS$G+vF~o<0tWzA%M}8x?2OMgRQOv^UTeZR?PqY
zy4d+uQ@cc=>B-E;fD>sD9h*hy%Zx@A4Dyh6q9u_YGH}Rj@94_9Oi6E9#fulitP=CJ
ztR83l_VL8D!f7c>(Y4g4Q>dph03Xps<l@*~lg51T4^3`2ka)n#aI?Y;&NgK5)rRTU
zqf=Fqfp<CzP4wF{rSrDybEn1^EdX;Vy=Hl1DX)3?FBZl*S8w*OoQoE=P<r(!{*_pw
zdhXHo%)In|<PyP5vTMyZCt1$l>e%XJip6uDU0ctW_s>z9H>uVqkbA-oU%CSzzsEOX
zoCbwdW}!FkYAE9wr%uTQcTawQmQomb8<q33%1NiY0f-z0gis7G>l!;Pc@iSTc#gjZ
ze0)>YT%5S<S6JlezdoSR-j*!U0ultIE6R6ff^UA0FaG^*YtXFjF!aZXVEgIkaih(3
zhCMCi)AP<9ZD!xRMa&HE?4fsN9!~pJi$_vozb<SIitTX^xb5x$Y4$ZWfUe$Xs2O{%
z%Oh72Ij(dzs;TFlwE*6MVkjW!QzdMBnd{72aJ^cq(fO{fO$OfT<#b_DHJy!y+Pry>
zjSu=_a{KF#_QxU;bNB2nEgH_9mW=wjerfnaL*CbXOg$#UuV-1i`n_A3l~}&~>69ZO
zz!Q~@ai&JuPozYaMpnybQtU)mJoY!%k(=IS&m4X54OnQu44R_Hr-P+>i9RYC3I$5{
zCHT?TbDo-}da0}GuH9(v8i*^B>U>EPy?<wDHX-TVwb*0899YOIs3?^1Ta+nxC9U!1
zhcwNM?Ah5zguB|Oi_hN4dhf<4|F!#m8;KtrE+cf%x+BSXdVaUtZbmZJO58r{k^TND
z3zkxRo!6>}5P7y^eiYS4VxDro{p5(1QpMGdQwrtj_P?Bh3T))KY!4(Q9k_ZWDYwY&
z^FmMRXRnCxQE~hO3k|dy+}>JfE%U+I2te<Gl}U9(v)Fy=nd?Za6=t=+!e;T(fw+i;
z5_@);nrXE$Xll2zIS~pre7$G(C-msD)ZQk?$XR>eWTz{;LWk-)Q(x6e=1f4V2Qj02
zCZ=t>T@Eks(Uj<Jw9}<)yNa~1cQUz^4he-DhpoyLWi4htVzk>CJ$!uLDmnIT_WN{3
z*T$qO&HUiE_k|6+f0x@he13Ar;#IGgeO7&uZGSh{hh{saso*7*DJ#H<q^g&OYs7mY
zndx6-B-q#pC!tx*o_*Pl5O)m|W4+e8gAdIgvKE1?Oe26$?^WLO-eSti`R^X44yG%0
zxOf*2d6j8uUn{9px_nP|T%Qom4vucT?eJ7sw7o}r5G^aWD5O6q8IR9}KB;9tzc*(?
z;9bp%&wPCC^@fA!sT{0cB7(qEcsu+6EVp-vrWzIe3=3CApoCE7JxMA_Cq6wnqI+2@
zrsyN*li|F}w<C3*F*H-{K-kvZvND&c7xXh?!+mo2g=s0f(T0W^@`12Ez#cY8G(T}$
z)~Rm-<T0V)+MagSYiRx5ms<`mo$)KC0y0%%(sH?Di9YQG)&+!|w3~i#<1@>$3#XU)
z)cSLfa`cb+%B>Zn!3Ot!)nX3<X0)ymQpTjN781mx-1LVlDhC|ZfxtU&EN-AC+lGmd
zSN+oco1sG%_?&3zE3BiL4rtQF<=9cp1HXQ$*(Bx%ab@d4d^Z3BN{=T6{av_cs<(sF
z4loR*A$3Vw<Z@VFKRE6{_pS!7R5i``2&d6iLo@%1ez%H>a(q5`rKk7Ht(r$bAaEL^
zYy8UWCP<*{YGiQRo?8!xxx2qEV&?1D6^J5BPgQG0njLg9!q`FL4Ik#XuS;!!-^!c}
zoM&AwqmQ)zls=Dc8e=2?!a4(MLiRMK(UWM%M0t&ia|t(3*K<SIGi*YDrS;2uJtKZm
zG5W5VB{eO)VGtqPl=xq$u;nO#a1tA+YYzBT1S-X`P36I*KX;|44;I53uK0!>hS=R0
za*v7P<%eX$U4FfJa`Q|Z4rXbwtKGfloU>Sxr)Jj45qoJ?u0r^^FWZCmz}het|LC&g
zvEnm&4Ox6#YVtOhQ0am`F;+p&A9#fq_%)qKBivK&Yc+ww=Z}}!F^uE=^ya$Yg$WPA
zT}&Kbs~0-<V%i};{(J||rmdB2Gr5fnd8YzG_HEsZ#e6dfUFhcu4RsttR@`Xuz-zC4
zFGdcuvnoJ2Ym^HYE__ioBwaXXY|*Ty8?PZ-uvBMys(a3Nse+3sxwN}GLI7<<(Z5zv
zH1+$4i3$Jw?DtXw#TG`?UG*QU<!VxD6XM<i$>aB;z*}PwyD5(g7r+H9#-%W^D#wEn
z$YNy!#hTjux3_<2)xJHcdb@ETm&_@2=AG>#Xt=trg9G!&T+)YM%}!WuFIuL2RMoS%
zzUulb+_I6qgT=P{$k1^7BSh@)%-)Z{NZkyJG!@mk(4|0L4+EPweCRf|{a3y{rRkF^
zw+q#vV0Flg<_^+!xEkK}*=7pDehDFS?D~ybzP-FLIMc<&>xOF^iL9igoJCrOr0s0w
zMNM~@xjyEbZBti{exT8CuJQP?Y=LK}fE^8ldcI*v!H+nKnl_JG0(!DkxC*)TxxU80
zWB4lb%Ez%yM*8BP#QbNNdNo^qUY}%2*BmFN&BDQE`3=>#SS7eBeFJ~Gbm0QBG-HfE
zIbCvaa%SdJ{&AuRy;zMk%Okd5R5>fN`bJIko9JlkdMtKKL_=!&D1D$y)S-9av_a!Q
zqocgV${eS^KQ1PG)`SXpd0%xgP*K;r6!W@c6_eQt^jkoWtYb=8^=}=C%<nv}S_f#9
z=h0f%9NF~fmLiqz3!?SK7ne0}|B^2NUka_+h_4^%9&D?uG)D5x9=TPhvW=38J_j|p
z(!&E-mfdJm34&T@%QQb4vx6v!z)nmojO7C8$t5j)rGS)E67rT#VJ;Gd=~{PVPUoOf
z3@Y|(IK8`BVVO>T&@wn!CGq9HWdzUiGzuWSvCMmhZc>%p_Y-z_VD9nIv%ai{?H2Zz
zn~(9ACh;&liibvAXGE6EbNF`Eh2$Uqc#0MIeSD!^H`_5~F7KlFa_YM{mlFO;Ps33W
z{K!&-`-gJLC0L?gxn{jI?~}Api7VvF@@G;C-`dND5IEhlTA#U-%D#r4;}4jcZsy^R
z>z$n|0_Z_`Dw%qlM8KEBy*H^qRj#yxMDaEZp?g@r`dnS44+@#!n?<4zUFUfsDTiuq
z0M?5tbN~mVFP*Y9B9npYO~~C0xe#u&O@P~kT6^jdb#+2D7H_6IFuoXA9i(_PuF1rT
z(c9arj~P+z6Gp$X&M`2&#!8zg{hXDw9x_-P(NI!xcABD^bUct4E-h2hUoM<Cdi2?J
z0!|Xg6B8XW@FpwkU8cCFJDc5-eHHvJ-Xm@hxmCK>NbfWJC{Er!6oZK!AOFTDKB`?+
zeM|Su^-7ae9x=H9(-22?+wpF?W5QZWqQD*IxWCV%2anbAmSnph6ts?g5iH8iW=&s>
z5=a229LY*!Jyf>n>pN?(n`al5Rs3Kr?1Rf)V)WhbTiT}Mu5JF8FW$X+&gPTw(-DWx
zMXI-Grh)`By1{QUB;RY{^25q7OdIE5l*)tLIU=PvZb2Kk66iwI*#*BNJ3mM8Cg#}3
I#!eCc0u3Yn(f|Me
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..2657cf25ae27089662f9a0d6245e59c33fc32fc6
GIT binary patch
literal 5204
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
index 3653e72cfebb342b593427ef299e52cd7d2e6576..90c0675a4ee10ecbd5bf1244d32406b2fce2c013
GIT binary patch
literal 2207
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
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..129ac1ed5bb64f0faf1cec2f30f496fa7873a08f
GIT binary patch
literal 1144
zc$}S7O>ERg6gCQ=2(n@iAVEc|kweuWv1^aL>#VIT$*zB31sjsh3bvQFjy=g*i9N=i
zu$vq}z#*jN#81Vc5()<{2oOSu0|y|S-~vQ|+J*xNwTenZRV1#c<FFelKshk7J@ejt
z-+OP~yyvOD-W{<uU#wvmCRW&~mFT=BdRtf1?{ntN89HqudW8(&AyP8~#N=!|h(N(L
zhfxWc_W1t0sEc7*s!q8=D#hK3h25kXVUl&%XQI*7UH46E1Q9TZh8-`<{&V9d3miMk
z?n@W>qOYQ=vvVRq0~5VvYhuKbZMJ(m=&CE!fQyI;>h7o)D)lV8Xjh@@NX@Ze5kf|?
z?7N^U#Xg|o0D*K;OjtaGK$4O$m6jy94G26GIG#RI0;ZI-qzIj$F<9y?u!oeAW;A?J
zDa%#~@fD7%)oRI_n8d*_2W44~YzRVvA`;=aN6dP{3)`C(G!$Ba;}ZvaAd<~NJVvrC
z+dP8n7mG`Vy|9renli3#`W#I1oa=H;bVy2QXnAy49`_MfLLnXtEP5Y9?f-MNJT(H+
zXp}vHLodY~)vz_@B99cbEK7Hiwqq+srqh71GsSlbyp(}3!)HVzFUUDr)dfL>O&g!$
zYND+1nvgP#R2o7Z=2TTzp&{hOyeO%eT$5YyLSlLrYI2?TTya^hq6Ww$I4EO0+N^-S
zDkeCrVjrjj66h$Jmg7Z=t<eQFVnu;-0NF->U9gy8#rZ@8hWzo#^KxD^WIdCUGby&g
zwLd3o91Vv1pj?_NT7%JYsrad|)IP|gJrmI8csd7)w6V??v|PFV``^Fbj@<&StNL8!
zgead9ubf<%p8RUnTU=c`_3zAcy*>W&m#f;37gzqY^6QS=&6b4=Qx~rt^sMyv+Wa?<
zE^qkj-h4-_+I4vL$b84b>4*J45AV^xeHoAavGw@+Q`bv(`j0(Xp-)e2YJ2mWcc}aH
zv@_EdZ#&B5;CJ!OFIM#Pd*iVeUp{!Y@qX*B+m)X3@mkN?^vvwJKPMm0^-MA?%(?}r
UzIxq#Hu@J7^j_^!{)Z#~0kCd!PXGV_
index 0c13cae05868f2f497478f543a66394ae1d729c0..95acc5133a0ed9501530579e5e5203bf32973d2a
GIT binary patch
literal 1095
zc$}S6U1-x#6pnL@Iact=e>7%3D6>s&+NMcZoo&*%vbB!3U=c;L<gSfdeoXFcH;|3J
zIK>zLVC=!SAqYA|5MiMBBF;Y?4AFrPJ_tStf(X8PGn*+o_TVMSz31fn&N=t|T<p&u
z3AOELBM2gt?U4(3-{-%rE%^J9n4ZSlc9bcjqCJRestbvfZVx~*YpNAkfT})vb^&$~
z#Kx*oDx-3)Pt<HPqWYLf-E;_lb#>PrRU3kc9Do(WN>X3vA5)~EC#hrc9Fub-ST%aa
zTv!~-m$b1VP0*?CLu6N7#0E@=RI+XkTb@`?QY&^veD>8eMXo^5P?Gu;R5{mAO12Bh
zcqAIu7yw9)i-1_1<G?|ZWdKVv_~F7JCdN6DO^}U6VQ;QJC>CU;;R{Pis)~>!(sZp>
zi`1eK+pW+*5Cq=_%Z4!`?2TGTt%ohIBd{PtPjd|i8Ma0GvN~Xopd>{FS1_GiZq=~m
zH4=qWM%Pt`1`&ofO*%k(r~n7oM|-7F2hs)T*(0uo>oM5zhpY9eJ`hJE9(4^|6m?j(
zwGk6qC@Uu^{3oItx~T981%O11Nw5sZ1HdzUR7tZ!N{})v8wG)lwYYLrNbo5jC`v32
zKnA2FDI)=eO-IvFPU2GmH*0xFwKN!Tjo(~;U9Kp(P(`*|vhCrZ1Ny5rvc0P9kW!H&
z_vcj2uzbY<zd(&xp=+Fjy5ia<xsqYgSR(>O`1j^%AstnO44)GC7}enF|C2Qu2SfkW
zE`bX7pnqI#ek`nx547;ixOg~1^Rp-LV2xzuRH?rF<=wr|1k)}rHUmOpCNF&J+5NnO
zY2LYQaj!VpL4BX=yLPL1sdz@deucg9q^Wf?dH7W2(VnTP9}k~>nB9b)zI@wv`L^{c
zbaLkS)tUFBOB2L~re+^DzPxm&cdqmELd)y?r}5S|FLpJx6I&i^z2Dh;{-!_L*-T!(
In?61H6I~-(EC2ui
index 4c79410772546cc90f53a496d2c5f82f4c5ec94f..86d00141703380cc325d78d12728afc077e5dfe9
GIT binary patch
literal 984
zc%17D@N?(olHy`uVBq!ia0vp^X+Z47!3HEfH!A8gFfh;eba4!+xb^mKw7;~W0Bb^&
z#smS591a!53jujq3QK(*J5K-qZ#nhXh4fcz(^f5BIX!0A?#LO*FZbO3_n|^$?a@m?
zhL3MXS|9^1srPf9`sV!m9X{*S;<LLyp3YbKd}u145of~DCx^9rV~?wB2x?GkJfct#
zxO&1?k89e~Zpak!8g9^8;#9cIF|yO)hVOdMR}*tWR5tE>xkq<iYt&4k<pEP}aBh?^
z-TadGq*}`AMF%Zk?Gaor=GZlN!Jz`Rg%JWrGG?63Z_Dv6Q}8_6RDAiT8E=$wQ%Ymp
zAx&9U$5{;%^md4D($4h$rtq7a@0{!N<)3pIXE`Ybth9(U5M%Y{Y|?O(HrpqBY3dgz
zK83%m?9VSXSC%oX<MrTZS+3q@Y<%Xkh{5FrCQoMM|Nrsx_03?G4DW9VVspfOm$e=g
zn$|h#pQ>exr`m%Xlcrhs%oE!itaEDqrl$gKr)M9%XnlO%tUHNYS{}OgYh?1ivub&H
z>Xsn8G?Q-T&O=B1ym|Gi_CC37ba0>ZjD2hN@}}kr7i{u78)LB1Xj_(7gm8eB(ZNRN
z8I5c9GF$itUkXdtNH;#1AbI%mChfH;x0333EK50xwX*Fe?7d;SJndSMnQ_lF!|JF@
z$u$z6G@l$&Jkz@7?}aHQwx$v1idrxJc0GMVE#^m6)TPHYVn!t###6TPKe)2x!Iccl
z%hhV(5<1DzpDrJ<U#^<+L?CTSVOH4!=fl-%;xnG|%y5Z1GVh+Q;(X_IvWH?$-}<`l
z<;i<0k_M+M4?p;uboxf+iPRG}6wgFltCQ1AuQ>mNZF1?yZ1ZKhpY9up6+ISsc5I4q
z?%b``)hiiKurABH^<>L5xz;%ulH5Ci&gXvm#^u|R>|4*OBn>J)%6sPeT2EfDSk9OD
zF6FKB&2Ht(3{&_Pi~pZ_<wm~Zcc5tM+v%IcZ!t{aTD<ntyq!PRJMC+?v1qBBur+=r
zTLOR7vqK5j7}Yut^rRH^^CilqzFo}W!({N<^<a)mLf=N^VxH!?Hw#(P7VFHY&E(cS
zGue5@at@#PZy65_;+N!p;VRayc91wE&}Pu0$dkz7ObT;`IqT!Ux1V|)`mp#@S53&g
zuRP5L+!bws&wtO@dH=Y`w}Q;vL*1LS_i1$7ef93DdnI1oeDksNnKR}y_HMeD;P*MJ
q^39K{pDf;opLXT>*L>-}%znmr*%xAA@_c6)Kv~w+&t;ucLK6U(`@(1d
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/resources/drawable/ic_menu_desktop_mode_off.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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/. -->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+       android:shape="rectangle">
+
+     <solid android:color="@android:color/transparent"/>
+
+</shape>
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/resources/drawable/ic_menu_desktop_mode_on.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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/. -->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+       android:shape="rectangle">
+
+     <solid android:color="@android:color/transparent"/>
+
+</shape>
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/resources/drawable/ic_menu_quit.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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/. -->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+       android:shape="rectangle">
+
+     <solid android:color="@android:color/transparent"/>
+
+</shape>
--- a/mobile/android/base/resources/layout/menu_item.xml
+++ b/mobile/android/base/resources/layout/menu_item.xml
@@ -1,38 +1,50 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <merge xmlns:android="http://schemas.android.com/apk/res/android">
 
-     <View android:layout_width="14dp"
+     <View android:layout_width="10dp"
            android:layout_height="fill_parent"
            android:layout_gravity="center_vertical"/>
 
      <ImageView android:id="@+id/icon"
-                android:layout_width="24dp"
-                android:layout_height="18dp"
+                android:layout_width="27dp"
+                android:layout_height="21dp"
                 android:paddingRight="6dp"
                 android:layout_gravity="center_vertical"
                 android:visibility="gone"/>
 
      <TextView android:id="@+id/title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1.0"
                android:textSize="16sp"
                android:textColor="@color/menu_item_title"
                android:singleLine="true"
                android:ellipsize="middle"
                android:layout_gravity="center_vertical"/>
 
-     <CheckBox android:id="@+id/check"
-               android:layout_width="18dp"
-               android:layout_height="18dp"
-               android:layout_gravity="center_vertical"
-               android:button="@drawable/menu_item_checkmark"
-               android:focusable="false"
-               android:clickable="false"
-               android:visibility="gone"/>
+     <FrameLayout android:layout_width="18dp"
+                  android:layout_height="18dp"
+                  android:layout_marginBottom="2dp"
+                  android:layout_gravity="center_vertical">
 
-     <View android:layout_width="14dp"
+         <CheckBox android:id="@+id/check"
+                   android:layout_width="18dp"
+                   android:layout_height="18dp"
+                   android:button="@drawable/menu_item_checkmark"
+                   android:focusable="false"
+                   android:clickable="false"
+                   android:visibility="gone"/>
+
+         <ImageView android:id="@+id/more"
+                   android:layout_width="18dp"
+                   android:layout_height="18dp"
+                   android:src="@drawable/menu_item_more"
+                   android:visibility="gone"/>
+
+     </FrameLayout>
+
+     <View android:layout_width="10dp"
            android:layout_height="fill_parent"
            android:layout_gravity="center_vertical"/>
 
 </merge>
--- a/mobile/android/base/resources/menu-large-v11/browser_app_menu.xml.in
+++ b/mobile/android/base/resources/menu-large-v11/browser_app_menu.xml.in
@@ -23,49 +23,54 @@
           android:icon="@drawable/ic_menu_share"
           android:title="@string/share" /> 
     
     <item android:id="@+id/find_in_page"
           android:icon="@drawable/ic_menu_find_in_page"
           android:title="@string/find_in_page" />
 
     <item android:id="@+id/desktop_mode"
-          android:icon="@drawable/ic_menu_desktop_mode"
+          android:icon="@drawable/ic_menu_desktop_mode_off"
           android:title="@string/desktop_mode"
           android:checkable="true" />
 
-    <item android:title="@string/tools">
+    <item android:title="@string/tools"
+          android:icon="@drawable/ic_menu_tools">
 
         <menu>
 
             <item android:id="@+id/save_as_pdf"
                   android:icon="@drawable/ic_menu_save_as_pdf"
                   android:title="@string/save_as_pdf" />
 
-            <item android:id="@+id/addons"
-                  android:title="@string/addons"/>
+            <item android:id="@+id/downloads"
+                  android:icon="@drawable/ic_menu_downloads"
+                  android:title="@string/downloads"/>
 
-            <item android:id="@+id/downloads"
-                  android:title="@string/downloads"/>
+            <item android:id="@+id/addons"
+                  android:icon="@drawable/ic_menu_addons"
+                  android:title="@string/addons"/>
 
 #if MOZ_UPDATE_CHANNEL != beta
 #if MOZ_UPDATE_CHANNEL != release
             <item android:id="@+id/apps"
+                  android:icon="@drawable/ic_menu_apps"
                   android:title="@string/apps"/>
 #endif
 #endif
 
         </menu>
 
     </item>
 
     <item android:id="@+id/char_encoding"
           android:visible="false"
           android:title="@string/char_encoding"/>
 
     <item android:id="@+id/settings"
+          android:icon="@drawable/ic_menu_settings"
           android:title="@string/settings" />
 
 #ifdef MOZ_PROFILING
     <item android:id="@+id/toggle_profiling"
           android:title="@string/toggle_profiling" />
 #endif
 </menu>
--- a/mobile/android/base/resources/menu-v11/browser_app_menu.xml.in
+++ b/mobile/android/base/resources/menu-v11/browser_app_menu.xml.in
@@ -24,49 +24,54 @@
           android:icon="@drawable/ic_menu_share"
           android:title="@string/share" /> 
     
     <item android:id="@+id/find_in_page"
           android:icon="@drawable/ic_menu_find_in_page"
           android:title="@string/find_in_page" />
 
     <item android:id="@+id/desktop_mode"
-          android:icon="@drawable/ic_menu_desktop_mode"
+          android:icon="@drawable/ic_menu_desktop_mode_off"
           android:title="@string/desktop_mode"
           android:checkable="true" />
 
-    <item android:title="@string/tools">
+    <item android:title="@string/tools"
+          android:icon="@drawable/ic_menu_tools">
 
         <menu>
 
             <item android:id="@+id/save_as_pdf"
                   android:icon="@drawable/ic_menu_save_as_pdf"
                   android:title="@string/save_as_pdf" />
 
-            <item android:id="@+id/addons"
-                  android:title="@string/addons"/>
+            <item android:id="@+id/downloads"
+                  android:icon="@drawable/ic_menu_downloads"
+                  android:title="@string/downloads"/>
 
-            <item android:id="@+id/downloads"
-                  android:title="@string/downloads"/>
+            <item android:id="@+id/addons"
+                  android:icon="@drawable/ic_menu_addons"
+                  android:title="@string/addons"/>
 
 #if MOZ_UPDATE_CHANNEL != beta
 #if MOZ_UPDATE_CHANNEL != release
             <item android:id="@+id/apps"
+                  android:icon="@drawable/ic_menu_apps"
                   android:title="@string/apps"/>
 #endif
 #endif
 
         </menu>
 
     </item>
 
     <item android:id="@+id/char_encoding"
           android:visible="false"
           android:title="@string/char_encoding"/>
 
     <item android:id="@+id/settings"
+          android:icon="@drawable/ic_menu_settings"
           android:title="@string/settings" />
 
 #ifdef MOZ_PROFILING
     <item android:id="@+id/toggle_profiling"
           android:title="@string/toggle_profiling" />
 #endif
 </menu>
--- a/mobile/android/base/resources/menu-xlarge-v11/browser_app_menu.xml.in
+++ b/mobile/android/base/resources/menu-xlarge-v11/browser_app_menu.xml.in
@@ -24,49 +24,54 @@
           android:icon="@drawable/ic_menu_share"
           android:title="@string/share" /> 
     
     <item android:id="@+id/find_in_page"
           android:icon="@drawable/ic_menu_find_in_page"
           android:title="@string/find_in_page" />
 
     <item android:id="@+id/desktop_mode"
-          android:icon="@drawable/ic_menu_desktop_mode"
+          android:icon="@drawable/ic_menu_desktop_mode_off"
           android:title="@string/desktop_mode"
           android:checkable="true" />
 
-    <item android:title="@string/tools">
+    <item android:title="@string/tools"
+          android:icon="@drawable/ic_menu_tools">
 
         <menu>
 
             <item android:id="@+id/save_as_pdf"
                   android:icon="@drawable/ic_menu_save_as_pdf"
                   android:title="@string/save_as_pdf" />
 
-            <item android:id="@+id/addons"
-                  android:title="@string/addons"/>
+            <item android:id="@+id/downloads"
+                  android:icon="@drawable/ic_menu_downloads"
+                  android:title="@string/downloads"/>
 
-            <item android:id="@+id/downloads"
-                  android:title="@string/downloads"/>
+            <item android:id="@+id/addons"
+                  android:icon="@drawable/ic_menu_addons"
+                  android:title="@string/addons"/>
 
 #if MOZ_UPDATE_CHANNEL != beta
 #if MOZ_UPDATE_CHANNEL != release
             <item android:id="@+id/apps"
+                  android:icon="@drawable/ic_menu_apps"
                   android:title="@string/apps"/>
 #endif
 #endif
 
         </menu>
 
     </item>
 
     <item android:id="@+id/char_encoding"
           android:visible="false"
           android:title="@string/char_encoding"/>
 
     <item android:id="@+id/settings"
+          android:icon="@drawable/ic_menu_settings"
           android:title="@string/settings" />
 
 #ifdef MOZ_PROFILING
     <item android:id="@+id/toggle_profiling"
           android:title="@string/toggle_profiling" />
 #endif
 </menu>
--- a/mobile/android/base/resources/menu/gecko_app_menu.xml
+++ b/mobile/android/base/resources/menu/gecko_app_menu.xml
@@ -1,10 +1,11 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!-- 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/. -->
 
 <menu xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:id="@+id/quit"
+          android:icon="@drawable/ic_menu_quit"
           android:title="@string/quit"
           android:orderInCategory="10" />
 </menu>
--- a/mobile/android/base/tests/testHistoryTab.java.in
+++ b/mobile/android/base/tests/testHistoryTab.java.in
@@ -132,20 +132,16 @@ public class testHistoryTab extends Pixe
     }
 
     private void testContextMenu(String url) {
         list = getHistoryList();
         // clear VKB
         mActions.sendSpecialKey(Actions.SpecialKey.BACK);
         mSolo.waitForText(url);
 
-        View child = list.getChildAt(0);
-        mSolo.clickLongOnView(child);
-        mAsserter.is(false, mSolo.waitForText("Open in New Tab"), "Header rows should not show a context menu");
-
         // wait for the history list to be populated
         mFirstChild = null;
         boolean success = waitForTest(new BooleanTest() {
             public boolean test() {
                 mFirstChild = list.getChildAt(1);
                 if (mFirstChild == null) {
                     return false;
                 }
@@ -173,16 +169,21 @@ public class testHistoryTab extends Pixe
 
             // TODO: Test clicking these does the right thing
             mAsserter.ok(mSolo.waitForText("Open in New Tab"), "Context menu has New Tab option", "Open in New Tab");
             mAsserter.ok(mSolo.searchText("Share", true), "Context menu has Share option", "Share");
             mAsserter.ok(mSolo.searchText("Remove", true), "Context menu has Remove option", "Remove");
             mAsserter.ok(mSolo.searchText("Add to Home Screen", true), "Context menu has Add to Home Screen option", "Add to Home Screen");
 
             mActions.sendSpecialKey(Actions.SpecialKey.BACK);
+
+            View child = list.getChildAt(0);
+            mSolo.clickLongOnView(child);
+            mAsserter.is(false, mSolo.waitForText("Open in New Tab"), "Header rows should not show a context menu");
+
         } else {
             mAsserter.ok(false, "waiting for history item", "history item available");
         }
         mActions.sendSpecialKey(Actions.SpecialKey.BACK);
     }
 
     private void testClick(String url) {
         list = getHistoryList();
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -176,17 +176,16 @@ var BrowserApp = {
     Services.obs.addObserver(this, "ScrollTo:FocusedInput", false);
     Services.obs.addObserver(this, "Sanitize:ClearData", false);
     Services.obs.addObserver(this, "FullScreen:Exit", false);
     Services.obs.addObserver(this, "Viewport:Change", false);
     Services.obs.addObserver(this, "Viewport:Flush", false);
     Services.obs.addObserver(this, "Passwords:Init", false);
     Services.obs.addObserver(this, "FormHistory:Init", false);
     Services.obs.addObserver(this, "ToggleProfiling", false);
-    Services.obs.addObserver(this, "Memory:Dump", false);
 
     Services.obs.addObserver(this, "sessionstore-state-purge-complete", false);
 
     function showFullScreenWarning() {
       NativeWindow.toast.show(Strings.browser.GetStringFromName("alertFullScreenToast"), "short");
     }
 
     window.addEventListener("fullscreen", function() {
@@ -225,16 +224,17 @@ var BrowserApp = {
     PermissionsHelper.init();
     CharacterEncoding.init();
     ActivityObserver.init();
     WebappsUI.init();
     RemoteDebugger.init();
     Reader.init();
     UserAgent.init();
     ExternalApps.init();
+    MemoryObserver.init();
 #ifdef MOZ_TELEMETRY_REPORTING
     Telemetry.init();
 #endif
 #ifdef ACCESSIBILITY
     AccessFu.attach(window);
 #endif
 
     // Init LoginManager
@@ -523,16 +523,17 @@ var BrowserApp = {
     ConsoleAPI.uninit();
     CharacterEncoding.uninit();
     SearchEngines.uninit();
     WebappsUI.uninit();
     RemoteDebugger.uninit();
     Reader.uninit();
     UserAgent.uninit();
     ExternalApps.uninit();
+    MemoryObserver.uninit();
 #ifdef MOZ_TELEMETRY_REPORTING
     Telemetry.uninit();
 #endif
   },
 
   // This function returns false during periods where the browser displayed document is
   // different from the browser content document, so user actions and some kinds of viewport
   // updates should be ignored. This period starts when we start loading a new page or
@@ -1142,107 +1143,29 @@ var BrowserApp = {
     } else if (aTopic == "ToggleProfiling") {
       let profiler = Cc["@mozilla.org/tools/profiler;1"].
                        getService(Ci.nsIProfiler);
       if (profiler.IsActive()) {
         profiler.StopProfiler();
       } else {
         profiler.StartProfiler(100000, 25, ["stackwalk"], 1);
       }
-    } else if (aTopic == "Memory:Dump") {
-      this.dumpMemoryStats(aData);
     }
   },
 
   get defaultBrowserWidth() {
     delete this.defaultBrowserWidth;
     let width = Services.prefs.getIntPref("browser.viewport.desktopWidth");
     return this.defaultBrowserWidth = width;
   },
 
   // nsIAndroidBrowserApp
   getBrowserTab: function(tabId) {
     return this.getTabForId(tabId);
   },
-
-  dumpMemoryStats: function(aLabel) {
-    // TODO once bug 788021 has landed, replace this code and just invoke that instead
-    // currently this code is hijacked from areweslimyet.com, original code can be found at:
-    // https://github.com/Nephyrin/MozAreWeSlimYet/blob/master/mozmill_endurance_test/performance.js
-    var memMgr = Cc["@mozilla.org/memory-reporter-manager;1"].getService(Ci.nsIMemoryReporterManager);
-
-    var timestamp = new Date();
-    var memory = {};
-
-    // These *should* be identical to the explicit/resident root node
-    // sum, AND the explicit/resident node explicit value (on newer builds),
-    // but we record all three so we can make sure the data is consistent
-    memory['manager_explicit'] = memMgr.explicit;
-    memory['manager_resident'] = memMgr.resident;
-
-    var knownHeap = 0;
-
-    function addReport(path, amount, kind, units) {
-      if (units !== undefined && units != Ci.nsIMemoryReporter.UNITS_BYTES)
-        // Unhandled. (old builds don't specify units, but use only bytes)
-        return;
-
-      if (memory[path])
-        memory[path] += amount;
-      else
-        memory[path] = amount;
-      if (kind !== undefined && kind == Ci.nsIMemoryReporter.KIND_HEAP
-          && path.indexOf('explicit/') == 0)
-        knownHeap += amount;
-    }
-
-    // Normal reporters
-    var reporters = memMgr.enumerateReporters();
-    while (reporters.hasMoreElements()) {
-      var r = reporters.getNext();
-      r instanceof Ci.nsIMemoryReporter;
-      if (r.path.length) {
-        addReport(r.path, r.amount, r.kind, r.units);
-      }
-    }
-
-    // Multireporters
-    if (memMgr.enumerateMultiReporters) {
-      var multireporters = memMgr.enumerateMultiReporters();
-
-      while (multireporters.hasMoreElements()) {
-        var mr = multireporters.getNext();
-        mr instanceof Ci.nsIMemoryMultiReporter;
-        mr.collectReports(function (proc, path, kind, units, amount, description, closure) {
-          addReport(path, amount, kind, units);
-        }, null);
-      }
-    }
-
-    var heapAllocated = memory['heap-allocated'];
-    // Called heap-used in older builds
-    if (!heapAllocated) heapAllocated = memory['heap-used'];
-    // This is how about:memory calculates derived value heap-unclassified, which
-    // is necessary to get a proper explicit value.
-    if (knownHeap && heapAllocated)
-      memory['explicit/heap-unclassified'] = memory['heap-allocated'] - knownHeap;
-
-    // If the build doesn't have a resident/explicit reporter, but does have
-    // the memMgr.explicit/resident field, use that
-    if (!memory['resident'])
-      memory['resident'] = memory['manager_resident']
-    if (!memory['explicit'])
-      memory['explicit'] = memory['manager_explicit']
-
-    var label = "[AboutMemoryDump|" + aLabel + "] ";
-    dump(label + timestamp);
-    for (var type in memory) {
-      dump(label + type + " = " + memory[type]);
-    }
-  },
 };
 
 var NativeWindow = {
   init: function() {
     Services.obs.addObserver(this, "Menu:Clicked", false);
     Services.obs.addObserver(this, "Doorhanger:Reply", false);
     this.contextmenus.init();
   },
@@ -2338,51 +2261,59 @@ Tab.prototype = {
     if (this.browser)
       return;
 
     aParams = aParams || {};
 
     this.browser = document.createElement("browser");
     this.browser.setAttribute("type", "content-targetable");
     this.setBrowserSize(kDefaultCSSViewportWidth, kDefaultCSSViewportHeight);
-    BrowserApp.deck.appendChild(this.browser);
+
+    // Make sure the previously selected panel remains selected. The selected panel of a deck is
+    // not stable when panels are added.
+    let selectedPanel = BrowserApp.deck.selectedPanel;
+    BrowserApp.deck.insertBefore(this.browser, aParams.sibling || null);
+    BrowserApp.deck.selectedPanel = selectedPanel;
 
     // Must be called after appendChild so the docshell has been created.
     this.setActive(false);
 
     this.browser.stop();
 
     let frameLoader = this.browser.QueryInterface(Ci.nsIFrameLoaderOwner).frameLoader;
     frameLoader.renderMode = Ci.nsIFrameLoader.RENDER_MODE_ASYNC_SCROLL;
 
     // only set tab uri if uri is valid
     let uri = null;
     try {
       uri = Services.io.newURI(aURL, null, null).spec;
     } catch (e) {}
 
-    this.id = ++gTabIDFactory;
-    this.desktopMode = ("desktopMode" in aParams) ? aParams.desktopMode : false;
-
-    let message = {
-      gecko: {
-        type: "Tab:Added",
-        tabID: this.id,
-        uri: uri,
-        parentId: ("parentId" in aParams) ? aParams.parentId : -1,
-        external: ("external" in aParams) ? aParams.external : false,
-        selected: ("selected" in aParams) ? aParams.selected : true,
-        title: aParams.title || aURL,
-        delayLoad: aParams.delayLoad || false,
-        desktopMode: this.desktopMode
-      }
-    };
-    sendMessageToJava(message);
-
-    this.overscrollController = new OverscrollController(this);
+    if (!aParams.zombifying) {
+      this.id = ++gTabIDFactory;
+      this.desktopMode = ("desktopMode" in aParams) ? aParams.desktopMode : false;
+
+      let message = {
+        gecko: {
+          type: "Tab:Added",
+          tabID: this.id,
+          uri: uri,
+          parentId: ("parentId" in aParams) ? aParams.parentId : -1,
+          external: ("external" in aParams) ? aParams.external : false,
+          selected: ("selected" in aParams) ? aParams.selected : true,
+          title: aParams.title || aURL,
+          delayLoad: aParams.delayLoad || false,
+          desktopMode: this.desktopMode
+        }
+      };
+      sendMessageToJava(message);
+
+      this.overscrollController = new OverscrollController(this);
+    }
+
     this.browser.contentWindow.controllers.insertControllerAt(0, this.overscrollController);
 
     let flags = Ci.nsIWebProgress.NOTIFY_STATE_ALL |
                 Ci.nsIWebProgress.NOTIFY_LOCATION |
                 Ci.nsIWebProgress.NOTIFY_SECURITY;
     this.browser.addProgressListener(this, flags);
     this.browser.sessionHistory.addSHistoryListener(this);
 
@@ -2476,26 +2407,29 @@ Tab.prototype = {
 
   destroy: function() {
     if (!this.browser)
       return;
 
     this.browser.contentWindow.controllers.removeController(this.overscrollController);
 
     this.browser.removeProgressListener(this);
+    this.browser.sessionHistory.removeSHistoryListener(this);
+
     this.browser.removeEventListener("DOMContentLoaded", this, true);
     this.browser.removeEventListener("DOMLinkAdded", this, true);
     this.browser.removeEventListener("DOMTitleChanged", this, true);
     this.browser.removeEventListener("DOMWindowClose", this, true);
     this.browser.removeEventListener("DOMWillOpenModalDialog", this, true);
     this.browser.removeEventListener("scroll", this, true);
+    this.browser.removeEventListener("MozScrolledAreaChanged", this, true);
     this.browser.removeEventListener("PluginClickToPlay", this, true);
     this.browser.removeEventListener("PluginPlayPreview", this, true);
     this.browser.removeEventListener("PluginNotFound", this, true);
-    this.browser.removeEventListener("MozScrolledAreaChanged", this, true);
+    this.browser.removeEventListener("pageshow", this, true);
 
     Services.obs.removeObserver(this, "before-first-paint");
     Services.prefs.removeObserver("browser.ui.zoom.force-user-scalable", this);
 
     // Make sure the previously selected panel remains selected. The selected panel of a deck is
     // not stable when panels are removed.
     let selectedPanel = BrowserApp.deck.selectedPanel;
     BrowserApp.deck.removeChild(this.browser);
@@ -7308,9 +7242,147 @@ var ExternalApps = {
       return apps.length > 0;
     }
   },
 
   openExternal: function(aElement) {
     let uri = NativeWindow.contextmenus._getLink(aElement);
     HelperApps.openUriInApp(uri);
   }
-}
+};
+
+var MemoryObserver = {
+  init: function() {
+    Services.obs.addObserver(this, "memory-pressure", false);
+    Services.obs.addObserver(this, "Memory:Dump", false);
+  },
+
+  uninit: function() {
+    Services.obs.removeObserver(this, "memory-pressure");
+    Services.obs.removeObserver(this, "Memory:Dump");
+  },
+
+  observe: function mo_observe(aSubject, aTopic, aData) {
+    if (aTopic == "memory-pressure") {
+      if (aData != "heap-minimize") {
+        this.handleLowMemory();
+      }
+      // The JS engine would normally GC on this notification, but since we
+      // disabled that in favor of this method (bug 669346), we should gc here.
+      // See bug 784040 for when this code was ported from XUL to native Fennec.
+      this.gc();
+    } else if (aTopic == "Memory:Dump") {
+      this.dumpMemoryStats(aData);
+    }
+  },
+
+  handleLowMemory: function() {
+    // do things to reduce memory usage here
+    let tabs = BrowserApp.tabs;
+    let selected = BrowserApp.selectedTab;
+    for (let i = 0; i < tabs.length; i++) {
+      if (tabs[i] != selected) {
+        this.zombify(tabs[i]);
+      }
+    }
+  },
+
+  zombify: function(tab) {
+    let browser = tab.browser;
+    let data = browser.__SS_data;
+    let extra = browser.__SS_extdata;
+
+    // We need this data to correctly create and position the new browser
+    // If this browser is already a zombie, fallback to the session data
+    let currentURL = browser.__SS_restore ? data.entries[0].url : browser.currentURI.spec;
+    let sibling = browser.nextSibling;
+
+    tab.destroy();
+    tab.create(currentURL, { sibling: sibling, zombifying: true, delayLoad: true });
+
+    // Reattach session store data and flag this browser so it is restored on select
+    browser = tab.browser;
+    browser.__SS_data = data;
+    browser.__SS_extdata = extra;
+    browser.__SS_restore = true;
+  },
+
+  gc: function() {
+    window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils).garbageCollect();
+    Cu.forceGC();
+  },
+
+  dumpMemoryStats: function(aLabel) {
+    // TODO once bug 788021 has landed, replace this code and just invoke that instead
+    // currently this code is hijacked from areweslimyet.com, original code can be found at:
+    // https://github.com/Nephyrin/MozAreWeSlimYet/blob/master/mozmill_endurance_test/performance.js
+    let memMgr = Cc["@mozilla.org/memory-reporter-manager;1"].getService(Ci.nsIMemoryReporterManager);
+
+    let timestamp = new Date();
+    let memory = {};
+
+    // These *should* be identical to the explicit/resident root node
+    // sum, AND the explicit/resident node explicit value (on newer builds),
+    // but we record all three so we can make sure the data is consistent
+    memory['manager_explicit'] = memMgr.explicit;
+    memory['manager_resident'] = memMgr.resident;
+
+    let knownHeap = 0;
+
+    function addReport(path, amount, kind, units) {
+      if (units !== undefined && units != Ci.nsIMemoryReporter.UNITS_BYTES)
+        // Unhandled. (old builds don't specify units, but use only bytes)
+        return;
+
+      if (memory[path])
+        memory[path] += amount;
+      else
+        memory[path] = amount;
+      if (kind !== undefined && kind == Ci.nsIMemoryReporter.KIND_HEAP
+          && path.indexOf('explicit/') == 0)
+        knownHeap += amount;
+    }
+
+    // Normal reporters
+    let reporters = memMgr.enumerateReporters();
+    while (reporters.hasMoreElements()) {
+      let r = reporters.getNext();
+      r instanceof Ci.nsIMemoryReporter;
+      if (r.path.length) {
+        addReport(r.path, r.amount, r.kind, r.units);
+      }
+    }
+
+    // Multireporters
+    if (memMgr.enumerateMultiReporters) {
+      let multireporters = memMgr.enumerateMultiReporters();
+
+      while (multireporters.hasMoreElements()) {
+        let mr = multireporters.getNext();
+        mr instanceof Ci.nsIMemoryMultiReporter;
+        mr.collectReports(function (proc, path, kind, units, amount, description, closure) {
+          addReport(path, amount, kind, units);
+        }, null);
+      }
+    }
+
+    let heapAllocated = memory['heap-allocated'];
+    // Called heap-used in older builds
+    if (!heapAllocated) heapAllocated = memory['heap-used'];
+    // This is how about:memory calculates derived value heap-unclassified, which
+    // is necessary to get a proper explicit value.
+    if (knownHeap && heapAllocated)
+      memory['explicit/heap-unclassified'] = memory['heap-allocated'] - knownHeap;
+
+    // If the build doesn't have a resident/explicit reporter, but does have
+    // the memMgr.explicit/resident field, use that
+    if (!memory['resident'])
+      memory['resident'] = memory['manager_resident']
+    if (!memory['explicit'])
+      memory['explicit'] = memory['manager_explicit']
+
+    let label = "[AboutMemoryDump|" + aLabel + "] ";
+    dump(label + timestamp);
+    for (let type in memory) {
+      dump(label + type + " = " + memory[type]);
+    }
+  },
+};
--- a/mobile/android/installer/package-manifest.in
+++ b/mobile/android/installer/package-manifest.in
@@ -278,18 +278,16 @@
 #ifdef MOZ_GTK2
 @BINPATH@/components/nsFilePicker.manifest
 @BINPATH@/components/nsFilePicker.js
 #endif
 @BINPATH@/components/nsHelperAppDlg.manifest
 @BINPATH@/components/nsHelperAppDlg.js
 @BINPATH@/components/nsDownloadManagerUI.manifest
 @BINPATH@/components/nsDownloadManagerUI.js
-@BINPATH@/components/nsProxyAutoConfig.manifest
-@BINPATH@/components/nsProxyAutoConfig.js
 @BINPATH@/components/NetworkGeolocationProvider.manifest
 @BINPATH@/components/NetworkGeolocationProvider.js
 @BINPATH@/components/GPSDGeolocationProvider.manifest
 @BINPATH@/components/GPSDGeolocationProvider.js
 @BINPATH@/components/nsSidebar.manifest
 @BINPATH@/components/nsSidebar.js
 @BINPATH@/components/extensions.manifest
 @BINPATH@/components/addonManager.js
--- a/mobile/xul/installer/package-manifest.in
+++ b/mobile/xul/installer/package-manifest.in
@@ -337,18 +337,16 @@
 #ifdef MOZ_GTK2
 @BINPATH@/components/nsFilePicker.manifest
 @BINPATH@/components/nsFilePicker.js
 #endif
 @BINPATH@/components/nsHelperAppDlg.manifest
 @BINPATH@/components/nsHelperAppDlg.js
 @BINPATH@/components/nsDownloadManagerUI.manifest
 @BINPATH@/components/nsDownloadManagerUI.js
-@BINPATH@/components/nsProxyAutoConfig.manifest
-@BINPATH@/components/nsProxyAutoConfig.js
 @BINPATH@/components/NetworkGeolocationProvider.manifest
 @BINPATH@/components/NetworkGeolocationProvider.js
 @BINPATH@/components/GPSDGeolocationProvider.manifest
 @BINPATH@/components/GPSDGeolocationProvider.js
 @BINPATH@/components/nsSidebar.manifest
 @BINPATH@/components/nsSidebar.js
 @BINPATH@/components/extensions.manifest
 @BINPATH@/components/addonManager.js
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -1116,16 +1116,19 @@ pref("network.dns.ipv4OnlyDomains", "");
 // This preference can be used to turn off IPv6 name lookups. See bug 68796.
 pref("network.dns.disableIPv6", false);
 
 // The grace period allows the DNS cache to use expired entries, while kicking off
 // a revalidation in the background. In seconds, but rounded to minutes in gecko.
 // Default to 30 days. (basically forever)
 pref("network.dnsCacheExpirationGracePeriod", 2592000);
 
+// This preference can be used to turn off DNS prefetch.
+pref("network.dns.disablePrefetch", false);
+
 // This preference controls whether or not URLs with UTF-8 characters are
 // escaped.  Set this preference to TRUE for strict RFC2396 conformance.
 pref("network.standard-url.escape-utf8", true);
 
 // This preference controls whether or not URLs are always encoded and sent as
 // UTF-8.
 pref("network.standard-url.encode-utf8", true);
 
--- a/netwerk/base/public/Makefile.in
+++ b/netwerk/base/public/Makefile.in
@@ -62,17 +62,16 @@ XPIDLSRCS	= \
 		nsIPrivateBrowsingService.idl \
 		nsIProgressEventSink.idl \
 		nsIPrompt.idl \
 		nsIProtocolProxyService.idl \
 		nsIProtocolProxyService2.idl \
 		nsIProtocolProxyFilter.idl \
 		nsIProtocolProxyCallback.idl \
 		nsIProxiedProtocolHandler.idl \
-		nsIProxyAutoConfig.idl \
 		nsIProxyInfo.idl \
 		nsITransport.idl \
 		nsISocketTransport.idl \
 		nsISocketTransportService.idl \
 		nsISpeculativeConnect.idl \
 		nsIServerSocket.idl \
 		nsIResumableChannel.idl \
 		nsIRequestObserverProxy.idl \
--- a/netwerk/base/public/nsIProtocolProxyService.idl
+++ b/netwerk/base/public/nsIProtocolProxyService.idl
@@ -12,34 +12,20 @@ interface nsIProtocolProxyFilter;
 interface nsIProxyInfo;
 interface nsIChannel;
 interface nsIURI;
 
 /**
  * nsIProtocolProxyService provides methods to access information about
  * various network proxies.
  */
-[scriptable, uuid(d7ec6237-162e-40f5-a2b4-46ccd5fa83c9)]
+[scriptable, uuid(e77c642b-026f-41ce-9b23-f829a6e3f300)]
 interface nsIProtocolProxyService : nsISupports
 {
-    /**
-     * This flag may be passed to the resolve method to request that it fail
-     * instead of block the calling thread.  Proxy Auto Config (PAC) may
-     * perform a synchronous DNS query, which may not return immediately.  So,
-     * calling resolve without this flag may result in locking up the calling
-     * thread for a lengthy period of time.
-     *
-     * By passing this flag to resolve, one can failover to asyncResolve to
-     * avoid locking up the calling thread if a PAC query is required.
-     *
-     * When this flag is passed to resolve, resolve may throw the exception
-     * NS_BASE_STREAM_WOULD_BLOCK to indicate that it failed due to this flag
-     * being present.
-     */
-    const unsigned long RESOLVE_NON_BLOCKING = 1 << 0;
+    /** Flag 1 << 0 is unused **/
 
     /**
      * When the proxy configuration is manual this flag may be passed to the
      * resolve and asyncResolve methods to request to prefer the SOCKS proxy
      * to HTTP ones.
      */
     const unsigned long RESOLVE_PREFER_SOCKS_PROXY = 1 << 1;
 
@@ -72,68 +58,47 @@ interface nsIProtocolProxyService : nsIS
     /**
      * When the proxy configuration is manual this flag may be passed to the
      * resolve and asyncResolve methods to that all methods will be tunneled via
      * CONNECT through the http proxy.
      */
     const unsigned long RESOLVE_ALWAYS_TUNNEL = (1 << 4);
 
     /**
-     * This method returns a nsIProxyInfo instance that identifies a proxy to
-     * be used for loading the given URI.  Otherwise, this method returns null
-     * indicating that a direct connection should be used.
+     * This method returns via callback a nsIProxyInfo instance that identifies
+     * a proxy to be used for loading the given URI.  Otherwise, this method returns
+     * null indicating that a direct connection should be used.
      *
      * @param aURI
      *        The URI to test.
      * @param aFlags
      *        A bit-wise combination of the RESOLVE_ flags defined above.  Pass
      *        0 to specify the default behavior.  Any additional bits that do
      *        not correspond to a RESOLVE_ flag are reserved for future use.
+     * @param aCallback
+     *        The object to be notified when the result is available.
+     *
+     * @return An object that can be used to cancel the asychronous operation.
+     *         If canceled, the cancelation status (aReason) will be forwarded
+     *         to the callback's onProxyAvailable method via the aStatus param.
      *
      * NOTE: If this proxy is unavailable, getFailoverForProxy may be called
      * to determine the correct secondary proxy to be used.
      *
      * NOTE: If the protocol handler for the given URI supports
      * nsIProxiedProtocolHandler, then the nsIProxyInfo instance returned from
      * resolve may be passed to the newProxiedChannel method to create a
      * nsIChannel to the given URI that uses the specified proxy.
      *
      * NOTE: However, if the nsIProxyInfo type is "http", then it means that
      * the given URI should be loaded using the HTTP protocol handler, which
      * also supports nsIProxiedProtocolHandler.
      *
-     * NOTE: If PAC is configured, and the PAC file has not yet been loaded,
-     * then this method will return a nsIProxyInfo instance with a type of
-     * "unknown" to indicate to the consumer that asyncResolve should be used
-     * to wait for the PAC file to finish loading.  Otherwise, the consumer
-     * may choose to treat the result as type "direct" if desired.
-     *
      * @see nsIProxiedProtocolHandler::newProxiedChannel 
      */
-    nsIProxyInfo resolve(in nsIURI aURI, in unsigned long aFlags);
-
-    /**
-     * This method is an asychronous version of the resolve method.  Unlike
-     * resolve, this method is guaranteed not to block the calling thread
-     * waiting for DNS queries to complete.  This method is intended as a
-     * substitute for resolve when the result is not needed immediately.
-     *
-     * @param aURI
-     *        The URI to test.
-     * @param aFlags
-     *        A bit-wise combination of the RESOLVE_ flags defined above.  Pass
-     *        0 to specify the default behavior.  Any additional bits that do
-     *        not correspond to a RESOLVE_ flag are reserved for future use.
-     * @param aCallback
-     *        The object to be notified when the result is available.
-     *
-     * @return An object that can be used to cancel the asychronous operation.
-     *         If canceled, the cancelation status (aReason) will be forwarded
-     *         to the callback's onProxyAvailable method via the aStatus param.
-     */
     nsICancelable asyncResolve(in nsIURI aURI, in unsigned long aFlags,
                                in nsIProtocolProxyCallback aCallback);
 
     /**
      * This method may be called to construct a nsIProxyInfo instance from
      * the given parameters.  This method may be useful in conjunction with
      * nsISocketTransportService::createTransport for creating, for example,
      * a SOCKS connection.
--- a/netwerk/base/public/nsIProtocolProxyService2.idl
+++ b/netwerk/base/public/nsIProtocolProxyService2.idl
@@ -4,17 +4,26 @@
  * 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 "nsIProtocolProxyService.idl"
 
 /**
  * An extension of nsIProtocolProxyService
  */
-[scriptable, uuid(dbd9565d-29b1-437a-bff5-2fc339e2c5df)]
+[scriptable, uuid(bed3702d-9374-4804-a20f-32baed8e2954)]
 interface nsIProtocolProxyService2 : nsIProtocolProxyService
 {
   /**
    * Call this method to cause the PAC file (if any is configured) to be
    * reloaded.  The PAC file is loaded asynchronously.
    */
   void reloadPAC();
+
+  /**
+   * This exists so Java(tm) can migrate to an asynchronous interface.
+   * Do not use this unless you are the plugin interface, and even then you
+   * ought to feel horribly guilty because you will create main thread jank.
+   *
+   * No documentation - it is deprecated!
+   **/
+  nsIProxyInfo deprecatedBlockingResolve(in nsIURI aURI, in unsigned long aFlags);
 };
--- a/netwerk/base/public/nsIProxiedProtocolHandler.idl
+++ b/netwerk/base/public/nsIProxiedProtocolHandler.idl
@@ -4,17 +4,31 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsIProtocolHandler.idl"
 
 interface nsIChannel;
 interface nsIURI;
 interface nsIProxyInfo;
 
-[scriptable, uuid(0a24fed4-1dd2-11b2-a75c-9f8b9a8f9ba7)]
+[scriptable, uuid(2b63fe69-b0fc-48f2-a2df-adb795a4ce5c)]
 interface nsIProxiedProtocolHandler : nsIProtocolHandler
 {
     /** Create a new channel with the given proxyInfo
      *
+     * @param uri the channel uri
+     * @param proxyInfo any proxy information that has already been determined,
+     *        or null if channel should later determine the proxy on its own using
+     *        proxyResolveFlags/proxyURI
+     * @param proxyResolveFlags used if the proxy is later determined
+     *        from nsIProtocolProxyService::asyncResolve
+     * @param proxyURI used if the proxy is later determined from
+     *        nsIProtocolProxyService::asyncResolve with this as the proxyURI name.
+     *        Generally this is the same as uri (or null which has the same
+     *        effect), except in the case of websockets which wants to bootstrap
+     *        to an http:// channel but make its proxy determination based on
+     *        a ws:// uri.
      */
-    nsIChannel newProxiedChannel(in nsIURI uri, in nsIProxyInfo proxyInfo);
+    nsIChannel newProxiedChannel(in nsIURI uri, in nsIProxyInfo proxyInfo,
+                                 in unsigned long proxyResolveFlags,
+                                 in nsIURI proxyURI);
 };
 
deleted file mode 100644
--- a/netwerk/base/public/nsIProxyAutoConfig.idl
+++ /dev/null
@@ -1,68 +0,0 @@
-/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* 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 "nsISupports.idl"
-
-/** 
- * The nsIProxyAutoConfig interface is used for setting arbitrary proxy
- * configurations based on the specified URL. 
- *
- * Note this interface wraps (at least in the implementation) the older
- * hacks of proxy auto config. 
- *
- *  - Gagan Saksena 04/23/00 
- */
-
-[scriptable, uuid(a42619df-0a1c-46fb-8154-0e9b8f8f1ea8)]
-interface nsIProxyAutoConfig : nsISupports
-{
-    /**
-     * This method initializes the object.  This method may be called multiple
-     * times.  If either parameter is an empty value, then the object is
-     * reset to its initial state.
-     *
-     * @param aPACURI
-     *        URI used to fetch the PAC script.  This is needed for properly
-     *        constructing the JS sandbox used to evaluate the PAC script.
-     * @param aPACScript
-     *        Javascript program text.
-     */
-    void init(in ACString aPACURI, in AString aPACScript);
-
-    /**
-     * Get the proxy string for the specified URI.  The proxy string is
-     * given by the following:
-     *   
-     *   result      = proxy-spec *( proxy-sep proxy-spec )
-     *   proxy-spec  = direct-type | proxy-type LWS proxy-host [":" proxy-port]
-     *   direct-type = "DIRECT"
-     *   proxy-type  = "PROXY" | "SOCKS" | "SOCKS4" | "SOCKS5"
-     *   proxy-sep   = ";" LWS
-     *   proxy-host  = hostname | ipv4-address-literal
-     *   proxy-port  = <any 16-bit unsigned integer>
-     *   LWS         = *( SP | HT )
-     *   SP          = <US-ASCII SP, space (32)>
-     *   HT          = <US-ASCII HT, horizontal-tab (9)>
-     *
-     * NOTE: direct-type and proxy-type are case insensitive
-     * NOTE: SOCKS implies SOCKS4
-     *
-     * Examples:
-     *   "PROXY proxy1.foo.com:8080; PROXY proxy2.foo.com:8080; DIRECT"
-     *   "SOCKS socksproxy"
-     *   "DIRECT"
-     *
-     * XXX add support for IPv6 address literals.
-     * XXX quote whatever the official standard is for PAC.
-     *
-     * @param aTestURI
-     *        The URI as an ASCII string to test.
-     * @param aTestHost
-     *        The ASCII hostname to test.
-     *
-     * @return PAC result string as defined above.
-     */
-    ACString getProxyForURI(in ACString aTestURI, in ACString aTestHost);
-};
--- a/netwerk/base/public/nsISystemProxySettings.idl
+++ b/netwerk/base/public/nsISystemProxySettings.idl
@@ -8,22 +8,36 @@
 
 /** 
  * This interface allows the proxy code to use platform-specific proxy
  * settings when the proxy preference is set to "automatic discovery". This service
  * acts like a PAC parser to netwerk, but it will actually read the system settings and
  * either return the proper proxy data from the autoconfig URL specified in the system proxy,
  * or generate proxy data based on the system's manual proxy settings.
  */
-[scriptable, uuid(a9f3ae38-b769-4e0b-9317-578388e326c9)]
+[scriptable, uuid(971591cd-277e-409a-bbf6-0a79879cd307)]
 interface nsISystemProxySettings : nsISupports
 {
     /**
+     * Whether or not it is appropriate to execute getProxyForURI off the main thread.
+     * If that method can block (e.g. for WPAD as windows does) then it must be
+     * not mainThreadOnly to avoid creating main thread jank. The main thread only option is
+     * provided for implementations that do not block but use other main thread only
+     * functions such as dbus.
+     */
+    readonly attribute bool mainThreadOnly;
+
+    /**
      * If non-empty, use this PAC file. If empty, call getProxyForURI instead.
      */
     readonly attribute AUTF8String PACURI;
     
     /**
-     * See nsIProxyAutoConfig::getProxyForURI; this function behaves exactly
-     * the same way.
+     * See ProxyAutoConfig::getProxyForURI; this function behaves similarly except
+     * a more relaxed return string is allowed that includes full urls instead of just
+     * host:port syntax. e.g. "PROXY http://www.foo.com:8080" instead of
+     * "PROXY www.foo.com:8080"
      */
-    AUTF8String getProxyForURI(in nsIURI aURI);
+    AUTF8String getProxyForURI(in AUTF8String testSpec,
+                               in AUTF8String testScheme,
+                               in AUTF8String testHost,
+                               in int32_t     testPort);
 };
--- a/netwerk/base/public/nsITimedChannel.idl
+++ b/netwerk/base/public/nsITimedChannel.idl
@@ -14,33 +14,33 @@ native TimeStamp(mozilla::TimeStamp);
 // All properties return zero if the value is not available
 [scriptable, uuid(c259b593-a9bf-4d08-8149-ef89e1977dc4)]
 interface nsITimedChannel : nsISupports {
   // Set this attribute to true to enable collection of timing data.
   // channelCreationTime will be available even with this attribute set to
   // false.
   attribute boolean timingEnabled;
 
-  [notxpcom] readonly attribute TimeStamp channelCreation;
-  [notxpcom] readonly attribute TimeStamp asyncOpen;
+  [noscript] readonly attribute TimeStamp channelCreation;
+  [noscript] readonly attribute TimeStamp asyncOpen;
 
   // The following are only set when the document is not (only) read from the
   // cache
-  [notxpcom] readonly attribute TimeStamp domainLookupStart;
-  [notxpcom] readonly attribute TimeStamp domainLookupEnd;
-  [notxpcom] readonly attribute TimeStamp connectStart;
-  [notxpcom] readonly attribute TimeStamp connectEnd;
-  [notxpcom] readonly attribute TimeStamp requestStart;
-  [notxpcom] readonly attribute TimeStamp responseStart;
-  [notxpcom] readonly attribute TimeStamp responseEnd;
+  [noscript] readonly attribute TimeStamp domainLookupStart;
+  [noscript] readonly attribute TimeStamp domainLookupEnd;
+  [noscript] readonly attribute TimeStamp connectStart;
+  [noscript] readonly attribute TimeStamp connectEnd;
+  [noscript] readonly attribute TimeStamp requestStart;
+  [noscript] readonly attribute TimeStamp responseStart;
+  [noscript] readonly attribute TimeStamp responseEnd;
 
   // The following are only set if the document is (partially) read from the
   // cache
-  [notxpcom] readonly attribute TimeStamp cacheReadStart;
-  [notxpcom] readonly attribute TimeStamp cacheReadEnd;
+  [noscript] readonly attribute TimeStamp cacheReadStart;
+  [noscript] readonly attribute TimeStamp cacheReadEnd;
 
   // All following are PRTime versions of the above.
   readonly attribute PRTime channelCreationTime;
   readonly attribute PRTime asyncOpenTime;
   readonly attribute PRTime domainLookupStartTime;
   readonly attribute PRTime domainLookupEndTime;
   readonly attribute PRTime connectStartTime;
   readonly attribute PRTime connectEndTime;
--- a/netwerk/base/public/nsNetUtil.h
+++ b/netwerk/base/public/nsNetUtil.h
@@ -847,50 +847,16 @@ NS_GetReferrerFromChannel(nsIChannel *ch
         rv = chan->GetReferrer(referrer);
         if (NS_FAILED(rv))
           *referrer = nullptr;
       }
     }
     return rv;
 }
 
-#ifdef MOZILLA_INTERNAL_API
-inline nsresult
-NS_ExamineForProxy(const char    *scheme,
-                   const char    *host,
-                   int32_t        port, 
-                   nsIProxyInfo **proxyInfo)
-{
-    nsresult rv;
-    nsCOMPtr<nsIProtocolProxyService> pps =
-            do_GetService(NS_PROTOCOLPROXYSERVICE_CONTRACTID, &rv);
-    if (NS_SUCCEEDED(rv)) {
-        nsAutoCString spec(scheme);
-        spec.Append("://");
-        spec.Append(host);
-        spec.Append(':');
-        spec.AppendInt(port);
-        // XXXXX - Under no circumstances whatsoever should any code which
-        // wants a uri do this. I do this here because I do not, in fact,
-        // actually want a uri (the dummy uris created here may not be 
-        // syntactically valid for the specific protocol), and all we need
-        // is something which has a valid scheme, hostname, and a string
-        // to pass to PAC if needed - bbaetz
-        nsCOMPtr<nsIURI> uri =
-                do_CreateInstance(NS_STANDARDURL_CONTRACTID, &rv);
-        if (NS_SUCCEEDED(rv)) {
-            rv = uri->SetSpec(spec);
-            if (NS_SUCCEEDED(rv))
-                rv = pps->Resolve(uri, 0, proxyInfo);
-        }
-    }
-    return rv;
-}
-#endif
-
 inline nsresult
 NS_ParseContentType(const nsACString &rawContentType,
                     nsCString        &contentType,
                     nsCString        &contentCharset)
 {
     // contentCharset is left untouched if not present in rawContentType
     nsresult rv;
     nsCOMPtr<nsINetUtil> util = do_GetNetUtil(&rv);
--- a/netwerk/base/src/Makefile.in
+++ b/netwerk/base/src/Makefile.in
@@ -61,18 +61,21 @@ CPPSRCS		= \
 		nsNetAddr.cpp \
 		nsNetStrings.cpp \
 		nsBase64Encoder.cpp \
 		nsSerializationHelper.cpp \
 		nsDNSPrefetch.cpp \
 		RedirectChannelRegistrar.cpp \
 		nsPreloadedStream.cpp \
 		nsStreamListenerWrapper.cpp \
+		ProxyAutoConfig.cpp \
 		$(NULL)
 
+LOCAL_INCLUDES	+= -I$(topsrcdir)/dom/base
+
 ifeq ($(MOZ_WIDGET_TOOLKIT),os2)
 	CPPSRCS += nsURLHelperOS2.cpp
 else
 ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
 	CPPSRCS += nsURLHelperWin.cpp
 	CPPSRCS += nsNativeConnectionHelper.cpp
 	CPPSRCS += nsAutodialWin.cpp
 else
@@ -92,21 +95,16 @@ ifdef MOZ_ENABLE_LIBCONIC
 endif
 ifdef MOZ_ENABLE_QTNETWORK
 	CPPSRCS += nsAutodialQt.cpp
 	LOCAL_INCLUDES += -I$(srcdir)/../../system/qt
 	OS_INCLUDES += $(MOZ_QT_CFLAGS)
 endif
 endif
 
-EXTRA_COMPONENTS = \
-		$(srcdir)/nsProxyAutoConfig.js \
-		$(srcdir)/nsProxyAutoConfig.manifest \
-		$(NULL)
-
 EXTRA_JS_MODULES = \
 		NetUtil.jsm \
 		$(NULL)
 
 # we don't want the shared lib, but we want to force the creation of a
 # static lib.
 FORCE_STATIC_LIB = 1
 
new file mode 100644
--- /dev/null
+++ b/netwerk/base/src/ProxyAutoConfig.cpp
@@ -0,0 +1,791 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* 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 "ProxyAutoConfig.h"
+#include "nsICancelable.h"
+#include "nsIDNSListener.h"
+#include "nsIDNSRecord.h"
+#include "nsIDNSService.h"
+#include "nsNetUtil.h"
+#include "nsThreadUtils.h"
+#include "nsIConsoleService.h"
+#include "nsJSUtils.h"
+#include "prnetdb.h"
+#include "nsITimer.h"
+
+namespace mozilla {
+namespace net {
+
+// These are some global helper symbols the PAC format requires that we provide that
+// are initialized as part of the global javascript context used for PAC evaluations.
+// Additionally dnsResolve(host) and myIpAddress() are supplied in the same context
+// but are implemented as c++ helpers. proxyAlert(msg) is similarly defined, but that
+// is a gecko specific extension.
+
+static const char *sPacUtils =
+  "function dnsDomainIs(host, domain) {\n"
+  "    return (host.length >= domain.length &&\n"
+  "            host.substring(host.length - domain.length) == domain);\n"
+  "}\n"
+  ""
+  "function dnsDomainLevels(host) {\n"
+  "    return host.split('.').length - 1;\n"
+  "}\n"
+  ""
+  "function convert_addr(ipchars) {\n"
+  "    var bytes = ipchars.split('.');\n"
+  "    var result = ((bytes[0] & 0xff) << 24) |\n"
+  "                 ((bytes[1] & 0xff) << 16) |\n"
+  "                 ((bytes[2] & 0xff) <<  8) |\n"
+  "                  (bytes[3] & 0xff);\n"
+  "    return result;\n"
+  "}\n"
+  ""
+  "function isInNet(ipaddr, pattern, maskstr) {\n"
+  "    var test = /^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$/.exec(ipaddr);\n"
+  "    if (test == null) {\n"
+  "        ipaddr = dnsResolve(ipaddr);\n"
+  "        if (ipaddr == null)\n"
+  "            return false;\n"
+  "    } else if (test[1] > 255 || test[2] > 255 || \n"
+  "               test[3] > 255 || test[4] > 255) {\n"
+  "        return false;    // not an IP address\n"
+  "    }\n"
+  "    var host = convert_addr(ipaddr);\n"
+  "    var pat  = convert_addr(pattern);\n"
+  "    var mask = convert_addr(maskstr);\n"
+  "    return ((host & mask) == (pat & mask));\n"
+  "    \n"
+  "}\n"
+  ""
+  "function isPlainHostName(host) {\n"
+  "    return (host.search('\\\\.') == -1);\n"
+  "}\n"
+  ""
+  "function isResolvable(host) {\n"
+  "    var ip = dnsResolve(host);\n"
+  "    return (ip != null);\n"
+  "}\n"
+  ""
+  "function localHostOrDomainIs(host, hostdom) {\n"
+  "    return (host == hostdom) ||\n"
+  "           (hostdom.lastIndexOf(host + '.', 0) == 0);\n"
+  "}\n"
+  ""
+  "function shExpMatch(url, pattern) {\n"
+  "   pattern = pattern.replace(/\\./g, '\\\\.');\n"
+  "   pattern = pattern.replace(/\\*/g, '.*');\n"
+  "   pattern = pattern.replace(/\\?/g, '.');\n"
+  "   var newRe = new RegExp('^'+pattern+'$');\n"
+  "   return newRe.test(url);\n"
+  "}\n"
+  ""
+  "var wdays = {SUN: 0, MON: 1, TUE: 2, WED: 3, THU: 4, FRI: 5, SAT: 6};\n"
+  "var months = {JAN: 0, FEB: 1, MAR: 2, APR: 3, MAY: 4, JUN: 5, JUL: 6, AUG: 7, SEP: 8, OCT: 9, NOV: 10, DEC: 11};\n"
+  ""
+  "function weekdayRange() {\n"
+  "    function getDay(weekday) {\n"
+  "        if (weekday in wdays) {\n"
+  "            return wdays[weekday];\n"
+  "        }\n"
+  "        return -1;\n"
+  "    }\n"
+  "    var date = new Date();\n"
+  "    var argc = arguments.length;\n"
+  "    var wday;\n"
+  "    if (argc < 1)\n"
+  "        return false;\n"
+  "    if (arguments[argc - 1] == 'GMT') {\n"
+  "        argc--;\n"
+  "        wday = date.getUTCDay();\n"
+  "    } else {\n"
+  "        wday = date.getDay();\n"
+  "    }\n"
+  "    var wd1 = getDay(arguments[0]);\n"
+  "    var wd2 = (argc == 2) ? getDay(arguments[1]) : wd1;\n"
+  "    return (wd1 == -1 || wd2 == -1) ? false\n"
+  "                                    : (wd1 <= wday && wday <= wd2);\n"
+  "}\n"
+  ""
+  "function dateRange() {\n"
+  "    function getMonth(name) {\n"
+  "        if (name in months) {\n"
+  "            return months[name];\n"
+  "        }\n"
+  "        return -1;\n"
+  "    }\n"
+  "    var date = new Date();\n"
+  "    var argc = arguments.length;\n"
+  "    if (argc < 1) {\n"
+  "        return false;\n"
+  "    }\n"
+  "    var isGMT = (arguments[argc - 1] == 'GMT');\n"
+  "\n"
+  "    if (isGMT) {\n"
+  "        argc--;\n"
+  "    }\n"
+  "    // function will work even without explict handling of this case\n"
+  "    if (argc == 1) {\n"
+  "        var tmp = parseInt(arguments[0]);\n"
+  "        if (isNaN(tmp)) {\n"
+  "            return ((isGMT ? date.getUTCMonth() : date.getMonth()) ==\n"
+  "                     getMonth(arguments[0]));\n"
+  "        } else if (tmp < 32) {\n"
+  "            return ((isGMT ? date.getUTCDate() : date.getDate()) == tmp);\n"
+  "        } else { \n"
+  "            return ((isGMT ? date.getUTCFullYear() : date.getFullYear()) ==\n"
+  "                     tmp);\n"
+  "        }\n"
+  "    }\n"
+  "    var year = date.getFullYear();\n"
+  "    var date1, date2;\n"
+  "    date1 = new Date(year,  0,  1,  0,  0,  0);\n"
+  "    date2 = new Date(year, 11, 31, 23, 59, 59);\n"
+  "    var adjustMonth = false;\n"
+  "    for (var i = 0; i < (argc >> 1); i++) {\n"
+  "        var tmp = parseInt(arguments[i]);\n"
+  "        if (isNaN(tmp)) {\n"
+  "            var mon = getMonth(arguments[i]);\n"
+  "            date1.setMonth(mon);\n"
+  "        } else if (tmp < 32) {\n"
+  "            adjustMonth = (argc <= 2);\n"
+  "            date1.setDate(tmp);\n"
+  "        } else {\n"
+  "            date1.setFullYear(tmp);\n"
+  "        }\n"
+  "    }\n"
+  "    for (var i = (argc >> 1); i < argc; i++) {\n"
+  "        var tmp = parseInt(arguments[i]);\n"
+  "        if (isNaN(tmp)) {\n"
+  "            var mon = getMonth(arguments[i]);\n"
+  "            date2.setMonth(mon);\n"
+  "        } else if (tmp < 32) {\n"
+  "            date2.setDate(tmp);\n"
+  "        } else {\n"
+  "            date2.setFullYear(tmp);\n"
+  "        }\n"
+  "    }\n"
+  "    if (adjustMonth) {\n"
+  "        date1.setMonth(date.getMonth());\n"
+  "        date2.setMonth(date.getMonth());\n"
+  "    }\n"
+  "    if (isGMT) {\n"
+  "    var tmp = date;\n"
+  "        tmp.setFullYear(date.getUTCFullYear());\n"
+  "        tmp.setMonth(date.getUTCMonth());\n"
+  "        tmp.setDate(date.getUTCDate());\n"
+  "        tmp.setHours(date.getUTCHours());\n"
+  "        tmp.setMinutes(date.getUTCMinutes());\n"
+  "        tmp.setSeconds(date.getUTCSeconds());\n"
+  "        date = tmp;\n"
+  "    }\n"
+  "    return ((date1 <= date) && (date <= date2));\n"
+  "}\n"
+  ""
+  "function timeRange() {\n"
+  "    var argc = arguments.length;\n"
+  "    var date = new Date();\n"
+  "    var isGMT= false;\n"
+  ""
+  "    if (argc < 1) {\n"
+  "        return false;\n"
+  "    }\n"
+  "    if (arguments[argc - 1] == 'GMT') {\n"
+  "        isGMT = true;\n"
+  "        argc--;\n"
+  "    }\n"
+  "\n"
+  "    var hour = isGMT ? date.getUTCHours() : date.getHours();\n"
+  "    var date1, date2;\n"
+  "    date1 = new Date();\n"
+  "    date2 = new Date();\n"
+  "\n"
+  "    if (argc == 1) {\n"
+  "        return (hour == arguments[0]);\n"
+  "    } else if (argc == 2) {\n"
+  "        return ((arguments[0] <= hour) && (hour <= arguments[1]));\n"
+  "    } else {\n"
+  "        switch (argc) {\n"
+  "        case 6:\n"
+  "            date1.setSeconds(arguments[2]);\n"
+  "            date2.setSeconds(arguments[5]);\n"
+  "        case 4:\n"
+  "            var middle = argc >> 1;\n"
+  "            date1.setHours(arguments[0]);\n"
+  "            date1.setMinutes(arguments[1]);\n"
+  "            date2.setHours(arguments[middle]);\n"
+  "            date2.setMinutes(arguments[middle + 1]);\n"
+  "            if (middle == 2) {\n"
+  "                date2.setSeconds(59);\n"
+  "            }\n"
+  "            break;\n"
+  "        default:\n"
+  "          throw 'timeRange: bad number of arguments'\n"
+  "        }\n"
+  "    }\n"
+  "\n"
+  "    if (isGMT) {\n"
+  "        date.setFullYear(date.getUTCFullYear());\n"
+  "        date.setMonth(date.getUTCMonth());\n"
+  "        date.setDate(date.getUTCDate());\n"
+  "        date.setHours(date.getUTCHours());\n"
+  "        date.setMinutes(date.getUTCMinutes());\n"
+  "        date.setSeconds(date.getUTCSeconds());\n"
+  "    }\n"
+  "    return ((date1 <= date) && (date <= date2));\n"
+  "}\n"
+  "";
+
+// sRunning is defined for the helper functions only while the
+// Javascript engine is running and the PAC object cannot be deleted
+// or reset.
+static ProxyAutoConfig *sRunning = nullptr;
+
+// The PACResolver is used for dnsResolve()
+class PACResolver MOZ_FINAL : public nsIDNSListener
+                            , public nsITimerCallback
+{
+public:
+  NS_DECL_ISUPPORTS
+
+  PACResolver()
+    : mStatus(NS_ERROR_FAILURE)
+  {
+  }
+
+  // nsIDNSListener
+  NS_IMETHODIMP OnLookupComplete(nsICancelable *request,
+                                 nsIDNSRecord *record,
+                                 nsresult status)
+  {
+    if (mTimer) {
+      mTimer->Cancel();
+      mTimer = nullptr;
+    }
+
+    mRequest = nullptr;
+    mStatus = status;
+    mResponse = record;
+    return NS_OK;
+  }
+
+  // nsITimerCallback
+  NS_IMETHODIMP Notify(nsITimer *timer) 
+  {
+    if (mRequest)
+      mRequest->Cancel(NS_ERROR_NET_TIMEOUT);
+    mTimer = nullptr;
+    return NS_OK;
+  }
+
+  nsresult                mStatus;
+  nsCOMPtr<nsICancelable> mRequest;
+  nsCOMPtr<nsIDNSRecord>  mResponse;
+  nsCOMPtr<nsITimer>      mTimer;
+};
+NS_IMPL_THREADSAFE_ISUPPORTS2(PACResolver, nsIDNSListener, nsITimerCallback)
+
+static
+void PACLogToConsole(nsString &aMessage)
+{
+  nsCOMPtr<nsIConsoleService> consoleService =
+    do_GetService(NS_CONSOLESERVICE_CONTRACTID);
+  if (!consoleService)
+    return;
+
+  consoleService->LogStringMessage(aMessage.get());
+}
+
+// Javascript errors are logged to the main error console
+static void
+PACErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
+{
+  nsString formattedMessage(NS_LITERAL_STRING("PAC Execution Error: "));
+  formattedMessage += report->ucmessage;
+  formattedMessage += NS_LITERAL_STRING(" [");
+  formattedMessage += report->uclinebuf;
+  formattedMessage += NS_LITERAL_STRING("]");
+  PACLogToConsole(formattedMessage);
+}
+
+// timeout of 0 means the normal necko timeout strategy, otherwise the dns request
+// will be canceled after aTimeout milliseconds
+static
+JSBool PACResolve(const nsCString &aHostName, PRNetAddr *aNetAddr,
+                  unsigned int aTimeout)
+{
+  if (!sRunning) {
+    NS_WARNING("PACResolve without a running ProxyAutoConfig object");
+    return false;
+  }
+
+  return sRunning->ResolveAddress(aHostName, aNetAddr, aTimeout);
+}
+
+bool
+ProxyAutoConfig::ResolveAddress(const nsCString &aHostName,
+                                PRNetAddr *aNetAddr,
+                                unsigned int aTimeout)
+{
+  nsCOMPtr<nsIDNSService> dns = do_GetService(NS_DNSSERVICE_CONTRACTID);
+  if (!dns)
+    return false;
+
+  nsRefPtr<PACResolver> helper = new PACResolver();
+
+  if (NS_FAILED(dns->AsyncResolve(aHostName, 0, helper,
+                                  NS_GetCurrentThread(),
+                                  getter_AddRefs(helper->mRequest))))
+    return false;
+
+  if (aTimeout && helper->mRequest) {
+    if (!mTimer)
+      mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
+    if (mTimer) {
+      mTimer->InitWithCallback(helper, aTimeout, nsITimer::TYPE_ONE_SHOT);
+      helper->mTimer = mTimer;
+    }
+  }
+
+  // Spin the event loop of the pac thread until lookup is complete.
+  // nsPACman is responsible for keeping a queue and only allowing
+  // one PAC execution at a time even when it is called re-entrantly.
+  while (helper->mRequest)
+    NS_ProcessNextEvent(NS_GetCurrentThread());
+
+  if (NS_FAILED(helper->mStatus) ||
+      NS_FAILED(helper->mResponse->GetNextAddr(0, aNetAddr)))
+    return false;
+  return true;
+}
+
+static
+bool PACResolveToString(const nsCString &aHostName,
+                        nsCString &aDottedDecimal,
+                        unsigned int aTimeout)
+{
+  PRNetAddr netAddr;
+  if (!PACResolve(aHostName, &netAddr, aTimeout))
+    return false;
+
+  char dottedDecimal[128];
+  if (PR_NetAddrToString(&netAddr, dottedDecimal, sizeof(dottedDecimal)) != PR_SUCCESS)
+    return false;
+
+  aDottedDecimal.Assign(dottedDecimal);
+  return true;
+}
+
+// dnsResolve(host) javascript implementation
+static
+JSBool PACDnsResolve(JSContext *cx, unsigned int argc, jsval *vp)
+{
+  if (NS_IsMainThread()) {
+    NS_WARNING("DNS Resolution From PAC on Main Thread. How did that happen?");
+    return false;
+  }
+
+  JSString *arg1 = nullptr;
+  if (!JS_ConvertArguments(cx, argc, JS_ARGV(cx, vp), "S", &arg1))
+    return false;
+
+  nsDependentJSString hostName;
+  nsAutoCString dottedDecimal;
+
+  if (!hostName.init(cx, arg1))
+    return false;
+  if (!PACResolveToString(NS_ConvertUTF16toUTF8(hostName), dottedDecimal, 0))
+    return false;
+
+  JSString *dottedDecimalString = JS_NewStringCopyZ(cx, dottedDecimal.get());
+  JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(dottedDecimalString));
+  return true;
+}
+
+// myIpAddress() javascript implementation
+static
+JSBool PACMyIpAddress(JSContext *cx, unsigned int argc, jsval *vp)
+{
+  if (NS_IsMainThread()) {
+    NS_WARNING("DNS Resolution From PAC on Main Thread. How did that happen?");
+    return false;
+  }
+
+  if (!sRunning) {
+    NS_WARNING("PAC myIPAddress without a running ProxyAutoConfig object");
+    return JS_FALSE;
+  }
+
+  return sRunning->MyIPAddress(vp);
+}
+
+// proxyAlert(msg) javascript implementation
+static
+JSBool PACProxyAlert(JSContext *cx, unsigned int argc, jsval *vp)
+{
+  JSString *arg1 = nullptr;
+  if (!JS_ConvertArguments(cx, argc, JS_ARGV(cx, vp), "S", &arg1))
+    return false;
+
+  nsDependentJSString message;
+  if (!message.init(cx, arg1))
+    return false;
+
+  nsString alertMessage;
+  alertMessage.SetCapacity(32 + message.Length());
+  alertMessage += NS_LITERAL_STRING("PAC-alert: ");
+  alertMessage += message;
+  PACLogToConsole(alertMessage);
+
+  JS_SET_RVAL(cx, vp, JSVAL_VOID);  /* return undefined */
+  return true;
+}
+
+static JSFunctionSpec PACGlobalFunctions[] = {
+  JS_FS("dnsResolve", PACDnsResolve, 1, 0),
+  JS_FS("myIpAddress", PACMyIpAddress, 0, 0),
+  JS_FS("proxyAlert", PACProxyAlert, 1, 0),
+  JS_FS_END
+};
+
+// JSRuntimeWrapper is a c++ object that manages the runtime and context
+// for the JS engine used on the PAC thread. It is initialized and destroyed
+// on the PAC thread.
+class JSRuntimeWrapper
+{
+ public:
+  static JSRuntimeWrapper *Create()
+  {
+    JSRuntimeWrapper *entry = new JSRuntimeWrapper();
+
+    if (NS_FAILED(entry->Init())) {
+      delete entry;
+      return nullptr;
+    }
+
+    return entry;
+  }
+
+  JSContext *Context() const
+  {
+    return mContext;
+  }
+
+  JSObject *Global() const
+  {
+    return mGlobal;
+  }
+
+  ~JSRuntimeWrapper()
+  {
+    MOZ_COUNT_DTOR(JSRuntimeWrapper);
+    if (mContext) {
+      JS_DestroyContext(mContext);
+    }
+
+    if (mRuntime) {
+      JS_DestroyRuntime(mRuntime);
+    }
+  }
+
+  void SetOK()
+  {
+    mOK = true;
+  }
+
+  bool IsOK()
+  {
+    return mOK;
+  }
+
+private:
+  static const unsigned sRuntimeHeapSize = 2 << 20;
+
+  JSRuntime *mRuntime;
+  JSContext *mContext;
+  JSObject  *mGlobal;
+  bool      mOK;
+
+  static JSClass sGlobalClass;
+
+  JSRuntimeWrapper()
+    : mRuntime(nullptr), mContext(nullptr), mGlobal(nullptr), mOK(false)
+  {
+      MOZ_COUNT_CTOR(JSRuntimeWrapper);
+  }
+
+  nsresult Init()
+  {
+    mRuntime = JS_NewRuntime(sRuntimeHeapSize);
+    NS_ENSURE_TRUE(mRuntime, NS_ERROR_OUT_OF_MEMORY);
+
+    mContext = JS_NewContext(mRuntime, 0);
+    NS_ENSURE_TRUE(mContext, NS_ERROR_OUT_OF_MEMORY);
+
+    JSAutoRequest ar(mContext);
+
+    mGlobal = JS_NewGlobalObject(mContext, &sGlobalClass, nullptr);
+    NS_ENSURE_TRUE(mGlobal, NS_ERROR_OUT_OF_MEMORY);
+
+    JS_SetGlobalObject(mContext, mGlobal);
+    JS_InitStandardClasses(mContext, mGlobal);
+
+    JS_SetVersion(mContext, JSVERSION_LATEST);
+    JS_SetErrorReporter(mContext, PACErrorReporter);
+
+    if (!JS_DefineFunctions(mContext, mGlobal, PACGlobalFunctions))
+      return NS_ERROR_FAILURE;
+
+    return NS_OK;
+  }
+};
+
+JSClass JSRuntimeWrapper::sGlobalClass = {
+  "PACResolutionThreadGlobal",
+  JSCLASS_GLOBAL_FLAGS,
+  JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
+  JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub
+};
+
+nsresult
+ProxyAutoConfig::Init(const nsCString &aPACURI,
+                      const nsCString &aPACScript)
+{
+  mPACURI = aPACURI;
+  mPACScript = sPacUtils;
+  mPACScript.Append(aPACScript);
+
+  if (!sRunning)
+    return SetupJS();
+
+  mJSNeedsSetup = true;
+  return NS_OK;
+}
+
+nsresult
+ProxyAutoConfig::SetupJS()
+{
+  mJSNeedsSetup = false;
+  NS_ABORT_IF_FALSE(!sRunning, "JIT is running");
+
+  delete mJSRuntime;
+  mJSRuntime = nullptr;
+
+  if (mPACScript.IsEmpty())
+    return NS_ERROR_FAILURE;
+
+  mJSRuntime = JSRuntimeWrapper::Create();
+  if (!mJSRuntime)
+    return NS_ERROR_FAILURE;
+
+  JSAutoRequest ar(mJSRuntime->Context());
+
+  JSScript *script = JS_CompileScript(mJSRuntime->Context(),
+                                      mJSRuntime->Global(),
+                                      mPACScript.get(), mPACScript.Length(),
+                                      mPACURI.get(), 1);
+  if (!script ||
+      !JS_ExecuteScript(mJSRuntime->Context(), mJSRuntime->Global(), script, nullptr)) {
+    nsString alertMessage(NS_LITERAL_STRING("PAC file failed to install from "));
+    alertMessage += NS_ConvertUTF8toUTF16(mPACURI);
+    PACLogToConsole(alertMessage);
+    return NS_ERROR_FAILURE;
+  }
+
+  mJSRuntime->SetOK();
+  nsString alertMessage(NS_LITERAL_STRING("PAC file installed from "));
+  alertMessage += NS_ConvertUTF8toUTF16(mPACURI);
+  PACLogToConsole(alertMessage);
+
+  // we don't need these now
+  mPACScript.Truncate();
+  mPACURI.Truncate();
+
+  return NS_OK;
+}
+
+nsresult
+ProxyAutoConfig::GetProxyForURI(const nsCString &aTestURI,
+                                const nsCString &aTestHost,
+                                nsACString &result)
+{
+  if (mJSNeedsSetup)
+    SetupJS();
+
+  if (!mJSRuntime || !mJSRuntime->IsOK())
+    return NS_ERROR_NOT_AVAILABLE;
+
+  JSContext *cx = mJSRuntime->Context();
+  JSAutoRequest ar(cx);
+
+  // the sRunning flag keeps a new PAC file from being installed
+  // while the event loop is spinning on a DNS function. Don't early return.
+  sRunning = this;
+  mRunningHost = aTestHost;
+
+  nsresult rv = NS_ERROR_FAILURE;
+  js::RootedString uriString(cx, JS_NewStringCopyZ(cx, aTestURI.get()));
+  js::RootedString hostString(cx, JS_NewStringCopyZ(cx, aTestHost.get()));
+
+  if (uriString && hostString) {
+    js::RootedValue uriValue(cx, STRING_TO_JSVAL(uriString));
+    js::RootedValue hostValue(cx, STRING_TO_JSVAL(hostString));
+
+    jsval argv[2] = { uriValue, hostValue };
+    jsval rval;
+    JSBool ok = JS_CallFunctionName(cx, mJSRuntime->Global(),
+                                    "FindProxyForURL", 2, argv, &rval);
+
+    if (ok && rval.isString()) {
+      nsDependentJSString pacString;
+      if (pacString.init(cx, rval.toString())) {
+        CopyUTF16toUTF8(pacString, result);
+        rv = NS_OK;
+      }
+    }
+  }
+
+  mRunningHost.Truncate();
+  sRunning = nullptr;
+  return rv;
+}
+
+void
+ProxyAutoConfig::GC()
+{
+  if (!mJSRuntime || !mJSRuntime->IsOK())
+    return;
+
+  JS_MaybeGC(mJSRuntime->Context());
+}
+
+ProxyAutoConfig::~ProxyAutoConfig()
+{
+  MOZ_COUNT_DTOR(ProxyAutoConfig);
+  NS_ASSERTION(!mJSRuntime,
+               "~ProxyAutoConfig leaking JS runtime that "
+               "should have been deleted on pac thread");
+}
+
+void
+ProxyAutoConfig::Shutdown()
+{
+  NS_ABORT_IF_FALSE(!NS_IsMainThread(), "wrong thread for shutdown");
+
+  if (sRunning || mShutdown)
+    return;
+
+  mShutdown = true;
+  delete mJSRuntime;
+  mJSRuntime = nullptr;
+}
+
+bool
+ProxyAutoConfig::SrcAddress(const PRNetAddr *remoteAddress, nsCString &localAddress)
+{
+  PRFileDesc *fd;
+  fd = PR_OpenUDPSocket(remoteAddress->raw.family);
+  if (!fd)
+    return false;
+
+  if (PR_Connect(fd, remoteAddress, 0) != PR_SUCCESS) {
+    PR_Close(fd);
+    return false;
+  }
+
+  PRNetAddr localName;
+  if (PR_GetSockName(fd, &localName) != PR_SUCCESS) {
+    PR_Close(fd);
+    return false;
+  }
+
+  PR_Close(fd);
+  
+  char dottedDecimal[128];
+  if (PR_NetAddrToString(&localName, dottedDecimal, sizeof(dottedDecimal)) != PR_SUCCESS)
+    return false;
+  
+  localAddress.Assign(dottedDecimal);
+
+  return true;
+}
+
+// hostName is run through a dns lookup and then a udp socket is connected
+// to the result. If that all works, the local IP address of the socket is
+// returned to the javascript caller and true is returned from this function.
+// otherwise false is returned.
+bool
+ProxyAutoConfig::MyIPAddressTryHost(const nsCString &hostName,
+                                    unsigned int timeout,
+                                    jsval *vp)
+{
+  PRNetAddr remoteAddress;
+  nsAutoCString localDottedDecimal;
+  JSContext *cx = mJSRuntime->Context();
+
+  if (PACResolve(hostName, &remoteAddress, timeout) &&
+      SrcAddress(&remoteAddress, localDottedDecimal)) {
+    JSString *dottedDecimalString =
+      JS_NewStringCopyZ(cx, localDottedDecimal.get());
+    JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(dottedDecimalString));
+    return true;
+  }
+  return false;
+}
+
+bool
+ProxyAutoConfig::MyIPAddress(jsval *vp)
+{
+  nsAutoCString remoteDottedDecimal;
+  nsAutoCString localDottedDecimal;
+  JSContext *cx = mJSRuntime->Context();
+
+  // first, lookup the local address of a socket connected
+  // to the host of uri being resolved by the pac file. This is
+  // v6 safe.. but is the last step like that
+  if (MyIPAddressTryHost(mRunningHost, kTimeout, vp))
+    return true;
+
+  // next, look for a route to a public internet address that doesn't need DNS.
+  // This is the google anycast dns address, but it doesn't matter if it
+  // remains operable (as we don't contact it) as long as the address stays
+  // in commonly routed IP address space.
+  remoteDottedDecimal.AssignLiteral("8.8.8.8");
+  if (MyIPAddressTryHost(remoteDottedDecimal, 0, vp))
+    return true;
+  
+  // next, use the old algorithm based on the local hostname
+  nsAutoCString hostName;
+  nsCOMPtr<nsIDNSService> dns = do_GetService(NS_DNSSERVICE_CONTRACTID);
+  if (dns && NS_SUCCEEDED(dns->GetMyHostName(hostName)) &&
+      PACResolveToString(hostName, localDottedDecimal, kTimeout)) {
+    JSString *dottedDecimalString =
+      JS_NewStringCopyZ(cx, localDottedDecimal.get());
+    JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(dottedDecimalString));
+    return true;
+  }
+
+  // next try a couple RFC 1918 variants.. maybe there is a
+  // local route
+  remoteDottedDecimal.AssignLiteral("192.168.0.1");
+  if (MyIPAddressTryHost(remoteDottedDecimal, 0, vp))
+    return true;
+
+  // more RFC 1918
+  remoteDottedDecimal.AssignLiteral("10.0.0.1");
+  if (MyIPAddressTryHost(remoteDottedDecimal, 0, vp))
+    return true;
+
+  // who knows? let's fallback to localhost
+  localDottedDecimal.AssignLiteral("127.0.0.1");
+  JSString *dottedDecimalString =
+    JS_NewStringCopyZ(cx, localDottedDecimal.get());
+  JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(dottedDecimalString));
+  return true;
+}
+
+} // namespace mozilla
+} // namespace mozilla::net
new file mode 100644
--- /dev/null
+++ b/netwerk/base/src/ProxyAutoConfig.h
@@ -0,0 +1,102 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* 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/. */
+
+#ifndef ProxyAutoConfig_h__
+#define ProxyAutoConfig_h__
+
+#include "nsString.h"
+#include "jsapi.h"
+#include "prio.h"
+#include "nsITimer.h"
+#include "nsAutoPtr.h"
+
+namespace mozilla { namespace net {
+
+class JSRuntimeWrapper;
+
+// The ProxyAutoConfig class is meant to be created and run on a
+// non main thread. It synchronously resolves PAC files by blocking that
+// thread and running nested event loops. GetProxyForURI is not re-entrant.
+
+class ProxyAutoConfig  {
+public:
+  ProxyAutoConfig()
+    : mJSRuntime(nullptr)
+    , mJSNeedsSetup(false)
+    , mShutdown(false)
+  {
+    MOZ_COUNT_CTOR(ProxyAutoConfig);
+  }
+  ~ProxyAutoConfig();
+
+  nsresult Init(const nsCString &aPACURI,
+                const nsCString &aPACScript);
+  void     Shutdown();
+  void     GC();
+  bool     MyIPAddress(jsval *vp);
+  bool     ResolveAddress(const nsCString &aHostName,
+                          PRNetAddr *aNetAddr, unsigned int aTimeout);
+
+  /**
+   * Get the proxy string for the specified URI.  The proxy string is
+   * given by the following:
+   *
+   *   result      = proxy-spec *( proxy-sep proxy-spec )
+   *   proxy-spec  = direct-type | proxy-type LWS proxy-host [":" proxy-port]
+   *   direct-type = "DIRECT"
+   *   proxy-type  = "PROXY" | "SOCKS" | "SOCKS4" | "SOCKS5"
+   *   proxy-sep   = ";" LWS
+   *   proxy-host  = hostname | ipv4-address-literal
+   *   proxy-port  = <any 16-bit unsigned integer>
+   *   LWS         = *( SP | HT )
+   *   SP          = <US-ASCII SP, space (32)>
+   *   HT          = <US-ASCII HT, horizontal-tab (9)>
+   *
+   * NOTE: direct-type and proxy-type are case insensitive
+   * NOTE: SOCKS implies SOCKS4
+   *
+   * Examples:
+   *   "PROXY proxy1.foo.com:8080; PROXY proxy2.foo.com:8080; DIRECT"
+   *   "SOCKS socksproxy"
+   *   "DIRECT"
+   *
+   * XXX add support for IPv6 address literals.
+   * XXX quote whatever the official standard is for PAC.
+   *
+   * @param aTestURI
+   *        The URI as an ASCII string to test.
+   * @param aTestHost
+   *        The ASCII hostname to test.
+   *
+   * @param result
+   *        result string as defined above.
+   */
+  nsresult GetProxyForURI(const nsCString &aTestURI,
+                          const nsCString &aTestHost,
+                          nsACString &result);
+
+private:
+  const static unsigned int kTimeout = 1000; // ms to allow for myipaddress dns queries
+
+  // used to compile the PAC file and setup the execution context
+  nsresult SetupJS();
+
+  bool SrcAddress(const PRNetAddr *remoteAddress, nsCString &localAddress);
+  bool MyIPAddressTryHost(const nsCString &hostName, unsigned int timeout,
+                          jsval *vp);
+
+  JSRuntimeWrapper *mJSRuntime;
+  bool              mJSNeedsSetup;
+  bool              mShutdown;
+  nsCString         mPACScript;
+  nsCString         mPACURI;
+  nsCString         mRunningHost;
+  nsCOMPtr<nsITimer> mTimer;
+};
+
+}} // namespace mozilla::net
+
+#endif  // ProxyAutoConfig_h__
--- a/netwerk/base/src/nsBaseChannel.cpp
+++ b/netwerk/base/src/nsBaseChannel.cpp
@@ -696,32 +696,35 @@ nsBaseChannel::OnStartRequest(nsIRequest
 
   // Now, the general type sniffers. Skip this if we have none.
   if ((mLoadFlags & LOAD_CALL_CONTENT_SNIFFERS) &&
       gIOService->GetContentSniffers().Count() != 0)
     mPump->PeekStream(CallTypeSniffers, static_cast<nsIChannel*>(this));
 
   SUSPEND_PUMP_FOR_SCOPE();
 
-  return mListener->OnStartRequest(this, mListenerContext);
+  if (mListener) // null in case of redirect
+      return mListener->OnStartRequest(this, mListenerContext);
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsBaseChannel::OnStopRequest(nsIRequest *request, nsISupports *ctxt,
                              nsresult status)
 {
   // If both mStatus and status are failure codes, we keep mStatus as-is since
   // that is consistent with our GetStatus and Cancel methods.
   if (NS_SUCCEEDED(mStatus))
     mStatus = status;
 
   // Cause IsPending to return false.
   mPump = nullptr;
 
-  mListener->OnStopRequest(this, mListenerContext, mStatus);
+  if (mListener) // null in case of redirect
+      mListener->OnStopRequest(this, mListenerContext, mStatus);
   mListener = nullptr;
   mListenerContext = nullptr;
 
   // No need to suspend pump in this scope since we will not be receiving
   // any more events from it.
 
   if (mLoadGroup)
     mLoadGroup->RemoveRequest(this, nullptr, mStatus);
--- a/netwerk/base/src/nsIOService.cpp
+++ b/netwerk/base/src/nsIOService.cpp
@@ -34,16 +34,19 @@
 #include "nsSimpleNestedURI.h"
 #include "nsNetUtil.h"
 #include "nsThreadUtils.h"
 #include "nsIPermissionManager.h"
 #include "nsTArray.h"
 #include "nsIConsoleService.h"
 #include "nsIUploadChannel2.h"
 #include "nsXULAppAPI.h"
+#include "nsIProxiedChannel.h"
+#include "nsIProtocolProxyCallback.h"
+#include "nsICancelable.h"
 
 
 #if defined(XP_WIN) || defined(MOZ_PLATFORM_MAEMO)
 #include "nsNativeConnectionHelper.h"
 #endif
 
 #define PORT_PREF_PREFIX           "network.security.ports."
 #define PORT_PREF(x)               PORT_PREF_PREFIX x
@@ -557,41 +560,16 @@ nsIOService::NewFileURI(nsIFile *file, n
 }
 
 NS_IMETHODIMP
 nsIOService::NewChannelFromURI(nsIURI *aURI, nsIChannel **result)
 {
     return NewChannelFromURIWithProxyFlags(aURI, nullptr, 0, result);
 }
 
-void
-nsIOService::LookupProxyInfo(nsIURI *aURI,
-                             nsIURI *aProxyURI,
-                             uint32_t aProxyFlags,
-                             nsCString *aScheme,
-                             nsIProxyInfo **outPI)
-{
-    nsresult rv;
-    nsCOMPtr<nsIProxyInfo> pi;
-
-    if (!mProxyService) {
-        mProxyService = do_GetService(NS_PROTOCOLPROXYSERVICE_CONTRACTID);
-        if (!mProxyService)
-            NS_WARNING("failed to get protocol proxy service");
-    }
-    if (mProxyService) {
-        rv = mProxyService->Resolve(aProxyURI ? aProxyURI : aURI, aProxyFlags,
-                                    getter_AddRefs(pi));
-        if (NS_FAILED(rv))
-            pi = nullptr;
-    }
-    pi.forget(outPI);
-}
-
-
 NS_IMETHODIMP
 nsIOService::NewChannelFromURIWithProxyFlags(nsIURI *aURI,
                                              nsIURI *aProxyURI,
                                              uint32_t aProxyFlags,
                                              nsIChannel **result)
 {
     nsresult rv;
     NS_ENSURE_ARG_POINTER(aURI);
@@ -606,36 +584,21 @@ nsIOService::NewChannelFromURIWithProxyF
     if (NS_FAILED(rv))
         return rv;
 
     uint32_t protoFlags;
     rv = handler->GetProtocolFlags(&protoFlags);
     if (NS_FAILED(rv))
         return rv;
 
-    // Talk to the PPS if the protocol handler allows proxying.  Otherwise,
-    // skip this step.  This allows us to lazily load the PPS at startup.
-    if (protoFlags & nsIProtocolHandler::ALLOWS_PROXY) {
-        nsCOMPtr<nsIProxyInfo> pi;
-        LookupProxyInfo(aURI, aProxyURI, aProxyFlags, &scheme, getter_AddRefs(pi));
-        if (pi) {
-            nsAutoCString type;
-            if (NS_SUCCEEDED(pi->GetType(type)) && type.EqualsLiteral("http")) {
-                // we are going to proxy this channel using an http proxy
-                rv = GetProtocolHandler("http", getter_AddRefs(handler));
-                if (NS_FAILED(rv))
-                    return rv;
-            }
-            nsCOMPtr<nsIProxiedProtocolHandler> pph = do_QueryInterface(handler);
-            if (pph)
-                return pph->NewProxiedChannel(aURI, pi, result);
-        }
-    }
-
-    rv = handler->NewChannel(aURI, result);
+    nsCOMPtr<nsIProxiedProtocolHandler> pph = do_QueryInterface(handler);
+    if (pph)
+        rv = pph->NewProxiedChannel(aURI, nullptr, aProxyFlags, aProxyURI, result);
+    else
+        rv = handler->NewChannel(aURI, result);
     NS_ENSURE_SUCCESS(rv, rv);
 
     // Some extensions override the http protocol handler and provide their own
     // implementation. The channels returned from that implementation doesn't
     // seem to always implement the nsIUploadChannel2 interface, presumably
     // because it's a new interface.
     // Eventually we should remove this and simply require that http channels
     // implement the new interface.
@@ -1202,40 +1165,84 @@ nsIOService::ExtractCharsetFromContentTy
                          aCharsetStart, aCharsetEnd);
     if (*aHadCharset && *aCharsetStart == *aCharsetEnd) {
         *aHadCharset = false;
     }
     return NS_OK;
 }
 
 // nsISpeculativeConnect
+class IOServiceProxyCallback MOZ_FINAL : public nsIProtocolProxyCallback
+{
+public:
+    NS_DECL_ISUPPORTS
+    NS_DECL_NSIPROTOCOLPROXYCALLBACK
+
+    IOServiceProxyCallback(nsIInterfaceRequestor *aCallbacks,
+                           nsIEventTarget *aTarget,
+                           nsIOService *aIOService)
+        : mCallbacks(aCallbacks)
+        , mTarget(aTarget)
+        , mIOService(aIOService)
+    { }
+
+private:
+    nsRefPtr<nsIInterfaceRequestor> mCallbacks;
+    nsRefPtr<nsIEventTarget>        mTarget;
+    nsRefPtr<nsIOService>           mIOService;
+};
+
+NS_IMPL_ISUPPORTS1(IOServiceProxyCallback, nsIProtocolProxyCallback)
+
 NS_IMETHODIMP
-nsIOService::SpeculativeConnect(nsIURI *aURI,
-                                nsIInterfaceRequestor *aCallbacks,
-                                nsIEventTarget *aTarget)
+IOServiceProxyCallback::OnProxyAvailable(nsICancelable *request, nsIURI *aURI,
+                                         nsIProxyInfo *pi, nsresult status)
 {
+    // Checking proxy status for speculative connect
+    nsAutoCString type;
+    if (NS_SUCCEEDED(status) && pi &&
+        NS_SUCCEEDED(pi->GetType(type)) &&
+        !type.EqualsLiteral("direct")) {
+        // proxies dont do speculative connect
+        return NS_OK;
+    }
+
     nsAutoCString scheme;
     nsresult rv = aURI->GetScheme(scheme);
     if (NS_FAILED(rv))
-        return rv;
-
-    // Check for proxy information. If there is a proxy configured then a
-    // speculative connect should not be performed because the potential
-    // reward is slim with tcp peers closely located to the browser.
-    nsCOMPtr<nsIProxyInfo> pi;
-    LookupProxyInfo(aURI, nullptr, 0, &scheme, getter_AddRefs(pi));
-    if (pi) 
         return NS_OK;
 
     nsCOMPtr<nsIProtocolHandler> handler;