Merge m-c to b2g-inbound.
authorRyan VanderMeulen <ryanvm@gmail.com>
Fri, 06 Sep 2013 21:12:58 -0400
changeset 158989 a67532a34e35d9d9edab54db9b0f760a94c1fb5f
parent 158988 667cca91930339524d1440261687af2a8c1b8db3 (current diff)
parent 158941 3697f962bb7b6f395ca47eca4396921861633118 (diff)
child 158990 2b4628ad4f5bee3c3a970cc7cb83ead32d2b8549
push id2961
push userlsblakk@mozilla.com
push dateMon, 28 Oct 2013 21:59:28 +0000
treeherdermozilla-beta@73ef4f13486f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone26.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge m-c to b2g-inbound.
--- a/browser/metro/base/content/apzc.js
+++ b/browser/metro/base/content/apzc.js
@@ -10,16 +10,17 @@ let Cr = Components.results;
 
 /**
  * Handler for APZC display port and pan begin/end notifications.
  * These notifications are only sent by widget/windows/winrt code when
  * the pref: layers.async-pan-zoom.enabled is true.
  */
 
 var APZCObserver = {
+  _debugEvents: false,
   init: function() {
     this._enabled = Services.prefs.getBoolPref(kAsyncPanZoomEnabled);
     if (!this._enabled) {
       return;
     }
 
     let os = Services.obs;
     os.addObserver(this, "apzc-request-content-repaint", false);
@@ -90,35 +91,33 @@ var APZCObserver = {
         x: displayPort.x + scrollTo.x,
         y: displayPort.y + scrollTo.y,
         w: displayPort.width,
         h: displayPort.height,
         scale: resolution,
         id: scrollId
       });
 
-      Util.dumpLn("APZC scrollId: " + scrollId);
-      Util.dumpLn("APZC scrollTo.x: " + scrollTo.x + ", scrollTo.y: " + scrollTo.y);
-      Util.dumpLn("APZC setResolution: " + resolution);
-      Util.dumpLn("APZC setDisplayPortForElement: displayPort.x: " +
-                  displayPort.x + ", displayPort.y: " + displayPort.y +
-                  ", displayPort.width: " + displayPort.width +
-                  ", displayort.height: " + displayPort.height);
+      if (this._debugEvents) {
+        Util.dumpLn("APZC scrollId: " + scrollId);
+        Util.dumpLn("APZC scrollTo.x: " + scrollTo.x + ", scrollTo.y: " + scrollTo.y);
+        Util.dumpLn("APZC setResolution: " + resolution);
+        Util.dumpLn("APZC setDisplayPortForElement: displayPort.x: " +
+                    displayPort.x + ", displayPort.y: " + displayPort.y +
+                    ", displayPort.width: " + displayPort.width +
+                    ", displayort.height: " + displayPort.height);
+      }
     } else if (aTopic == "apzc-handle-pan-begin") {
       // When we're panning, hide the main scrollbars by setting imprecise
       // input (which sets a property on the browser which hides the scrollbar
       // via CSS).  This reduces jittering from left to right. We may be able
       // to get rid of this once we implement axis locking in /gfx APZC.
-      Util.dumpLn("APZC pan-begin");
       if (InputSourceHelper.isPrecise) {
         InputSourceHelper._imprecise();
       }
-
-    } else if (aTopic == "apzc-handle-pan-end") {
-      Util.dumpLn("APZC pan-end");
     }
   },
 
   receiveMessage: function(aMessage) {
     let json = aMessage.json;
     switch (aMessage.name) {
       case "scroll": {
         let data = json.viewId + " " + json.presShellId + " (" + json.scrollOffset.x + ", " + json.scrollOffset.y + ")";
--- a/browser/metro/profile/metro.js
+++ b/browser/metro/profile/metro.js
@@ -29,17 +29,17 @@ pref("metro.debug.selection.dumpRanges",
 pref("metro.debug.selection.dumpEvents", false);
 
 // Enable tab-modal prompts
 pref("prompts.tab_modal.enabled", true);
 
 
 // Enable off main thread compositing
 pref("layers.offmainthreadcomposition.enabled", true);
-pref("layers.async-pan-zoom.enabled", false);
+pref("layers.async-pan-zoom.enabled", true);
 pref("layers.componentalpha.enabled", false);
 pref("gfx.azpc.touch_start_tolerance", "0.1"); // dpi * tolerance = pixel threshold
 pref("gfx.axis.fling_friction", "0.002");
 
 // Enable Microsoft TSF support by default for imes.
 pref("intl.enable_tsf_support", true);
 
 pref("general.autoScroll", true);
--- a/caps/include/nsScriptSecurityManager.h
+++ b/caps/include/nsScriptSecurityManager.h
@@ -483,19 +483,16 @@ private:
 
     nsresult
     InitPolicies();
 
     nsresult
     InitDomainPolicy(JSContext* cx, const char* aPolicyName,
                      DomainPolicy* aDomainPolicy);
 
-    // JS strings we need to clean up on shutdown
-    static jsid sEnabledID;
-
     inline void
     ScriptSecurityPrefChanged();
 
     nsObjectHashtable* mOriginToPolicyMap;
     DomainPolicy* mDefaultPolicy;
     nsObjectHashtable* mCapabilities;
 
     nsCOMPtr<nsIPrincipal> mSystemPrincipal;
--- a/caps/src/nsScriptSecurityManager.cpp
+++ b/caps/src/nsScriptSecurityManager.cpp
@@ -72,16 +72,28 @@ using namespace mozilla::dom;
 
 static NS_DEFINE_CID(kZipReaderCID, NS_ZIPREADER_CID);
 
 nsIIOService    *nsScriptSecurityManager::sIOService = nullptr;
 nsIStringBundle *nsScriptSecurityManager::sStrBundle = nullptr;
 JSRuntime       *nsScriptSecurityManager::sRuntime   = 0;
 bool nsScriptSecurityManager::sStrictFileOriginPolicy = true;
 
+// Lazily initialized. Use the getter below.
+static jsid sEnabledID = JSID_VOID;
+static jsid
+EnabledID()
+{
+    if (sEnabledID != JSID_VOID)
+        return sEnabledID;
+    AutoSafeJSContext cx;
+    sEnabledID = INTERNED_STRING_TO_JSID(cx, JS_InternString(cx, "enabled"));
+    return sEnabledID;
+}
+
 bool
 nsScriptSecurityManager::SubjectIsPrivileged()
 {
     JSContext *cx = GetCurrentJSContext();
     if (cx && xpc::IsUniversalXPConnectEnabled(cx))
         return true;
     bool isSystem = false;
     return NS_SUCCEEDED(SubjectPrincipalIsSystem(&isSystem)) && isSystem;
@@ -1441,17 +1453,17 @@ nsScriptSecurityManager::CheckLoadURIWit
             return NS_OK;
         }
 
         // Now check capability policies
         static const char loadURIPrefGroup[] = "checkloaduri";
         ClassInfoData nameData(nullptr, loadURIPrefGroup);
 
         SecurityLevel secLevel;
-        rv = LookupPolicy(aPrincipal, nameData, sEnabledID,
+        rv = LookupPolicy(aPrincipal, nameData, EnabledID(),
                           nsIXPCSecurityManager::ACCESS_GET_PROPERTY,
                           nullptr, &secLevel);
         if (NS_SUCCEEDED(rv) && secLevel.level == SCRIPT_SECURITY_ALL_ACCESS)
         {
             // OK for this site!
             return NS_OK;
         }
 
@@ -1728,17 +1740,17 @@ nsScriptSecurityManager::CanExecuteScrip
     if (!*result)
         return NS_OK; // Do not run scripts
 
     //-- Check for a per-site policy
     static const char jsPrefGroupName[] = "javascript";
     ClassInfoData nameData(nullptr, jsPrefGroupName);
 
     SecurityLevel secLevel;
-    rv = LookupPolicy(aPrincipal, nameData, sEnabledID,
+    rv = LookupPolicy(aPrincipal, nameData, EnabledID(),
                       nsIXPCSecurityManager::ACCESS_GET_PROPERTY,
                       nullptr, &secLevel);
     if (NS_FAILED(rv) || secLevel.level == SCRIPT_SECURITY_NO_ACCESS)
     {
         *result = false;
         return rv;
     }
 
@@ -2325,24 +2337,16 @@ nsScriptSecurityManager::nsScriptSecurit
 {
     static_assert(sizeof(intptr_t) == sizeof(void*),
                   "intptr_t and void* have different lengths on this platform. "
                   "This may cause a security failure with the SecurityLevel union.");
 }
 
 nsresult nsScriptSecurityManager::Init()
 {
-    JSContext* cx = GetSafeJSContext();
-    if (!cx) return NS_ERROR_FAILURE;   // this can happen of xpt loading fails
-    
-    ::JS_BeginRequest(cx);
-    if (sEnabledID == JSID_VOID)
-        sEnabledID = INTERNED_STRING_TO_JSID(cx, ::JS_InternString(cx, "enabled"));
-    ::JS_EndRequest(cx);
-
     InitPrefs();
 
     nsresult rv = CallGetService(NS_IOSERVICE_CONTRACTID, &sIOService);
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsCOMPtr<nsIStringBundleService> bundleService =
         mozilla::services::GetStringBundleService();
     if (!bundleService)
@@ -2373,18 +2377,16 @@ nsresult nsScriptSecurityManager::Init()
 
     JS_SetTrustedPrincipals(sRuntime, system);
 
     return NS_OK;
 }
 
 static StaticRefPtr<nsScriptSecurityManager> gScriptSecMan;
 
-jsid nsScriptSecurityManager::sEnabledID   = JSID_VOID;
-
 nsScriptSecurityManager::~nsScriptSecurityManager(void)
 {
     Preferences::RemoveObservers(this, kObservedPrefs);
     delete mOriginToPolicyMap;
     if(mDefaultPolicy)
         mDefaultPolicy->Drop();
     delete mCapabilities;
 }
--- a/content/base/public/nsHostObjectProtocolHandler.h
+++ b/content/base/public/nsHostObjectProtocolHandler.h
@@ -4,26 +4,26 @@
 
 #ifndef nsHostObjectProtocolHandler_h
 #define nsHostObjectProtocolHandler_h
 
 #include "mozilla/Attributes.h"
 #include "nsIProtocolHandler.h"
 #include "nsIURI.h"
 #include "nsCOMPtr.h"
+#include "nsIInputStream.h"
 
 #define BLOBURI_SCHEME "blob"
 #define MEDIASTREAMURI_SCHEME "mediastream"
 #define MEDIASOURCEURI_SCHEME "mediasource"
 #define FONTTABLEURI_SCHEME "moz-fonttable"
 
 class nsIDOMBlob;
 class nsIDOMMediaStream;
 class nsIPrincipal;
-class nsIInputStream;
 
 namespace mozilla {
 namespace dom {
 class MediaSource;
 }
 }
 
 class nsHostObjectProtocolHandler : public nsIProtocolHandler
--- a/content/base/src/nsXMLHttpRequest.cpp
+++ b/content/base/src/nsXMLHttpRequest.cpp
@@ -62,16 +62,17 @@
 #include "mozilla/dom/XMLHttpRequestBinding.h"
 #include "mozilla/Attributes.h"
 #include "nsIPermissionManager.h"
 #include "nsMimeTypes.h"
 #include "nsIHttpChannelInternal.h"
 #include "nsCharSeparatedTokenizer.h"
 #include "nsFormData.h"
 #include "nsStreamListenerWrapper.h"
+#include "xpcjsid.h"
 
 #include "nsWrapperCacheInlines.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 // Maximum size that we'll grow an ArrayBuffer instead of doubling,
 // once doubling reaches this threshold
--- a/content/base/src/nsXMLHttpRequest.h
+++ b/content/base/src/nsXMLHttpRequest.h
@@ -43,16 +43,17 @@
 
 class AsyncVerifyRedirectCallbackForwarder;
 class BlobSet;
 class nsDOMFile;
 class nsFormData;
 class nsIJARChannel;
 class nsILoadGroup;
 class nsIUnicodeDecoder;
+class nsIJSID;
 
 namespace mozilla {
 
 // A helper for building up an ArrayBuffer object's data
 // before creating the ArrayBuffer itself.  Will do doubling
 // based reallocation, up to an optional maximum growth given.
 //
 // When all the data has been appended, call getArrayBuffer,
--- a/content/canvas/test/webgl/non-conf-tests/Makefile.in
+++ b/content/canvas/test/webgl/non-conf-tests/Makefile.in
@@ -1,8 +1,9 @@
 #
 # 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/.
 
 MOCHITEST_FILES = \
   test_webgl_conformance.html \
+  test_webgl_request_mismatch.html \
   $(NULL)
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/non-conf-tests/test_webgl_request_mismatch.html
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML>
+<title>WebGL test: Mismatched 'webgl' and 'experimental-webgl' context requests</title>
+<script src="/MochiKit/MochiKit.js"></script>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" href="/tests/SimpleTest/test.css">
+<body>
+<canvas id="c1"></canvas>
+<canvas id="c2"></canvas>
+<canvas id="c3"></canvas>
+<canvas id="c4"></canvas>
+<script>
+
+function testContextRetrieval(canvasId, creationId, requestId) {
+  var canvas = document.getElementById(canvasId);
+  ok(canvas, 'Invalid `canvasId`: ' + canvasId);
+
+  var createdGL = canvas.getContext(creationId);
+  if (!createdGL)
+    return; // No WebGL on this machine?
+
+  var requestedGL = canvas.getContext(requestId);
+  if (creationId == requestId) {
+    ok(requestedGL, 'Request for \'' + requestId + '\' on from \'' + creationId + '\' should succeed.');
+    ok(requestedGL == createdGL, 'Request for \'' + requestId + '\' on from \'' + creationId + '\' should match.');
+  } else {
+    ok(!requestedGL, 'Request for \'' + requestId + '\' on from \'' + creationId + '\' should fail.');
+  }
+}
+
+testContextRetrieval('c1', 'experimental-webgl', 'webgl');
+testContextRetrieval('c2', 'webgl', 'experimental-webgl');
+testContextRetrieval('c3', 'experimental-webgl', 'experimental-webgl');
+testContextRetrieval('c4', 'webgl', 'webgl');
+
+</script>
+
--- a/content/html/content/src/HTMLAudioElement.cpp
+++ b/content/html/content/src/HTMLAudioElement.cpp
@@ -13,16 +13,17 @@
 #include "nsIDocument.h"
 #include "jsfriendapi.h"
 #include "nsContentUtils.h"
 #include "nsJSUtils.h"
 #include "AudioSampleFormat.h"
 #include "AudioChannelCommon.h"
 #include <algorithm>
 #include "mozilla/Preferences.h"
+#include "nsComponentManagerUtils.h"
 
 static bool
 IsAudioAPIEnabled()
 {
   return mozilla::Preferences::GetBool("media.audio_data.enabled", true);
 }
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(Audio)
--- a/content/html/content/src/HTMLCanvasElement.cpp
+++ b/content/html/content/src/HTMLCanvasElement.cpp
@@ -666,16 +666,24 @@ nsresult
 HTMLCanvasElement::GetContext(const nsAString& aContextId,
                               nsISupports** aContext)
 {
   ErrorResult rv;
   *aContext = GetContext(nullptr, aContextId, JS::NullHandleValue, rv).get();
   return rv.ErrorCode();
 }
 
+static bool
+IsContextIdWebGL(const nsAString& str)
+{
+  return str.EqualsLiteral("webgl") ||
+         str.EqualsLiteral("experimental-webgl") ||
+         str.EqualsLiteral("moz-webgl");
+}
+
 already_AddRefed<nsISupports>
 HTMLCanvasElement::GetContext(JSContext* aCx,
                               const nsAString& aContextId,
                               JS::Handle<JS::Value> aContextOptions,
                               ErrorResult& rv)
 {
   if (mCurrentContextId.IsEmpty()) {
     rv = GetContextHelper(aContextId, getter_AddRefs(mCurrentContext));
@@ -697,16 +705,30 @@ HTMLCanvasElement::GetContext(JSContext*
     if (rv.Failed()) {
       rv = NS_OK; // See bug 645792
       return nullptr;
     }
     mCurrentContextId.Assign(aContextId);
   }
 
   if (!mCurrentContextId.Equals(aContextId)) {
+    if (IsContextIdWebGL(aContextId) &&
+        IsContextIdWebGL(mCurrentContextId))
+    {
+      // Warn when we get a request for a webgl context with an id that differs
+      // from the id it was created with.
+      nsCString creationId = NS_LossyConvertUTF16toASCII(mCurrentContextId);
+      nsCString requestId = NS_LossyConvertUTF16toASCII(aContextId);
+      JS_ReportWarning(aCx, "WebGL: Retrieving a WebGL context from a canvas "
+                            "via a request id ('%s') different from the id used "
+                            "to create the context ('%s') is not allowed.",
+                            requestId.get(),
+                            creationId.get());
+    }
+    
     //XXX eventually allow for more than one active context on a given canvas
     return nullptr;
   }
 
   nsCOMPtr<nsICanvasRenderingContextInternal> context = mCurrentContext;
   return context.forget();
 }
 
--- a/content/media/WebVTTLoadListener.cpp
+++ b/content/media/WebVTTLoadListener.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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 "WebVTTLoadListener.h"
 #include "mozilla/dom/TextTrackCue.h"
 #include "mozilla/dom/HTMLTrackElement.h"
+#include "nsIInputStream.h"
 
 namespace mozilla {
 namespace dom {
 
 NS_IMPL_CYCLE_COLLECTION_1(WebVTTLoadListener, mElement)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WebVTTLoadListener)
   NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
--- a/content/media/mediasource/MediaSource.cpp
+++ b/content/media/mediasource/MediaSource.cpp
@@ -6,16 +6,17 @@
 
 #include "MediaSource.h"
 
 #include "mozilla/dom/HTMLMediaElement.h"
 #include "MediaSourceInputAdapter.h"
 #include "SourceBuffer.h"
 #include "SourceBufferList.h"
 #include "nsContentTypeParser.h"
+#include "nsIInputStream.h"
 
 #ifdef PR_LOGGING
 PRLogModuleInfo* gMediaSourceLog;
 #define LOG(type, msg) PR_LOG(gMediaSourceLog, type, msg)
 #else
 #define LOG(type, msg)
 #endif
 
--- a/content/media/mediasource/MediaSource.h
+++ b/content/media/mediasource/MediaSource.h
@@ -13,16 +13,18 @@
 #include "mozilla/dom/MediaSourceBinding.h"
 #include "mozilla/dom/TypedArray.h"
 #include "nsCOMPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsDOMEventTargetHelper.h"
 #include "nsWrapperCache.h"
 #include "nscore.h"
 
+class nsIInputStream;
+
 namespace mozilla {
 namespace dom {
 
 class HTMLMediaElement;
 class MediaSourceInputAdapter;
 class SourceBufferList;
 class SourceBuffer;
 class TimeRanges;
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -185,16 +185,17 @@
 #include "nsIDOMCameraManager.h"
 #include "nsIDOMGlobalObjectConstructor.h"
 #include "nsIDOMLockedFile.h"
 #include "nsDebug.h"
 
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/Likely.h"
 #include "WindowNamedPropertiesHandler.h"
+#include "nsIInterfaceInfoManager.h"
 
 #ifdef MOZ_TIME_MANAGER
 #include "TimeManager.h"
 #endif
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using mozilla::dom::workers::ResolveWorkerClasses;
--- a/dom/base/nsDOMException.cpp
+++ b/dom/base/nsDOMException.cpp
@@ -10,16 +10,17 @@
 #include "nsCRTGlue.h"
 #include "nsContentUtils.h"
 #include "nsDOMClassInfoID.h"
 #include "nsError.h"
 #include "nsIDOMDOMException.h"
 #include "nsIDocument.h"
 #include "nsString.h"
 #include "prprf.h"
+#include "nsIException.h"
 
 using namespace mozilla;
 
 enum DOM4ErrorTypeCodeMap {
   /* DOM4 errors from http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#domexception */
   IndexSizeError             = nsIDOMDOMException::INDEX_SIZE_ERR,
   HierarchyRequestError      = nsIDOMDOMException::HIERARCHY_REQUEST_ERR,
   WrongDocumentError         = nsIDOMDOMException::WRONG_DOCUMENT_ERR,
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -44,16 +44,17 @@
 #include "nsIInlineEventHandlers.h"
 #include "nsWrapperCacheInlines.h"
 #include "nsIIdleObserver.h"
 #include "nsIDocument.h"
 #include "nsIDOMTouchEvent.h"
 
 #include "mozilla/dom/EventTarget.h"
 #include "Units.h"
+#include "nsComponentManagerUtils.h"
 
 #ifdef MOZ_B2G
 #include "nsIDOMWindowB2G.h"
 #endif // MOZ_B2G
 
 #ifdef MOZ_WEBSPEECH
 #include "nsISpeechSynthesisGetter.h"
 #endif // MOZ_WEBSPEECH
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -50,16 +50,17 @@
 #include "nsIObjectOutputStream.h"
 #include "prmem.h"
 #include "WrapperFactory.h"
 #include "nsGlobalWindow.h"
 #include "nsScriptNameSpaceManager.h"
 #include "StructuredCloneTags.h"
 #include "mozilla/dom/ImageData.h"
 #include "mozilla/dom/ImageDataBinding.h"
+#include "nsAXPCNativeCallContext.h"
 
 #include "nsJSPrincipals.h"
 
 #ifdef XP_MACOSX
 // AssertMacros.h defines 'check' and conflicts with AccessCheck.h
 #undef check
 #endif
 #include "AccessCheck.h"
--- a/dom/base/nsJSTimeoutHandler.cpp
+++ b/dom/base/nsJSTimeoutHandler.cpp
@@ -12,16 +12,17 @@
 #include "nsContentUtils.h"
 #include "nsError.h"
 #include "nsGlobalWindow.h"
 #include "nsIContentSecurityPolicy.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/Likely.h"
 #include <algorithm>
 #include "mozilla/dom/FunctionBinding.h"
+#include "nsAXPCNativeCallContext.h"
 
 static const char kSetIntervalStr[] = "setInterval";
 static const char kSetTimeoutStr[] = "setTimeout";
 
 using namespace mozilla::dom;
 
 // Our JS nsIScriptTimeoutHandler implementation.
 class nsJSScriptTimeoutHandler MOZ_FINAL : public nsIScriptTimeoutHandler
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -23,16 +23,17 @@
 #include "mozilla/Likely.h"
 #include "mozilla/Util.h"
 #include "nsCycleCollector.h"
 #include "nsIXPConnect.h"
 #include "nsThreadUtils.h" // Hacky work around for some bindings needing NS_IsMainThread.
 #include "nsTraceRefcnt.h"
 #include "qsObjectHelper.h"
 #include "xpcpublic.h"
+#include "nsIVariant.h"
 
 #include "nsWrapperCacheInlines.h"
 
 class nsPIDOMWindow;
 
 extern nsresult
 xpc_qsUnwrapArgImpl(JSContext* cx, jsval v, const nsIID& iid, void** ppArg,
                     nsISupports** ppArgRef, jsval* vp);
--- a/dom/devicestorage/DeviceStorage.h
+++ b/dom/devicestorage/DeviceStorage.h
@@ -18,16 +18,18 @@
 
 #define DEVICESTORAGE_PICTURES   "pictures"
 #define DEVICESTORAGE_VIDEOS     "videos"
 #define DEVICESTORAGE_MUSIC      "music"
 #define DEVICESTORAGE_APPS       "apps"
 #define DEVICESTORAGE_SDCARD     "sdcard"
 #define DEVICESTORAGE_CRASHES    "crashes"
 
+class nsIInputStream;
+
 namespace mozilla {
 namespace dom {
 class DeviceStorageEnumerationParameters;
 class DOMCursor;
 class DOMRequest;
 } // namespace dom
 } // namespace mozilla
 
--- a/dom/indexedDB/IndexedDatabase.h
+++ b/dom/indexedDB/IndexedDatabase.h
@@ -12,28 +12,28 @@
 #include "mozilla/Attributes.h"
 #include "js/StructuredClone.h"
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "nsDebug.h"
 #include "nsError.h"
 #include "nsStringGlue.h"
 #include "nsTArray.h"
+#include "nsIInputStream.h"
 
 #define BEGIN_INDEXEDDB_NAMESPACE \
   namespace mozilla { namespace dom { namespace indexedDB {
 
 #define END_INDEXEDDB_NAMESPACE \
   } /* namespace indexedDB */ } /* namepsace dom */ } /* namespace mozilla */
 
 #define USING_INDEXEDDB_NAMESPACE \
   using namespace mozilla::dom::indexedDB;
 
 class nsIDOMBlob;
-class nsIInputStream;
 
 BEGIN_INDEXEDDB_NAMESPACE
 
 class FileInfo;
 class IDBDatabase;
 class IDBTransaction;
 
 template <class T>
--- a/dom/interfaces/geolocation/nsIDOMGeoGeolocation.idl
+++ b/dom/interfaces/geolocation/nsIDOMGeoGeolocation.idl
@@ -3,31 +3,28 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "domstubs.idl"
 
 interface nsIDOMGeoPositionCallback;
 interface nsIDOMGeoPositionErrorCallback;
 
 %{C++
-#include "DictionaryHelpers.h"
+namespace mozilla {
+namespace dom {
+class PositionOptions;
+}
+}
 %}
 
-dictionary GeoPositionOptions
-{
-  boolean enableHighAccuracy;
-  long timeout;
-  long maximumAge;
-};
-
-[ptr] native NamespacedGeoPositionOptions(mozilla::idl::GeoPositionOptions);
+[ptr] native NamespacedPositionOptions(mozilla::dom::PositionOptions);
 
 [builtinclass, uuid(1bc7d103-c7ae-4467-881c-21a8dfa17938)]
 interface nsIDOMGeoGeolocation : nsISupports
 {
   int32_t watchPosition(in nsIDOMGeoPositionCallback callback,
                         in nsIDOMGeoPositionErrorCallback errorCallback,
-                        in NamespacedGeoPositionOptions options);
+                        in NamespacedPositionOptions options);
   void getCurrentPosition(in nsIDOMGeoPositionCallback callback,
                           in nsIDOMGeoPositionErrorCallback errorCallback,
-                          in NamespacedGeoPositionOptions options);
+                          in NamespacedPositionOptions options);
   void clearWatch(in long watchId);
 };
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -29,16 +29,17 @@
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/ExternalHelperAppParent.h"
 #include "mozilla/dom/PMemoryReportRequestParent.h"
 #include "mozilla/dom/power/PowerManagerService.h"
 #include "mozilla/dom/DOMStorageIPC.h"
 #include "mozilla/dom/bluetooth/PBluetoothParent.h"
 #include "mozilla/dom/PFMRadioParent.h"
 #include "mozilla/dom/devicestorage/DeviceStorageRequestParent.h"
+#include "mozilla/dom/GeolocationBinding.h"
 #include "SmsParent.h"
 #include "mozilla/Hal.h"
 #include "mozilla/hal_sandbox/PHalParent.h"
 #include "mozilla/ipc/TestShellParent.h"
 #include "mozilla/ipc/InputStreamUtils.h"
 #include "mozilla/layers/CompositorParent.h"
 #include "mozilla/layers/ImageBridgeParent.h"
 #include "mozilla/net/NeckoParent.h"
@@ -143,17 +144,16 @@ static const char* sClipboardTextFlavors
 using base::ChildPrivileges;
 using base::KillProcess;
 using namespace mozilla::dom::bluetooth;
 using namespace mozilla::dom::devicestorage;
 using namespace mozilla::dom::indexedDB;
 using namespace mozilla::dom::power;
 using namespace mozilla::dom::mobilemessage;
 using namespace mozilla::hal;
-using namespace mozilla::idl;
 using namespace mozilla::ipc;
 using namespace mozilla::layers;
 using namespace mozilla::net;
 using namespace mozilla::jsipc;
 
 namespace mozilla {
 namespace dom {
 
@@ -2616,18 +2616,18 @@ ContentParent::RecvFilePathUpdateNotify(
 static int32_t
 AddGeolocationListener(nsIDOMGeoPositionCallback* watcher, bool highAccuracy)
 {
   nsCOMPtr<nsIDOMGeoGeolocation> geo = do_GetService("@mozilla.org/geolocation;1");
   if (!geo) {
     return -1;
   }
 
-  GeoPositionOptions* options = new GeoPositionOptions();
-  options->enableHighAccuracy = highAccuracy;
+  PositionOptions* options = new PositionOptions();
+  options->mEnableHighAccuracy = highAccuracy;
   int32_t retval = 1;
   geo->WatchPosition(watcher, nullptr, options, &retval);
   return retval;
 }
 
 bool
 ContentParent::RecvAddGeolocationListener(const IPC::Principal& aPrincipal,
                                           const bool& aHighAccuracy)
--- a/dom/src/geolocation/nsGeolocation.cpp
+++ b/dom/src/geolocation/nsGeolocation.cpp
@@ -66,56 +66,55 @@ class nsGeolocationRequest
   NS_DECL_NSITIMERCALLBACK
   NS_DECL_NSIGEOLOCATIONUPDATE
 
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsGeolocationRequest, nsIContentPermissionRequest)
 
   nsGeolocationRequest(Geolocation* aLocator,
                        const GeoPositionCallback& aCallback,
                        const GeoPositionErrorCallback& aErrorCallback,
-                       idl::GeoPositionOptions* aOptions,
+                       PositionOptions* aOptions,
                        bool aWatchPositionRequest = false,
                        int32_t aWatchId = 0);
   void Shutdown();
 
   void SendLocation(nsIDOMGeoPosition* location);
-  bool WantsHighAccuracy() {return mOptions && mOptions->enableHighAccuracy;}
+  bool WantsHighAccuracy() {return mOptions && mOptions->mEnableHighAccuracy;}
   void SetTimeoutTimer();
   nsIPrincipal* GetPrincipal();
 
   ~nsGeolocationRequest();
 
   virtual bool Recv__delete__(const bool& allow) MOZ_OVERRIDE;
   virtual void IPDLRelease() MOZ_OVERRIDE { Release(); }
 
   bool IsWatch() { return mIsWatchPositionRequest; }
   int32_t WatchId() { return mWatchId; }
  private:
   bool mIsWatchPositionRequest;
 
   nsCOMPtr<nsITimer> mTimeoutTimer;
   GeoPositionCallback mCallback;
   GeoPositionErrorCallback mErrorCallback;
-  nsAutoPtr<idl::GeoPositionOptions> mOptions;
+  nsAutoPtr<PositionOptions> mOptions;
 
   nsRefPtr<Geolocation> mLocator;
 
   int32_t mWatchId;
   bool mShutdown;
 };
 
-static idl::GeoPositionOptions*
-GeoPositionOptionsFromPositionOptions(const PositionOptions& aOptions)
+static PositionOptions*
+CreatePositionOptionsCopy(const PositionOptions& aOptions)
 {
-  nsAutoPtr<idl::GeoPositionOptions> geoOptions(
-    new idl::GeoPositionOptions());
+  nsAutoPtr<PositionOptions> geoOptions(new PositionOptions());
 
-  geoOptions->enableHighAccuracy = aOptions.mEnableHighAccuracy;
-  geoOptions->maximumAge = aOptions.mMaximumAge;
-  geoOptions->timeout = aOptions.mTimeout;
+  geoOptions->mEnableHighAccuracy = aOptions.mEnableHighAccuracy;
+  geoOptions->mMaximumAge = aOptions.mMaximumAge;
+  geoOptions->mTimeout = aOptions.mTimeout;
 
   return geoOptions.forget();
 }
 
 class GeolocationSettingsCallback : public nsISettingsServiceCallback
 {
 public:
   NS_DECL_ISUPPORTS
@@ -331,17 +330,17 @@ PositionError::NotifyCallback(const GeoP
 }
 ////////////////////////////////////////////////////
 // nsGeolocationRequest
 ////////////////////////////////////////////////////
 
 nsGeolocationRequest::nsGeolocationRequest(Geolocation* aLocator,
                                            const GeoPositionCallback& aCallback,
                                            const GeoPositionErrorCallback& aErrorCallback,
-                                           idl::GeoPositionOptions* aOptions,
+                                           PositionOptions* aOptions,
                                            bool aWatchPositionRequest,
                                            int32_t aWatchId)
   : mIsWatchPositionRequest(aWatchPositionRequest),
     mCallback(aCallback),
     mErrorCallback(aErrorCallback),
     mOptions(aOptions),
     mLocator(aLocator),
     mWatchId(aWatchId),
@@ -455,21 +454,21 @@ nsGeolocationRequest::Allow()
   //
   // either:
   // a) the user has specified a maximumAge which allows us to return a cached value,
   // -or-
   // b) the cached position time is some reasonable value to return to the user (<30s)
 
   uint32_t maximumAge = 30 * PR_MSEC_PER_SEC;
   if (mOptions) {
-    if (mOptions->maximumAge >= 0) {
-      maximumAge = mOptions->maximumAge;
+    if (mOptions->mMaximumAge >= 0) {
+      maximumAge = mOptions->mMaximumAge;
     }
   }
-  gs->SetHigherAccuracy(mOptions && mOptions->enableHighAccuracy);
+  gs->SetHigherAccuracy(mOptions && mOptions->mEnableHighAccuracy);
 
   bool canUseCache = lastPosition && maximumAge > 0 &&
     (PRTime(PR_Now() / PR_USEC_PER_MSEC) - maximumAge <=
     PRTime(cachedPositionTime));
 
   if (canUseCache) {
     // okay, we can return a cached position
     // getCurrentPosition requests serviced by the cache
@@ -492,17 +491,17 @@ void
 nsGeolocationRequest::SetTimeoutTimer()
 {
   if (mTimeoutTimer) {
     mTimeoutTimer->Cancel();
     mTimeoutTimer = nullptr;
   }
 
   int32_t timeout;
-  if (mOptions && (timeout = mOptions->timeout) != 0) {
+  if (mOptions && (timeout = mOptions->mTimeout) != 0) {
 
     if (timeout < 0) {
       timeout = 0;
     } else if (timeout < 10) {
       timeout = 10;
     }
 
     mTimeoutTimer = do_CreateInstance("@mozilla.org/timer;1");
@@ -595,17 +594,17 @@ nsGeolocationRequest::Shutdown()
 
   if (mTimeoutTimer) {
     mTimeoutTimer->Cancel();
     mTimeoutTimer = nullptr;
   }
 
   // This should happen last, to ensure that this request isn't taken into consideration
   // when deciding whether existing requests still require high accuracy.
-  if (mOptions && mOptions->enableHighAccuracy) {
+  if (mOptions && mOptions->mEnableHighAccuracy) {
     nsRefPtr<nsGeolocationService> gs = nsGeolocationService::GetGeolocationService();
     if (gs) {
       gs->SetHigherAccuracy(false);
     }
   }
 }
 
 bool nsGeolocationRequest::Recv__delete__(const bool& allow)
@@ -1195,44 +1194,43 @@ void
 Geolocation::GetCurrentPosition(PositionCallback& aCallback,
                                 PositionErrorCallback* aErrorCallback,
                                 const PositionOptions& aOptions,
                                 ErrorResult& aRv)
 {
   GeoPositionCallback successCallback(&aCallback);
   GeoPositionErrorCallback errorCallback(aErrorCallback);
 
-  nsresult rv =
-    GetCurrentPosition(successCallback, errorCallback,
-                       GeoPositionOptionsFromPositionOptions(aOptions));
+  nsresult rv = GetCurrentPosition(successCallback, errorCallback,
+                                   CreatePositionOptionsCopy(aOptions));
 
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
   }
 
   return;
 }
 
 NS_IMETHODIMP
 Geolocation::GetCurrentPosition(nsIDOMGeoPositionCallback* aCallback,
                                 nsIDOMGeoPositionErrorCallback* aErrorCallback,
-                                idl::GeoPositionOptions* aOptions)
+                                PositionOptions* aOptions)
 {
   NS_ENSURE_ARG_POINTER(aCallback);
 
   GeoPositionCallback successCallback(aCallback);
   GeoPositionErrorCallback errorCallback(aErrorCallback);
 
   return GetCurrentPosition(successCallback, errorCallback, aOptions);
 }
 
 nsresult
 Geolocation::GetCurrentPosition(GeoPositionCallback& callback,
                                 GeoPositionErrorCallback& errorCallback,
-                                idl::GeoPositionOptions *options)
+                                PositionOptions *options)
 {
   if (mPendingCallbacks.Length() > MAX_GEO_REQUESTS_PER_WINDOW) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   nsRefPtr<nsGeolocationRequest> request = new nsGeolocationRequest(this,
                                                                     callback,
                                                                     errorCallback,
@@ -1284,45 +1282,44 @@ Geolocation::WatchPosition(PositionCallb
                            PositionErrorCallback* aErrorCallback,
                            const PositionOptions& aOptions,
                            ErrorResult& aRv)
 {
   int32_t ret;
   GeoPositionCallback successCallback(&aCallback);
   GeoPositionErrorCallback errorCallback(aErrorCallback);
 
-  nsresult rv =
-    WatchPosition(successCallback, errorCallback,
-                  GeoPositionOptionsFromPositionOptions(aOptions), &ret);
+  nsresult rv = WatchPosition(successCallback, errorCallback,
+                              CreatePositionOptionsCopy(aOptions), &ret);
 
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
   }
 
   return ret;
 }
 
 NS_IMETHODIMP
 Geolocation::WatchPosition(nsIDOMGeoPositionCallback *aCallback,
                            nsIDOMGeoPositionErrorCallback *aErrorCallback,
-                           idl::GeoPositionOptions *aOptions,
+                           PositionOptions *aOptions,
                            int32_t* aRv)
 {
   NS_ENSURE_ARG_POINTER(aCallback);
 
   GeoPositionCallback successCallback(aCallback);
   GeoPositionErrorCallback errorCallback(aErrorCallback);
 
   return WatchPosition(successCallback, errorCallback, aOptions, aRv);
 }
 
 nsresult
 Geolocation::WatchPosition(GeoPositionCallback& aCallback,
                            GeoPositionErrorCallback& aErrorCallback,
-                           idl::GeoPositionOptions* aOptions,
+                           PositionOptions* aOptions,
                            int32_t* aRv)
 {
   if (mWatchingCallbacks.Length() > MAX_GEO_REQUESTS_PER_WINDOW) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   // The watch ID:
   *aRv = mLastWatchId++;
--- a/dom/src/geolocation/nsGeolocation.h
+++ b/dom/src/geolocation/nsGeolocation.h
@@ -171,18 +171,18 @@ public:
 
   // Notification from the service:
   void ServiceReady();
 
 private:
 
   ~Geolocation();
 
-  nsresult GetCurrentPosition(GeoPositionCallback& aCallback, GeoPositionErrorCallback& aErrorCallback, mozilla::idl::GeoPositionOptions* aOptions);
-  nsresult WatchPosition(GeoPositionCallback& aCallback, GeoPositionErrorCallback& aErrorCallback, mozilla::idl::GeoPositionOptions* aOptions, int32_t* aRv);
+  nsresult GetCurrentPosition(GeoPositionCallback& aCallback, GeoPositionErrorCallback& aErrorCallback, PositionOptions* aOptions);
+  nsresult WatchPosition(GeoPositionCallback& aCallback, GeoPositionErrorCallback& aErrorCallback, PositionOptions* aOptions, int32_t* aRv);
 
   bool RegisterRequestWithPrompt(nsGeolocationRequest* request);
 
   // Methods for the service when it's ready to process requests:
   nsresult GetCurrentPositionReady(nsGeolocationRequest* aRequest);
   nsresult WatchPositionReady(nsGeolocationRequest* aRequest);
 
   // Two callback arrays.  The first |mPendingCallbacks| holds objects for only
--- a/dom/workers/XMLHttpRequest.cpp
+++ b/dom/workers/XMLHttpRequest.cpp
@@ -25,16 +25,17 @@
 #include "Exceptions.h"
 #include "File.h"
 #include "RuntimeService.h"
 #include "WorkerPrivate.h"
 #include "XMLHttpRequestUpload.h"
 
 #include "DOMBindingInlines.h"
 #include "mozilla/Attributes.h"
+#include "nsComponentManagerUtils.h"
 
 using namespace mozilla;
 
 using namespace mozilla::dom;
 USING_WORKERS_NAMESPACE
 
 using mozilla::dom::workers::exceptions::ThrowDOMExceptionForNSResult;
 
--- a/embedding/components/find/src/nsWebBrowserFind.cpp
+++ b/embedding/components/find/src/nsWebBrowserFind.cpp
@@ -33,16 +33,17 @@
 #include "nsIServiceManager.h"
 #include "nsIObserverService.h"
 #include "nsISupportsPrimitives.h"
 #include "nsFind.h"
 #include "nsError.h"
 #include "nsFocusManager.h"
 #include "mozilla/Services.h"
 #include "mozilla/dom/Element.h"
+#include "nsISimpleEnumerator.h"
 
 #if DEBUG
 #include "nsIWebNavigation.h"
 #include "nsXPIDLString.h"
 #endif
 
 #if defined(XP_MACOSX) && !defined(__LP64__)
 #include "nsAutoPtr.h"
--- a/gfx/src/nsRegion.cpp
+++ b/gfx/src/nsRegion.cpp
@@ -241,19 +241,17 @@ void nsRegion::RgnRect::operator delete 
 
 
 
 void nsRegion::Init()
 {
   mRectListHead.prev = mRectListHead.next = &mRectListHead;
   mCurRect = &mRectListHead;
   mRectCount = 0;
-  MOZ_ASSERT(mBoundRect.x == 0 && mBoundRect.y == 0 &&
-             mBoundRect.width == 0 && mBoundRect.height == 0,
-             "Caller must have initialized mBoundRect");
+  mBoundRect.SetRect (0, 0, 0, 0);
 }
 
 inline void nsRegion::InsertBefore (RgnRect* aNewRect, RgnRect* aRelativeRect)
 {
   aNewRect->prev = aRelativeRect->prev;
   aNewRect->next = aRelativeRect;
   aRelativeRect->prev->next = aNewRect;
   aRelativeRect->prev = aNewRect;
--- a/js/jsd/jsd_val.cpp
+++ b/js/jsd/jsd_val.cpp
@@ -472,20 +472,17 @@ JSDProperty*
 jsd_GetValueProperty(JSDContext* jsdc, JSDValue* jsdval, JSString* nameStr)
 {
     JS::RootedString name(jsdc->jsrt, nameStr);
     AutoSafeJSContext cx;
     JSAutoCompartment acBase(cx, jsdc->glob);
     JSDProperty* jsdprop;
     JSDProperty* iter = NULL;
     JS::RootedObject obj(cx);
-    unsigned  attrs = 0;
     bool found;
-    const jschar * nameChars;
-    size_t nameLen;
     JS::RootedValue val(cx), nameval(cx);
     JS::RootedId nameid(cx);
     JS::RootedValue propId(cx);
     JS::RootedValue propValue(cx);
     JS::RootedValue propAlias(cx);
     uint8_t propFlags;
 
     if(!jsd_IsValueObject(jsdc, jsdval))
@@ -499,34 +496,38 @@ jsd_GetValueProperty(JSDContext* jsdc, J
             int result;
             if (JS_CompareStrings(cx, propName, name, &result) && !result)
                 return jsdprop;
         }
         JSD_DropProperty(jsdc, jsdprop);
     }
     /* Not found in property list, look it up explicitly */
 
+    nameval = STRING_TO_JSVAL(name);
+    if(!JS_ValueToId(cx, nameval, nameid.address()))
+        return NULL;
+
     if(!(obj = JSVAL_TO_OBJECT(jsdval->val)))
         return NULL;
 
-    if (!(nameChars = JS_GetStringCharsZAndLength(cx, name, &nameLen)))
-        return NULL;
-
+    JS::Rooted<JSPropertyDescriptor> desc(cx);
     {
         JSAutoCompartment ac(cx, obj);
+        JS::RootedId id(cx, nameid);
 
-        JS_GetUCPropertyAttributes(cx, obj, nameChars, nameLen, &attrs, &found);
-        if (!found)
-        {
+        if(!JS_WrapId(cx, id.address()))
             return NULL;
-        }
+        if(!JS_GetOwnPropertyDescriptorById(cx, obj, id, 0, &desc))
+            return NULL;
+        if(!desc.object())
+            return NULL;
 
         JS_ClearPendingException(cx);
 
-        if(!JS_GetUCProperty(cx, obj, nameChars, nameLen, &val))
+        if(!JS_GetPropertyById(cx, obj, id, &val))
         {
             if (JS_IsExceptionPending(cx))
             {
                 if (!JS_GetPendingException(cx, propValue.address()))
                 {
                     return NULL;
                 }
                 propFlags = JSPD_EXCEPTION;
@@ -538,26 +539,23 @@ jsd_GetValueProperty(JSDContext* jsdc, J
             }
         }
         else
         {
             propValue = val;
         }
     }
 
-    nameval = STRING_TO_JSVAL(name);
-    if (!JS_ValueToId(cx, nameval, nameid.address()) ||
-        !JS_IdToValue(cx, nameid, propId.address())) {
+    if (!JS_IdToValue(cx, nameid, propId.address()))
         return NULL;
-    }
 
     propAlias = JSVAL_NULL;
-    propFlags |= (attrs & JSPROP_ENUMERATE) ? JSPD_ENUMERATE : 0
-        | (attrs & JSPROP_READONLY)  ? JSPD_READONLY  : 0
-        | (attrs & JSPROP_PERMANENT) ? JSPD_PERMANENT : 0;
+    propFlags |= desc.isEnumerable() ? JSPD_ENUMERATE : 0
+        | desc.isReadonly() ? JSPD_READONLY  : 0
+        | desc.isPermanent() ? JSPD_PERMANENT : 0;
 
     return _newProperty(jsdc, propId, propValue, propAlias, propFlags, JSDPD_HINTED);
 }
 
 /*
  * Retrieve a JSFunction* from a JSDValue*. This differs from
  * JS_ValueToFunction by fully unwrapping the object first.
  */
--- a/js/public/Class.h
+++ b/js/public/Class.h
@@ -368,20 +368,16 @@ typedef bool
 (* StrictSpecialIdOp)(JSContext *cx, JS::HandleObject obj, HandleSpecialId sid,
                       JS::MutableHandleValue vp, bool strict);
 typedef bool
 (* GenericAttributesOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id, unsigned *attrsp);
 typedef bool
 (* PropertyAttributesOp)(JSContext *cx, JS::HandleObject obj, JS::Handle<PropertyName*> name,
                          unsigned *attrsp);
 typedef bool
-(* ElementAttributesOp)(JSContext *cx, JS::HandleObject obj, uint32_t index, unsigned *attrsp);
-typedef bool
-(* SpecialAttributesOp)(JSContext *cx, JS::HandleObject obj, HandleSpecialId sid, unsigned *attrsp);
-typedef bool
 (* DeletePropertyOp)(JSContext *cx, JS::HandleObject obj, JS::Handle<PropertyName*> name,
                      bool *succeeded);
 typedef bool
 (* DeleteElementOp)(JSContext *cx, JS::HandleObject obj, uint32_t index, bool *succeeded);
 typedef bool
 (* DeleteSpecialOp)(JSContext *cx, JS::HandleObject obj, HandleSpecialId sid, bool *succeeded);
 
 
@@ -463,35 +459,28 @@ struct ObjectOps
     ElementIdOp         getElement;
     ElementIfPresentOp  getElementIfPresent; /* can be null */
     SpecialIdOp         getSpecial;
     StrictGenericIdOp   setGeneric;
     StrictPropertyIdOp  setProperty;
     StrictElementIdOp   setElement;
     StrictSpecialIdOp   setSpecial;
     GenericAttributesOp getGenericAttributes;
-    PropertyAttributesOp getPropertyAttributes;
-    ElementAttributesOp getElementAttributes;
-    SpecialAttributesOp getSpecialAttributes;
     GenericAttributesOp setGenericAttributes;
-    PropertyAttributesOp setPropertyAttributes;
-    ElementAttributesOp setElementAttributes;
-    SpecialAttributesOp setSpecialAttributes;
     DeletePropertyOp    deleteProperty;
     DeleteElementOp     deleteElement;
     DeleteSpecialOp     deleteSpecial;
 
     JSNewEnumerateOp    enumerate;
     ObjectOp            thisObject;
 };
 
 #define JS_NULL_OBJECT_OPS                                                    \
     {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,   \
-     NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,        \
-     NULL,NULL,NULL}
+     NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}
 
 } // namespace js
 
 // Classes, objects, and properties.
 
 typedef void (*JSClassInternal)();
 
 struct JSClass {
--- a/js/src/builtin/TypedObject.cpp
+++ b/js/src/builtin/TypedObject.cpp
@@ -1659,23 +1659,17 @@ Class BinaryBlock::class_ = {
         BinaryBlock::obj_getElement,
         BinaryBlock::obj_getElementIfPresent,
         BinaryBlock::obj_getSpecial,
         BinaryBlock::obj_setGeneric,
         BinaryBlock::obj_setProperty,
         BinaryBlock::obj_setElement,
         BinaryBlock::obj_setSpecial,
         BinaryBlock::obj_getGenericAttributes,
-        BinaryBlock::obj_getPropertyAttributes,
-        BinaryBlock::obj_getElementAttributes,
-        BinaryBlock::obj_getSpecialAttributes,
         BinaryBlock::obj_setGenericAttributes,
-        BinaryBlock::obj_setPropertyAttributes,
-        BinaryBlock::obj_setElementAttributes,
-        BinaryBlock::obj_setSpecialAttributes,
         BinaryBlock::obj_deleteProperty,
         BinaryBlock::obj_deleteElement,
         BinaryBlock::obj_deleteSpecial,
         BinaryBlock::obj_enumerate,
         NULL, /* thisObject */
     }
 };
 
@@ -2199,43 +2193,16 @@ BinaryBlock::obj_getGenericAttributes(JS
     if (!proto) {
         *attrsp = 0;
         return true;
     }
 
     return JSObject::getGenericAttributes(cx, proto, id, attrsp);
 }
 
-bool
-BinaryBlock::obj_getPropertyAttributes(JSContext *cx, HandleObject obj,
-                                        HandlePropertyName name,
-                                        unsigned *attrsp)
-{
-    RootedId id(cx, NameToId(name));
-    return obj_getGenericAttributes(cx, obj, id, attrsp);
-}
-
-bool
-BinaryBlock::obj_getElementAttributes(JSContext *cx, HandleObject obj,
-                                       uint32_t index, unsigned *attrsp)
-{
-    RootedId id(cx);
-    if (!IndexToId(cx, index, &id))
-        return false;
-    return obj_getGenericAttributes(cx, obj, id, attrsp);
-}
-
-bool
-BinaryBlock::obj_getSpecialAttributes(JSContext *cx, HandleObject obj,
-                                       HandleSpecialId sid, unsigned *attrsp)
-{
-    RootedId id(cx, SPECIALID_TO_JSID(sid));
-    return obj_getGenericAttributes(cx, obj, id, attrsp);
-}
-
 static bool
 IsOwnId(JSContext *cx, HandleObject obj, HandleId id)
 {
     uint32_t index;
     RootedObject type(cx, GetType(obj));
     TypeRepresentation *typeRepr = typeRepresentation(type);
 
     switch (typeRepr->kind()) {
@@ -2266,43 +2233,16 @@ BinaryBlock::obj_setGenericAttributes(JS
         *attrsp = 0;
         return true;
     }
 
     return JSObject::setGenericAttributes(cx, proto, id, attrsp);
 }
 
 bool
-BinaryBlock::obj_setPropertyAttributes(JSContext *cx, HandleObject obj,
-                                        HandlePropertyName name,
-                                        unsigned *attrsp)
-{
-    RootedId id(cx, NameToId(name));
-    return obj_setGenericAttributes(cx, obj, id, attrsp);
-}
-
-bool
-BinaryBlock::obj_setElementAttributes(JSContext *cx, HandleObject obj,
-                                       uint32_t index, unsigned *attrsp)
-{
-    RootedId id(cx);
-    if (!IndexToId(cx, index, &id))
-        return false;
-    return obj_setGenericAttributes(cx, obj, id, attrsp);
-}
-
-bool
-BinaryBlock::obj_setSpecialAttributes(JSContext *cx, HandleObject obj,
-                                      HandleSpecialId sid, unsigned *attrsp)
-{
-    RootedId id(cx, SPECIALID_TO_JSID(sid));
-    return obj_setGenericAttributes(cx, obj, id, attrsp);
-}
-
-bool
 BinaryBlock::obj_deleteProperty(JSContext *cx, HandleObject obj,
                                 HandlePropertyName name, bool *succeeded)
 {
     Rooted<jsid> id(cx, NameToId(name));
     if (IsOwnId(cx, obj, id))
         return ReportPropertyError(cx, JSMSG_CANT_DELETE, id);
 
     RootedObject proto(cx, obj->getProto());
--- a/js/src/builtin/TypedObject.h
+++ b/js/src/builtin/TypedObject.h
@@ -176,31 +176,18 @@ class BinaryBlock
                                   MutableHandleValue vp, bool strict);
     static bool obj_setElement(JSContext *cx, HandleObject obj, uint32_t index,
                                  MutableHandleValue vp, bool strict);
     static bool obj_setSpecial(JSContext *cx, HandleObject obj,
                                  HandleSpecialId sid, MutableHandleValue vp, bool strict);
 
     static bool obj_getGenericAttributes(JSContext *cx, HandleObject obj,
                                            HandleId id, unsigned *attrsp);
-    static bool obj_getPropertyAttributes(JSContext *cx, HandleObject obj,
-                                            HandlePropertyName name, unsigned *attrsp);
-    static bool obj_getElementAttributes(JSContext *cx, HandleObject obj,
-                                           uint32_t index, unsigned *attrsp);
-    static bool obj_getSpecialAttributes(JSContext *cx, HandleObject obj,
-                                           HandleSpecialId sid, unsigned *attrsp);
-
     static bool obj_setGenericAttributes(JSContext *cx, HandleObject obj,
                                            HandleId id, unsigned *attrsp);
-    static bool obj_setPropertyAttributes(JSContext *cx, HandleObject obj,
-                                            HandlePropertyName name, unsigned *attrsp);
-    static bool obj_setElementAttributes(JSContext *cx, HandleObject obj,
-                                           uint32_t index, unsigned *attrsp);
-    static bool obj_setSpecialAttributes(JSContext *cx, HandleObject obj,
-                                           HandleSpecialId sid, unsigned *attrsp);
 
     static bool obj_deleteProperty(JSContext *cx, HandleObject obj, HandlePropertyName name,
                                      bool *succeeded);
     static bool obj_deleteElement(JSContext *cx, HandleObject obj, uint32_t index,
                                     bool *succeeded);
     static bool obj_deleteSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid,
                                     bool *succeeded);
 
--- a/js/src/jit/Ion.cpp
+++ b/js/src/jit/Ion.cpp
@@ -1647,16 +1647,21 @@ IonCompile(JSContext *cx, JSScript *scri
 
     JS_ASSERT(!GetIonScript(builder->script(), executionMode));
     JS_ASSERT(CanIonCompile(builder->script(), executionMode));
 
     RootedScript builderScript(cx, builder->script());
     IonSpewNewFunction(graph, builderScript);
 
     if (!builder->build()) {
+        if (cx->isExceptionPending()) {
+            IonSpew(IonSpew_Abort, "Builder raised exception.");
+            return AbortReason_Error;
+        }
+
         IonSpew(IonSpew_Abort, "Builder failed to build.");
         return builder->abortReason();
     }
     builder->clearForBackEnd();
 
     // If possible, compile the script off thread.
     if (OffThreadCompilationAvailable(cx)) {
         SetIonScript(builder->script(), executionMode, ION_COMPILING_SCRIPT);
@@ -1827,16 +1832,19 @@ Compile(JSContext *cx, HandleScript scri
     if (executionMode == SequentialExecution) {
         // Use getUseCount instead of incUseCount to avoid bumping the
         // use count twice.
         if (script->getUseCount() < js_IonOptions.usesBeforeCompile)
             return Method_Skipped;
     }
 
     AbortReason reason = IonCompile(cx, script, osrFrame, osrPc, constructing, executionMode);
+    if (reason == AbortReason_Error)
+        return Method_Error;
+
     if (reason == AbortReason_Disable)
         return Method_CantCompile;
 
     // Compilation succeeded or we invalidated right away or an inlining/alloc abort
     return HasIonScript(script, executionMode) ? Method_Compiled : Method_Skipped;
 }
 
 } // namespace jit
--- a/js/src/jit/Ion.h
+++ b/js/src/jit/Ion.h
@@ -250,16 +250,17 @@ enum MethodStatus
     Method_Skipped,
     Method_Compiled
 };
 
 enum AbortReason {
     AbortReason_Alloc,
     AbortReason_Inlining,
     AbortReason_Disable,
+    AbortReason_Error,
     AbortReason_NoAbort
 };
 
 // An Ion context is needed to enter into either an Ion method or an instance
 // of the Ion compiler. It points to a temporary allocator and the active
 // JSContext, either of which may be NULL, and the active compartment, which
 // will not be NULL.
 
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -3767,24 +3767,33 @@ IonBuilder::inlineScriptedCall(CallInfo 
                                                  this->info().executionMode());
     if (!info)
         return false;
 
     MIRGraphExits saveExits;
     AutoAccumulateExits aae(graph(), saveExits);
 
     // Build the graph.
+    JS_ASSERT(!cx->isExceptionPending());
     IonBuilder inlineBuilder(cx, &temp(), &graph(), &inspector, info, NULL,
                              inliningDepth_ + 1, loopDepth_);
     if (!inlineBuilder.buildInline(this, outerResumePoint, callInfo)) {
         JS_ASSERT(calleeScript->hasAnalysis());
+        if (cx->isExceptionPending()) {
+            IonSpew(IonSpew_Abort, "Inline builder raised exception.");
+            abortReason_ = AbortReason_Error;
+            return false;
+        }
 
         // Inlining the callee failed. Disable inlining the function
-        if (inlineBuilder.abortReason_ == AbortReason_Disable)
+        if (inlineBuilder.abortReason_ == AbortReason_Disable) {
+            // Only mark callee as un-inlineable only if the inlining was aborted
+            // for a non-exception reason.
             calleeScript->analysis()->setIonUninlineable();
+        }
 
         abortReason_ = AbortReason_Inlining;
         return false;
     }
 
     // Create return block.
     jsbytecode *postCall = GetNextPc(pc);
     MBasicBlock *returnBlock = newBlock(NULL, postCall);
@@ -5560,19 +5569,30 @@ IonBuilder::jsop_initprop(HandleProperty
     if (!CanEffectlesslyCallLookupGenericOnObject(cx, templateObject, id))
         return abort("INITPROP template object is special");
 
     bool res = LookupPropertyWithFlags(cx, templateObject, id,
                                        0, &holder, &shape);
     if (!res)
         return false;
 
-    if (!shape || holder != templateObject ||
-        PropertyWriteNeedsTypeBarrier(cx, current, &obj, name, &value))
+    if (!shape || holder != templateObject) {
+        // JSOP_NEWINIT becomes an MNewObject without preconfigured properties.
+        MInitProp *init = MInitProp::New(obj, name, value);
+        current->add(init);
+        return resumeAfter(init);
+    }
+
+    bool writeNeedsBarrier = false;
+    if (!PropertyWriteNeedsTypeBarrier(cx, current, &obj, name, &value, /* canModify = */ true,
+                                       &writeNeedsBarrier))
     {
+        return false;
+    }
+    if (writeNeedsBarrier) {
         // JSOP_NEWINIT becomes an MNewObject without preconfigured properties.
         MInitProp *init = MInitProp::New(obj, name, value);
         current->add(init);
         return resumeAfter(init);
     }
 
     if (NeedsPostBarrier(info(), value))
         current->add(MPostWriteBarrier::New(obj, value));
@@ -6262,17 +6282,22 @@ IonBuilder::getStaticName(HandleObject s
     if (propertyTypes && propertyTypes->isOwnProperty(cx, staticType, true)) {
         // The property has been reconfigured as non-configurable, non-enumerable
         // or non-writable.
         *psucceeded = false;
         return true;
     }
 
     types::StackTypeSet *types = types::TypeScript::BytecodeTypes(script(), pc);
-    bool barrier = PropertyReadNeedsTypeBarrier(cx, staticType, name, types);
+    bool barrier;
+    if (!PropertyReadNeedsTypeBarrier(cx, staticType, name, types, /* updateObserved = */ true,
+                                      &barrier))
+    {
+        return false;
+    }
 
     // If the property is permanent, a shape guard isn't necessary.
 
     JSObject *singleton = types->getSingleton();
 
     JSValueType knownType = types->getKnownTypeTag();
     if (!barrier) {
         if (singleton) {
@@ -6786,17 +6811,19 @@ IonBuilder::getElemTryCache(bool *emitte
     // of this getelem.
     bool nonNativeGetElement = inspector->hasSeenNonNativeGetElement(pc);
     if (index->mightBeType(MIRType_Int32) && nonNativeGetElement)
         return true;
 
     // Emit GetElementCache.
 
     types::StackTypeSet *types = types::TypeScript::BytecodeTypes(script(), pc);
-    bool barrier = PropertyReadNeedsTypeBarrier(cx, obj, NULL, types);
+    bool barrier;
+    if (!PropertyReadNeedsTypeBarrier(cx, obj, NULL, types, &barrier))
+        return false;
 
     // Always add a barrier if the index might be a string, so that the cache
     // can attach stubs for particular properties.
     if (index->mightBeType(MIRType_String))
         barrier = true;
 
     // See note about always needing a barrier in jsop_getprop.
     if (needsToMonitorMissingProperties(types))
@@ -6830,20 +6857,24 @@ bool
 IonBuilder::jsop_getelem_dense(MDefinition *obj, MDefinition *index)
 {
     types::StackTypeSet *types = types::TypeScript::BytecodeTypes(script(), pc);
 
     if (JSOp(*pc) == JSOP_CALLELEM && !index->mightBeType(MIRType_String) && types->noConstraints()) {
         // Indexed call on an element of an array. Populate the observed types
         // with any objects that could be in the array, to avoid extraneous
         // type barriers.
-        AddObjectsForPropertyRead(cx, obj, NULL, types);
-    }
-
-    bool barrier = PropertyReadNeedsTypeBarrier(cx, obj, NULL, types);
+        if (!AddObjectsForPropertyRead(cx, obj, NULL, types))
+            return false;
+    }
+
+    bool barrier;
+    if (!PropertyReadNeedsTypeBarrier(cx, obj, NULL, types, &barrier))
+        return false;
+
     bool needsHoleCheck = !ElementAccessIsPacked(cx, obj);
 
     // Reads which are on holes in the object do not have to bail out if
     // undefined values have been observed at this access site and the access
     // cannot hit another indexed property on the object or its prototypes.
     bool readOutOfBounds =
         types->hasType(types::Type::UndefinedType()) &&
         !ElementAccessHasExtraIndexedProperty(cx, obj);
@@ -7198,17 +7229,23 @@ IonBuilder::setElemTryTyped(bool *emitte
 bool
 IonBuilder::setElemTryDense(bool *emitted, MDefinition *object,
                             MDefinition *index, MDefinition *value)
 {
     JS_ASSERT(*emitted == false);
 
     if (!ElementAccessIsDenseNative(object, index))
         return true;
-    if (PropertyWriteNeedsTypeBarrier(cx, current, &object, NULL, &value))
+    bool needsBarrier;
+    if (!PropertyWriteNeedsTypeBarrier(cx, current, &object, NULL, &value, /* canModify = */ true,
+                                       &needsBarrier))
+    {
+        return false;
+    }
+    if (needsBarrier)
         return true;
     if (!object->resultTypeSet())
         return true;
 
     types::StackTypeSet::DoubleConversion conversion =
         object->resultTypeSet()->convertDoubleElements(cx);
 
     // If AmbiguousDoubleConversion, only handle int32 values for now.
@@ -7258,17 +7295,24 @@ IonBuilder::setElemTryCache(bool *emitte
 
     // TODO: Bug 876650: remove this check:
     // Temporary disable the cache if non dense native,
     // untill the cache supports more ics
     SetElemICInspector icInspect(inspector->setElemICInspector(pc));
     if (!icInspect.sawDenseWrite())
         return true;
 
-    if (PropertyWriteNeedsTypeBarrier(cx, current, &object, NULL, &value))
+    bool needsBarrier;
+    if (PropertyWriteNeedsTypeBarrier(cx, current, &object, NULL, &value, /* canModify = */ true,
+                                      &needsBarrier))
+    {
+        return false;
+    }
+
+    if (needsBarrier)
         return true;
 
     // Emit SetElementCache.
     MInstruction *ins = MSetElementCache::New(object, index, value, script()->strict);
     current->add(ins);
     current->push(value);
 
     if (!resumeAfter(ins))
@@ -7278,17 +7322,20 @@ IonBuilder::setElemTryCache(bool *emitte
     return true;
 }
 
 bool
 IonBuilder::jsop_setelem_dense(types::StackTypeSet::DoubleConversion conversion,
                                SetElemSafety safety,
                                MDefinition *obj, MDefinition *id, MDefinition *value)
 {
-    MIRType elementType = DenseNativeElementType(cx, obj);
+    MIRType elementType;
+    if (!DenseNativeElementType(cx, obj, &elementType))
+        return false;
+
     bool packed = ElementAccessIsPacked(cx, obj);
 
     // Writes which are on holes in the object do not have to bail out if they
     // cannot hit another indexed property on the object or its prototypes.
     bool writeOutOfBounds = !ElementAccessHasExtraIndexedProperty(cx, obj);
 
     if (NeedsPostBarrier(info(), value))
         current->add(MPostWriteBarrier::New(obj, value));
@@ -8095,17 +8142,19 @@ IonBuilder::jsop_getprop(HandlePropertyN
     bool emitted = false;
 
     types::StackTypeSet *types = types::TypeScript::BytecodeTypes(script(), pc);
 
     // Try to optimize arguments.length.
     if (!getPropTryArgumentsLength(&emitted) || emitted)
         return emitted;
 
-    bool barrier = PropertyReadNeedsTypeBarrier(cx, current->peek(-1), name, types);
+    bool barrier;
+    if (!PropertyReadNeedsTypeBarrier(cx, current->peek(-1), name, types, &barrier))
+        return false;
 
     // Try to hardcode known constants.
     if (!getPropTryConstant(&emitted, id, types) || emitted)
         return emitted;
 
     // Except when loading constants above, always use a call if we are doing
     // the definite properties analysis and not actually emitting code, to
     // simplify later analysis.
@@ -8400,17 +8449,21 @@ IonBuilder::getPropTryCache(bool *emitte
     //
     // In parallel execution, idempotency of caches is ignored, since we
     // repeat the entire ForkJoin workload if we bail out. Note that it's
     // overly restrictive to mark everything as idempotent, because we can
     // treat non-idempotent caches in parallel as repeatable.
     if (obj->type() == MIRType_Object && !invalidatedIdempotentCache() &&
         info().executionMode() != ParallelExecution)
     {
-        if (PropertyReadIsIdempotent(cx, obj, name))
+        bool idempotent;
+        if (!PropertyReadIsIdempotent(cx, obj, name, &idempotent))
+            return false;
+
+        if (idempotent)
             load->setIdempotent();
     }
 
     if (JSOp(*pc) == JSOP_CALLPROP) {
         if (!annotateGetPropertyCache(cx, obj, load, obj->resultTypeSet(), types))
             return false;
     }
 
@@ -8475,17 +8528,22 @@ IonBuilder::jsop_setprop(HandlePropertyN
     if (NeedsPostBarrier(info(), value))
         current->add(MPostWriteBarrier::New(obj, value));
 
     // Try to inline a common property setter, or make a call.
     if (!setPropTryCommonSetter(&emitted, obj, name, id, value) || emitted)
         return emitted;
 
     types::StackTypeSet *objTypes = obj->resultTypeSet();
-    bool barrier = PropertyWriteNeedsTypeBarrier(cx, current, &obj, name, &value);
+    bool barrier;
+    if (!PropertyWriteNeedsTypeBarrier(cx, current, &obj, name, &value,
+                                       /* canModify = */ true, &barrier))
+    {
+        return false;
+    }
 
     // Try to emit store from definite slots.
     if (!setPropTryDefiniteSlot(&emitted, obj, name, value, barrier, objTypes) || emitted)
         return emitted;
 
     // Try to emit a monomorphic/polymorphic store based on baseline caches.
     if (!setPropTryInlineAccess(&emitted, obj, name, id, value, barrier, objTypes) || emitted)
         return emitted;
--- a/js/src/jit/MCallOptimize.cpp
+++ b/js/src/jit/MCallOptimize.cpp
@@ -318,17 +318,20 @@ IonBuilder::inlineArrayPopShift(CallInfo
         return InliningStatus_NotInlined;
 
     callInfo.unwrapArgs();
 
     types::StackTypeSet *returnTypes = getInlineReturnTypeSet();
     bool needsHoleCheck = thisTypes->hasObjectFlags(cx, types::OBJECT_FLAG_NON_PACKED);
     bool maybeUndefined = returnTypes->hasType(types::Type::UndefinedType());
 
-    bool barrier = PropertyReadNeedsTypeBarrier(cx, callInfo.thisArg(), NULL, returnTypes);
+    bool barrier;
+    if (!PropertyReadNeedsTypeBarrier(cx, callInfo.thisArg(), NULL, returnTypes, &barrier))
+        return InliningStatus_Error;
+
     if (barrier)
         returnType = MIRType_Value;
 
     MArrayPopShift *ins = MArrayPopShift::New(callInfo.thisArg(), mode,
                                               needsHoleCheck, maybeUndefined);
     current->add(ins);
     current->push(ins);
     ins->setResultType(returnType);
@@ -345,17 +348,23 @@ IonBuilder::inlineArrayPopShift(CallInfo
 IonBuilder::InliningStatus
 IonBuilder::inlineArrayPush(CallInfo &callInfo)
 {
     if (callInfo.argc() != 1 || callInfo.constructing())
         return InliningStatus_NotInlined;
 
     MDefinition *obj = callInfo.thisArg();
     MDefinition *value = callInfo.getArg(0);
-    if (PropertyWriteNeedsTypeBarrier(cx, current, &obj, NULL, &value, /* canModify = */ false))
+    bool writeNeedsBarrier;
+    if (!PropertyWriteNeedsTypeBarrier(cx, current, &obj, NULL, &value, /* canModify = */ false,
+                                       &writeNeedsBarrier))
+    {
+        return InliningStatus_Error;
+    }
+    if (writeNeedsBarrier)
         return InliningStatus_NotInlined;
     JS_ASSERT(obj == callInfo.thisArg() && value == callInfo.getArg(0));
 
     if (getInlineReturnType() != MIRType_Int32)
         return InliningStatus_NotInlined;
     if (callInfo.thisArg()->type() != MIRType_Object)
         return InliningStatus_NotInlined;
 
@@ -997,22 +1006,32 @@ IonBuilder::inlineUnsafePutElements(Call
         uint32_t arri = base + 0;
         uint32_t idxi = base + 1;
         uint32_t elemi = base + 2;
 
         MDefinition *obj = callInfo.getArg(arri);
         MDefinition *id = callInfo.getArg(idxi);
         MDefinition *elem = callInfo.getArg(elemi);
 
+        bool isDenseNative = ElementAccessIsDenseNative(obj, id);
+
+        bool writeNeedsBarrier = false;
+        if (isDenseNative) {
+            if (!PropertyWriteNeedsTypeBarrier(cx, current, &obj, NULL, &elem,
+                                               /* canModify = */ false,
+                                               &writeNeedsBarrier))
+            {
+                return InliningStatus_Error;
+            }
+        }
+
         // We can only inline setelem on dense arrays that do not need type
         // barriers and on typed arrays.
         ScalarTypeRepresentation::Type arrayType;
-        if ((!ElementAccessIsDenseNative(obj, id) ||
-             PropertyWriteNeedsTypeBarrier(cx, current, &obj, NULL,
-                                           &elem, /* canModify = */ false)) &&
+        if ((!isDenseNative || writeNeedsBarrier) &&
             !ElementAccessIsTypedArray(obj, id, &arrayType))
         {
             return InliningStatus_NotInlined;
         }
     }
 
     callInfo.unwrapArgs();
 
--- a/js/src/jit/MIR.cpp
+++ b/js/src/jit/MIR.cpp
@@ -2525,58 +2525,71 @@ jit::ElementAccessHasExtraIndexedPropert
     types::StackTypeSet *types = obj->resultTypeSet();
 
     if (!types || types->hasObjectFlags(cx, types::OBJECT_FLAG_LENGTH_OVERFLOW))
         return true;
 
     return types::TypeCanHaveExtraIndexedProperties(cx, types);
 }
 
-MIRType
-jit::DenseNativeElementType(JSContext *cx, MDefinition *obj)
+bool
+jit::DenseNativeElementType(JSContext *cx, MDefinition *obj, MIRType *result)
 {
+    JS_ASSERT(result);
+    *result = MIRType_None;
+
     types::StackTypeSet *types = obj->resultTypeSet();
     MIRType elementType = MIRType_None;
     unsigned count = types->getObjectCount();
 
     for (unsigned i = 0; i < count; i++) {
-        if (types::TypeObject *object = types->getTypeOrSingleObject(cx, i)) {
-            if (object->unknownProperties())
-                return MIRType_None;
-
-            types::HeapTypeSet *elementTypes = object->getProperty(cx, JSID_VOID, false);
-            if (!elementTypes)
-                return MIRType_None;
-
-            MIRType type = MIRTypeFromValueType(elementTypes->getKnownTypeTag(cx));
-            if (type == MIRType_None)
-                return MIRType_None;
-
-            if (elementType == MIRType_None)
-                elementType = type;
-            else if (elementType != type)
-                return MIRType_None;
-        }
+        types::TypeObject *object;
+        if (!types->getTypeOrSingleObject(cx, i, &object))
+            return false;
+
+        if (!object)
+            continue;
+
+        if (object->unknownProperties())
+            return true;
+
+        types::HeapTypeSet *elementTypes = object->getProperty(cx, JSID_VOID, false);
+        if (!elementTypes)
+            return true;
+
+        MIRType type = MIRTypeFromValueType(elementTypes->getKnownTypeTag(cx));
+        if (type == MIRType_None)
+            return true;
+
+        if (elementType == MIRType_None)
+            elementType = type;
+        else if (elementType != type)
+            return true;
     }
 
-    return elementType;
+    *result = elementType;
+    return true;
 }
 
 bool
 jit::PropertyReadNeedsTypeBarrier(JSContext *cx, types::TypeObject *object, PropertyName *name,
-                                  types::StackTypeSet *observed, bool updateObserved)
+                                  types::StackTypeSet *observed, bool updateObserved, bool *result)
 {
     // If the object being read from has types for the property which haven't
     // been observed at this access site, the read could produce a new type and
     // a barrier is needed. Note that this only covers reads from properties
     // which are accounted for by type information, i.e. native data properties
     // and elements.
-
-    if (object->unknownProperties())
+    JS_ASSERT(result);
+    *result = false;
+
+    if (object->unknownProperties()) {
+        *result = true;
         return true;
+    }
 
     jsid id = name ? types::IdToTypeId(NameToId(name)) : JSID_VOID;
 
     // If this access has never executed, try to add types to the observed set
     // according to any property which exists on the object or its prototype.
     if (updateObserved && observed->empty() && observed->noConstraints() && !JSID_IS_VOID(id)) {
         JSObject *obj = object->singleton ? object->singleton : object->proto;
 
@@ -2591,151 +2604,186 @@ jit::PropertyReadNeedsTypeBarrier(JSCont
                 observed->addType(cx, types::GetValueType(v));
             }
 
             obj = obj->getProto();
         }
     }
 
     types::HeapTypeSet *property = object->getProperty(cx, id, false);
-    if (!property)
+    if (!property) {
+        *result = true;
         return true;
+    }
 
     // We need to consider possible types for the property both as an 'own'
     // property on the object and as inherited from any prototype. Type sets
     // for a property do not, however, reflect inherited types until a
     // getFromPrototypes() call has been performed.
     if (!property->hasPropagatedProperty())
         object->getFromPrototypes(cx, id, property);
 
-    if (!TypeSetIncludes(observed, MIRType_Value, property))
+    if (!TypeSetIncludes(observed, MIRType_Value, property)) {
+        *result = true;
         return true;
+    }
 
     // Type information for singleton objects is not required to reflect the
     // initial 'undefined' value for native properties, in particular global
     // variables declared with 'var'. Until the property is assigned a value
     // other than undefined, a barrier is required.
     if (name && object->singleton && object->singleton->isNative()) {
         Shape *shape = object->singleton->nativeLookup(cx, name);
         if (shape &&
             shape->hasDefaultGetter() &&
             object->singleton->nativeGetSlot(shape->slot()).isUndefined())
         {
+            *result = true;
             return true;
         }
     }
 
     property->addFreeze(cx);
-    return false;
+    *result = false;
+    return true;
 }
 
 bool
 jit::PropertyReadNeedsTypeBarrier(JSContext *cx, MDefinition *obj, PropertyName *name,
-                                  types::StackTypeSet *observed)
+                                  types::StackTypeSet *observed, bool *result)
 {
+    JS_ASSERT(result);
+    *result = false;
+
     if (observed->unknown())
-        return false;
+        return true;
 
     types::TypeSet *types = obj->resultTypeSet();
-    if (!types || types->unknownObject())
+    if (!types || types->unknownObject()) {
+        *result = true;
         return true;
+    }
 
     bool updateObserved = types->getObjectCount() == 1;
     for (size_t i = 0; i < types->getObjectCount(); i++) {
-        types::TypeObject *object = types->getTypeOrSingleObject(cx, i);
-        if (object && PropertyReadNeedsTypeBarrier(cx, object, name, observed, updateObserved))
-            return true;
+        types::TypeObject *object;
+        if (!types->getTypeOrSingleObject(cx, i, &object))
+            return false;
+
+        if (object) {
+            if (!PropertyReadNeedsTypeBarrier(cx, object, name, observed, updateObserved, result))
+                return false;
+
+            if (*result)
+                return true;
+        }
     }
 
-    return false;
+    *result = false;
+    return true;
 }
 
 bool
-jit::PropertyReadIsIdempotent(JSContext *cx, MDefinition *obj, PropertyName *name)
+jit::PropertyReadIsIdempotent(JSContext *cx, MDefinition *obj, PropertyName *name, bool *result)
 {
+    JS_ASSERT(result);
+    *result = false;
     // Determine if reading a property from obj is likely to be idempotent.
 
     jsid id = types::IdToTypeId(NameToId(name));
 
     types::TypeSet *types = obj->resultTypeSet();
     if (!types || types->unknownObject())
-        return false;
+        return true;
 
     for (size_t i = 0; i < types->getObjectCount(); i++) {
-        if (types::TypeObject *object = types->getTypeOrSingleObject(cx, i)) {
+        types::TypeObject *object;
+        if (!types->getTypeOrSingleObject(cx, i, &object))
+            return false;
+
+        if (object) {
             if (object->unknownProperties())
-                return false;
+                return true;
 
             // Check if the property has been reconfigured or is a getter.
             types::HeapTypeSet *property = object->getProperty(cx, id, false);
             if (!property || property->isOwnProperty(cx, object, true))
-                return false;
+                return true;
         }
     }
 
+    *result = true;
     return true;
 }
 
-void
+bool
 jit::AddObjectsForPropertyRead(JSContext *cx, MDefinition *obj, PropertyName *name,
                                types::StackTypeSet *observed)
 {
     // Add objects to observed which *could* be observed by reading name from obj,
     // to hopefully avoid unnecessary type barriers and code invalidations.
 
     JS_ASSERT(observed->noConstraints());
 
     types::StackTypeSet *types = obj->resultTypeSet();
     if (!types || types->unknownObject()) {
         observed->addType(cx, types::Type::AnyObjectType());
-        return;
+        return true;
     }
 
     jsid id = name ? types::IdToTypeId(NameToId(name)) : JSID_VOID;
 
     for (size_t i = 0; i < types->getObjectCount(); i++) {
-        types::TypeObject *object = types->getTypeOrSingleObject(cx, i);
+        types::TypeObject *object;
+        if (!types->getTypeOrSingleObject(cx, i, &object))
+            return false;
+
         if (!object)
             continue;
 
         if (object->unknownProperties()) {
             observed->addType(cx, types::Type::AnyObjectType());
-            return;
+            return true;
         }
 
         types::HeapTypeSet *property = object->getProperty(cx, id, false);
         if (property->unknownObject()) {
             observed->addType(cx, types::Type::AnyObjectType());
-            return;
+            return true;
         }
 
         for (size_t i = 0; i < property->getObjectCount(); i++) {
             if (types::TypeObject *object = property->getTypeObject(i))
                 observed->addType(cx, types::Type::ObjectType(object));
             else if (JSObject *object = property->getSingleObject(i))
                 observed->addType(cx, types::Type::ObjectType(object));
         }
     }
+
+    return true;
 }
 
 static bool
 TryAddTypeBarrierForWrite(JSContext *cx, MBasicBlock *current, types::StackTypeSet *objTypes,
                           jsid id, MDefinition **pvalue)
 {
     // Return whether pvalue was modified to include a type barrier ensuring
     // that writing the value to objTypes/id will not require changing type
     // information.
 
     // All objects in the set must have the same types for id. Otherwise, we
     // could bail out without subsequently triggering a type change that
     // invalidates the compiled code.
     types::HeapTypeSet *aggregateProperty = NULL;
 
     for (size_t i = 0; i < objTypes->getObjectCount(); i++) {
-        types::TypeObject *object = objTypes->getTypeOrSingleObject(cx, i);
+        types::TypeObject *object;
+        if (!objTypes->getTypeOrSingleObject(cx, i, &object))
+            return false;
+
         if (!object)
             continue;
 
         if (object->unknownProperties())
             return false;
 
         types::HeapTypeSet *property = object->getProperty(cx, id, false);
         if (!property)
@@ -2803,83 +2851,103 @@ AddTypeGuard(MBasicBlock *current, MDefi
     // For now, never move type object guards.
     guard->setNotMovable();
 
     return guard;
 }
 
 bool
 jit::PropertyWriteNeedsTypeBarrier(JSContext *cx, MBasicBlock *current, MDefinition **pobj,
-                                   PropertyName *name, MDefinition **pvalue, bool canModify)
+                                   PropertyName *name, MDefinition **pvalue, bool canModify,
+                                   bool *result)
 {
+    JS_ASSERT(result);
+    *result = false;
+
     // If any value being written is not reflected in the type information for
     // objects which obj could represent, a type barrier is needed when writing
     // the value. As for propertyReadNeedsTypeBarrier, this only applies for
     // properties that are accounted for by type information, i.e. normal data
     // properties and elements.
 
     types::StackTypeSet *types = (*pobj)->resultTypeSet();
-    if (!types || types->unknownObject())
+    if (!types || types->unknownObject()) {
+        *result = true;
         return true;
+    }
 
     jsid id = name ? types::IdToTypeId(NameToId(name)) : JSID_VOID;
 
     // If all of the objects being written to have property types which already
     // reflect the value, no barrier at all is needed. Additionally, if all
     // objects being written to have the same types for the property, and those
     // types do *not* reflect the value, add a type barrier for the value.
 
     bool success = true;
     for (size_t i = 0; i < types->getObjectCount(); i++) {
-        types::TypeObject *object = types->getTypeOrSingleObject(cx, i);
+        types::TypeObject *object;
+        if (!types->getTypeOrSingleObject(cx, i, &object))
+            return false;
+
         if (!object || object->unknownProperties())
             continue;
 
         types::HeapTypeSet *property = object->getProperty(cx, id, false);
         if (!property) {
             success = false;
             break;
         }
         if (!TypeSetIncludes(property, (*pvalue)->type(), (*pvalue)->resultTypeSet())) {
             // Either pobj or pvalue needs to be modified to filter out the
             // types which the value could have but are not in the property,
             // or a VM call is required. A VM call is always required if pobj
             // and pvalue cannot be modified.
-            if (!canModify)
+            if (!canModify) {
+                *result = true;
                 return true;
+            }
             success = TryAddTypeBarrierForWrite(cx, current, types, id, pvalue);
             break;
         }
     }
 
     if (success)
-        return false;
+        return true;
 
     // If all of the objects except one have property types which reflect the
     // value, and the remaining object has no types at all for the property,
     // add a guard that the object does not have that remaining object's type.
 
-    if (types->getObjectCount() <= 1)
+    if (types->getObjectCount() <= 1) {
+        *result = true;
         return true;
+    }
 
     types::TypeObject *excluded = NULL;
     for (size_t i = 0; i < types->getObjectCount(); i++) {
-        types::TypeObject *object = types->getTypeOrSingleObject(cx, i);
+        types::TypeObject *object;
+        if (!types->getTypeOrSingleObject(cx, i, &object))
+            return false;
+
         if (!object || object->unknownProperties())
             continue;
 
         types::HeapTypeSet *property = object->getProperty(cx, id, false);
-        if (!property)
+        if (!property) {
+            *result = true;
             return true;
+        }
 
         if (TypeSetIncludes(property, (*pvalue)->type(), (*pvalue)->resultTypeSet()))
             continue;
 
-        if (!property->empty() || excluded)
+        if (!property->empty() || excluded) {
+            *result = true;
             return true;
+        }
         excluded = object;
     }
 
     JS_ASSERT(excluded);
 
     *pobj = AddTypeGuard(current, *pobj, excluded, /* bailOnEquality = */ true);
-    return false;
+    return true;
 }
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -8505,24 +8505,24 @@ typedef Vector<MDefinition *, 8, IonAllo
 
 // Helper functions used to decide how to build MIR.
 
 bool ElementAccessIsDenseNative(MDefinition *obj, MDefinition *id);
 bool ElementAccessIsTypedArray(MDefinition *obj, MDefinition *id,
                                ScalarTypeRepresentation::Type *arrayType);
 bool ElementAccessIsPacked(JSContext *cx, MDefinition *obj);
 bool ElementAccessHasExtraIndexedProperty(JSContext *cx, MDefinition *obj);
-MIRType DenseNativeElementType(JSContext *cx, MDefinition *obj);
+bool DenseNativeElementType(JSContext *cx, MDefinition *obj, MIRType *result);
 bool PropertyReadNeedsTypeBarrier(JSContext *cx, types::TypeObject *object, PropertyName *name,
-                                  types::StackTypeSet *observed, bool updateObserved = true);
+                                  types::StackTypeSet *observed, bool updateObserved, bool *result);
 bool PropertyReadNeedsTypeBarrier(JSContext *cx, MDefinition *obj, PropertyName *name,
-                                  types::StackTypeSet *observed);
-bool PropertyReadIsIdempotent(JSContext *cx, MDefinition *obj, PropertyName *name);
-void AddObjectsForPropertyRead(JSContext *cx, MDefinition *obj, PropertyName *name,
+                                  types::StackTypeSet *observed, bool *result);
+bool PropertyReadIsIdempotent(JSContext *cx, MDefinition *obj, PropertyName *name, bool *result);
+bool AddObjectsForPropertyRead(JSContext *cx, MDefinition *obj, PropertyName *name,
                                types::StackTypeSet *observed);
 bool PropertyWriteNeedsTypeBarrier(JSContext *cx, MBasicBlock *current, MDefinition **pobj,
                                    PropertyName *name, MDefinition **pvalue,
-                                   bool canModify = true);
+                                   bool canModify, bool *result);
 
 } // namespace jit
 } // namespace js
 
 #endif /* jit_MIR_h */
--- a/js/src/jsapi-tests/testDefineGetterSetterNonEnumerable.cpp
+++ b/js/src/jsapi-tests/testDefineGetterSetterNonEnumerable.cpp
@@ -40,20 +40,19 @@ BEGIN_TEST(testDefineGetterSetterNonEnum
                             JSPROP_GETTER | JSPROP_SETTER | JSPROP_ENUMERATE));
 
     CHECK(JS_DefineProperty(cx, vObject, PROPERTY_NAME,
                             JSVAL_VOID,
                             JS_DATA_TO_FUNC_PTR(JSPropertyOp, (JSObject*) funGetObj),
                             JS_DATA_TO_FUNC_PTR(JSStrictPropertyOp, (JSObject*) funSetObj),
                             JSPROP_GETTER | JSPROP_SETTER | JSPROP_PERMANENT));
 
-    bool found = false;
-    unsigned attrs = 0;
-    CHECK(JS_GetPropertyAttributes(cx, vObject, PROPERTY_NAME, &attrs, &found));
-    CHECK(found);
-    CHECK(attrs & JSPROP_GETTER);
-    CHECK(attrs & JSPROP_SETTER);
-    CHECK(attrs & JSPROP_PERMANENT);
-    CHECK(!(attrs & JSPROP_ENUMERATE));
+    JS::Rooted<JSPropertyDescriptor> desc(cx);
+    CHECK(JS_GetOwnPropertyDescriptor(cx, vObject, PROPERTY_NAME, 0, &desc));
+    CHECK(desc.object());
+    CHECK(desc.hasGetterObject());
+    CHECK(desc.hasSetterObject());
+    CHECK(desc.isPermanent());
+    CHECK(!desc.isEnumerable());
 
     return true;
 }
 END_TEST(testDefineGetterSetterNonEnumerable)
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -3629,136 +3629,52 @@ GetPropertyDescriptorById(JSContext *cx,
         JS_ASSERT(desc.getter() == NULL);
         JS_ASSERT(desc.setter() == NULL);
         JS_ASSERT(desc.value().isUndefined());
     }
     return true;
 }
 
 JS_PUBLIC_API(bool)
+JS_GetOwnPropertyDescriptorById(JSContext *cx, JSObject *objArg, jsid idArg, unsigned flags,
+                                MutableHandle<JSPropertyDescriptor> desc)
+{
+    RootedObject obj(cx, objArg);
+    RootedId id(cx, idArg);
+    AssertHeapIsIdle(cx);
+    CHECK_REQUEST(cx);
+
+    return GetPropertyDescriptorById(cx, obj, id, flags, true, desc);
+}
+
+JS_PUBLIC_API(bool)
+JS_GetOwnPropertyDescriptor(JSContext *cx, JSObject *objArg, const char *name, unsigned flags,
+                            MutableHandle<JSPropertyDescriptor> desc)
+{
+    RootedObject obj(cx, objArg);
+    JSAtom *atom = Atomize(cx, name, strlen(name));
+    return atom && JS_GetOwnPropertyDescriptorById(cx, obj, AtomToId(atom), flags, desc);
+}
+
+JS_PUBLIC_API(bool)
 JS_GetPropertyDescriptorById(JSContext *cx, JSObject *objArg, jsid idArg, unsigned flags,
                              MutableHandle<JSPropertyDescriptor> desc)
 {
     RootedObject obj(cx, objArg);
     RootedId id(cx, idArg);
     return GetPropertyDescriptorById(cx, obj, id, flags, false, desc);
 }
 
 JS_PUBLIC_API(bool)
-JS_GetPropertyAttrsGetterAndSetterById(JSContext *cx, JSObject *objArg, jsid idArg,
-                                       unsigned *attrsp, bool *foundp,
-                                       JSPropertyOp *getterp, JSStrictPropertyOp *setterp)
-{
-    RootedObject obj(cx, objArg);
-    RootedId id(cx, idArg);
-    Rooted<PropertyDescriptor> desc(cx);
-    if (!GetPropertyDescriptorById(cx, obj, id, 0, false, &desc))
-        return false;
-
-    *attrsp = desc.attributes();
-    *foundp = !!desc.object();
-    if (getterp)
-        *getterp = desc.getter();
-    if (setterp)
-        *setterp = desc.setter();
-    return true;
-}
-
-JS_PUBLIC_API(bool)
-JS_GetPropertyAttributes(JSContext *cx, JSObject *objArg, const char *name,
-                         unsigned *attrsp, bool *foundp)
-{
-    RootedObject obj(cx, objArg);
-    JSAtom *atom = Atomize(cx, name, strlen(name));
-    return atom && JS_GetPropertyAttrsGetterAndSetterById(cx, obj, AtomToId(atom),
-                                                          attrsp, foundp, NULL, NULL);
-}
-
-JS_PUBLIC_API(bool)
-JS_GetUCPropertyAttributes(JSContext *cx, JSObject *objArg, const jschar *name, size_t namelen,
-                           unsigned *attrsp, bool *foundp)
-{
-    RootedObject obj(cx, objArg);
-    JSAtom *atom = AtomizeChars<CanGC>(cx, name, AUTO_NAMELEN(name, namelen));
-    return atom && JS_GetPropertyAttrsGetterAndSetterById(cx, obj, AtomToId(atom),
-                                                          attrsp, foundp, NULL, NULL);
-}
-
-JS_PUBLIC_API(bool)
-JS_GetPropertyAttrsGetterAndSetter(JSContext *cx, JSObject *objArg, const char *name,
-                                   unsigned *attrsp, bool *foundp,
-                                   JSPropertyOp *getterp, JSStrictPropertyOp *setterp)
+JS_GetPropertyDescriptor(JSContext *cx, JSObject *objArg, const char *name, unsigned flags,
+                         MutableHandle<JSPropertyDescriptor> desc)
 {
     RootedObject obj(cx, objArg);
     JSAtom *atom = Atomize(cx, name, strlen(name));
-    return atom && JS_GetPropertyAttrsGetterAndSetterById(cx, obj, AtomToId(atom),
-                                                          attrsp, foundp, getterp, setterp);
-}
-
-JS_PUBLIC_API(bool)
-JS_GetUCPropertyAttrsGetterAndSetter(JSContext *cx, JSObject *objArg,
-                                     const jschar *name, size_t namelen,
-                                     unsigned *attrsp, bool *foundp,
-                                     JSPropertyOp *getterp, JSStrictPropertyOp *setterp)
-{
-    RootedObject obj(cx, objArg);
-    JSAtom *atom = AtomizeChars<CanGC>(cx, name, AUTO_NAMELEN(name, namelen));
-    return atom && JS_GetPropertyAttrsGetterAndSetterById(cx, obj, AtomToId(atom),
-                                                          attrsp, foundp, getterp, setterp);
-}
-
-JS_PUBLIC_API(bool)
-JS_GetOwnPropertyDescriptor(JSContext *cx, JSObject *objArg, jsid idArg, MutableHandleValue vp)
-{
-    RootedObject obj(cx, objArg);
-    RootedId id(cx, idArg);
-    AssertHeapIsIdle(cx);
-    CHECK_REQUEST(cx);
-
-    return GetOwnPropertyDescriptor(cx, obj, id, vp);
-}
-
-static bool
-SetPropertyAttributesById(JSContext *cx, HandleObject obj, HandleId id, unsigned attrs, bool *foundp)
-{
-    RootedObject obj2(cx);
-    RootedShape shape(cx);
-
-    if (!LookupPropertyById(cx, obj, id, 0, &obj2, &shape))
-        return false;
-    if (!shape || obj != obj2) {
-        *foundp = false;
-        return true;
-    }
-    bool ok = obj->isNative()
-                ? JSObject::changePropertyAttributes(cx, obj, shape, attrs)
-                : JSObject::setGenericAttributes(cx, obj, id, &attrs);
-    if (ok)
-        *foundp = true;
-    return ok;
-}
-
-JS_PUBLIC_API(bool)
-JS_SetPropertyAttributes(JSContext *cx, JSObject *objArg, const char *name,
-                         unsigned attrs, bool *foundp)
-{
-    RootedObject obj(cx, objArg);
-    JSAtom *atom = Atomize(cx, name, strlen(name));
-    RootedId id(cx, AtomToId(atom));
-    return atom && SetPropertyAttributesById(cx, obj, id, attrs, foundp);
-}
-
-JS_PUBLIC_API(bool)
-JS_SetUCPropertyAttributes(JSContext *cx, JSObject *objArg, const jschar *name, size_t namelen,
-                           unsigned attrs, bool *foundp)
-{
-    RootedObject obj(cx, objArg);
-    JSAtom *atom = AtomizeChars<CanGC>(cx, name, AUTO_NAMELEN(name, namelen));
-    RootedId id(cx, AtomToId(atom));
-    return atom && SetPropertyAttributesById(cx, obj, id, attrs, foundp);
+    return atom && JS_GetPropertyDescriptorById(cx, obj, AtomToId(atom), flags, desc);
 }
 
 JS_PUBLIC_API(bool)
 JS_GetPropertyById(JSContext *cx, JSObject *objArg, jsid idArg, MutableHandleValue vp)
 {
     return JS_ForwardGetPropertyTo(cx, objArg, idArg, objArg, vp);
 }
 
@@ -6659,9 +6575,8 @@ JS_PreventExtensions(JSContext *cx, JS::
 {
     bool extensible;
     if (!JSObject::isExtensible(cx, obj, &extensible))
         return false;
     if (!extensible)
         return true;
     return JSObject::preventExtensions(cx, obj);
 }
-
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -2786,55 +2786,16 @@ JS_DefineProperty(JSContext *cx, JSObjec
 
 extern JS_PUBLIC_API(bool)
 JS_DefinePropertyById(JSContext *cx, JSObject *obj, jsid id, jsval value,
                       JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs);
 
 extern JS_PUBLIC_API(bool)
 JS_DefineOwnProperty(JSContext *cx, JSObject *obj, jsid id, jsval descriptor, bool *bp);
 
-/*
- * Determine the attributes (JSPROP_* flags) of a property on a given object.
- *
- * If the object does not have a property by that name, *foundp will be
- * false and the value of *attrsp is undefined.
- */
-extern JS_PUBLIC_API(bool)
-JS_GetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name,
-                         unsigned *attrsp, bool *foundp);
-
-/*
- * The same, but if the property is native, return its getter and setter via
- * *getterp and *setterp, respectively (and only if the out parameter pointer
- * is not null).
- */
-extern JS_PUBLIC_API(bool)
-JS_GetPropertyAttrsGetterAndSetter(JSContext *cx, JSObject *obj,
-                                   const char *name,
-                                   unsigned *attrsp, bool *foundp,
-                                   JSPropertyOp *getterp,
-                                   JSStrictPropertyOp *setterp);
-
-extern JS_PUBLIC_API(bool)
-JS_GetPropertyAttrsGetterAndSetterById(JSContext *cx, JSObject *obj,
-                                       jsid id,
-                                       unsigned *attrsp, bool *foundp,
-                                       JSPropertyOp *getterp,
-                                       JSStrictPropertyOp *setterp);
-
-/*
- * Set the attributes of a property on a given object.
- *
- * If the object does not have a property by that name, *foundp will be
- * false and nothing will be altered.
- */
-extern JS_PUBLIC_API(bool)
-JS_SetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name,
-                         unsigned attrs, bool *foundp);
-
 extern JS_PUBLIC_API(bool)
 JS_DefinePropertyWithTinyId(JSContext *cx, JSObject *obj, const char *name,
                             int8_t tinyid, jsval value,
                             JSPropertyOp getter, JSStrictPropertyOp setter,
                             unsigned attrs);
 
 extern JS_PUBLIC_API(bool)
 JS_AlreadyHasOwnProperty(JSContext *cx, JSObject *obj, const char *name,
@@ -3008,27 +2969,36 @@ class MutableHandleBase<JSPropertyDescri
     }
     JSPropertyDescriptor *extractMutable() {
         return static_cast<JS::MutableHandle<JSPropertyDescriptor>*>(this)->address();
     }
 };
 
 } /* namespace js */
 
+extern JS_PUBLIC_API(bool)
+JS_GetOwnPropertyDescriptorById(JSContext *cx, JSObject *objArg, jsid id, unsigned flags,
+                                JS::MutableHandle<JSPropertyDescriptor> desc);
+
+extern JS_PUBLIC_API(bool)
+JS_GetOwnPropertyDescriptor(JSContext *cx, JSObject *objArg, const char *name, unsigned flags,
+                            JS::MutableHandle<JSPropertyDescriptor> desc);
+
 /*
- * Like JS_GetPropertyAttrsGetterAndSetterById but will return a property on
- * an object on the prototype chain (returned in objp). If data->obj is null,
+ * Like JS_GetOwnPropertyDescriptorById but will return a property on
+ * an object on the prototype chain (returned in desc->obj). If desc->obj is null,
  * then this property was not found on the prototype chain.
  */
 extern JS_PUBLIC_API(bool)
 JS_GetPropertyDescriptorById(JSContext *cx, JSObject *obj, jsid id, unsigned flags,
                              JS::MutableHandle<JSPropertyDescriptor> desc);
 
 extern JS_PUBLIC_API(bool)
-JS_GetOwnPropertyDescriptor(JSContext *cx, JSObject *obj, jsid id, JS::MutableHandle<JS::Value> vp);
+JS_GetPropertyDescriptor(JSContext *cx, JSObject *obj, const char *name, unsigned flags,
+                         JS::MutableHandle<JSPropertyDescriptor> desc);
 
 extern JS_PUBLIC_API(bool)
 JS_GetProperty(JSContext *cx, JSObject *obj, const char *name, JS::MutableHandle<JS::Value> vp);
 
 extern JS_PUBLIC_API(bool)
 JS_GetPropertyDefault(JSContext *cx, JSObject *obj, const char *name, jsval def,
                       JS::MutableHandle<JS::Value> vp);
 
@@ -3062,51 +3032,16 @@ extern JS_PUBLIC_API(bool)
 JS_DeletePropertyById2(JSContext *cx, JSObject *obj, jsid id, bool *succeeded);
 
 extern JS_PUBLIC_API(bool)
 JS_DefineUCProperty(JSContext *cx, JSObject *obj,
                     const jschar *name, size_t namelen, jsval value,
                     JSPropertyOp getter, JSStrictPropertyOp setter,
                     unsigned attrs);
 
-/*
- * Determine the attributes (JSPROP_* flags) of a property on a given object.
- *
- * If the object does not have a property by that name, *foundp will be
- * false and the value of *attrsp is undefined.
- */
-extern JS_PUBLIC_API(bool)
-JS_GetUCPropertyAttributes(JSContext *cx, JSObject *obj,
-                           const jschar *name, size_t namelen,
-                           unsigned *attrsp, bool *foundp);
-
-/*
- * The same, but if the property is native, return its getter and setter via
- * *getterp and *setterp, respectively (and only if the out parameter pointer
- * is not null).
- */
-extern JS_PUBLIC_API(bool)
-JS_GetUCPropertyAttrsGetterAndSetter(JSContext *cx, JSObject *obj,
-                                     const jschar *name, size_t namelen,
-                                     unsigned *attrsp, bool *foundp,
-                                     JSPropertyOp *getterp,
-                                     JSStrictPropertyOp *setterp);
-
-/*
- * Set the attributes of a property on a given object.
- *
- * If the object does not have a property by that name, *foundp will be
- * false and nothing will be altered.
- */
-extern JS_PUBLIC_API(bool)
-JS_SetUCPropertyAttributes(JSContext *cx, JSObject *obj,
-                           const jschar *name, size_t namelen,
-                           unsigned attrs, bool *foundp);
-
-
 extern JS_PUBLIC_API(bool)
 JS_DefineUCPropertyWithTinyId(JSContext *cx, JSObject *obj,
                               const jschar *name, size_t namelen,
                               int8_t tinyid, jsval value,
                               JSPropertyOp getter, JSStrictPropertyOp setter,
                               unsigned attrs);
 
 extern JS_PUBLIC_API(bool)
--- a/js/src/jsinfer.h
+++ b/js/src/jsinfer.h
@@ -506,17 +506,17 @@ class TypeSet
      * Iterate through the objects in this set. getObjectCount overapproximates
      * in the hash case (see SET_ARRAY_SIZE in jsinferinlines.h), and getObject
      * may return NULL.
      */
     inline unsigned getObjectCount() const;
     inline TypeObjectKey *getObject(unsigned i) const;
     inline JSObject *getSingleObject(unsigned i) const;
     inline TypeObject *getTypeObject(unsigned i) const;
-    inline TypeObject *getTypeOrSingleObject(JSContext *cx, unsigned i) const;
+    inline bool getTypeOrSingleObject(JSContext *cx, unsigned i, TypeObject **obj) const;
 
     void setOwnProperty(bool configurable) {
         flags |= TYPE_FLAG_OWN_PROPERTY;
         if (configurable)
             flags |= TYPE_FLAG_CONFIGURED_PROPERTY;
     }
     void setDefinite(unsigned slot) {
         JS_ASSERT(slot <= (TYPE_FLAG_DEFINITE_MASK >> TYPE_FLAG_DEFINITE_SHIFT));
--- a/js/src/jsinferinlines.h
+++ b/js/src/jsinferinlines.h
@@ -1402,30 +1402,38 @@ TypeSet::getSingleObject(unsigned i) con
 
 inline TypeObject *
 TypeSet::getTypeObject(unsigned i) const
 {
     TypeObjectKey *key = getObject(i);
     return (key && !(uintptr_t(key) & 1)) ? (TypeObject *) key : NULL;
 }
 
-inline TypeObject *
-TypeSet::getTypeOrSingleObject(JSContext *cx, unsigned i) const
+inline bool
+TypeSet::getTypeOrSingleObject(JSContext *cx, unsigned i, TypeObject **result) const
 {
+    JS_ASSERT(result);
     JS_ASSERT(cx->compartment()->activeAnalysis);
+
+    *result = NULL;
+
     TypeObject *type = getTypeObject(i);
     if (!type) {
         JSObject *singleton = getSingleObject(i);
         if (!singleton)
-            return NULL;
+            return true;
+
         type = singleton->uninlinedGetType(cx);
-        if (!type)
+        if (!type) {
             cx->compartment()->types.setPendingNukeTypes(cx);
+            return false;
+        }
     }
-    return type;
+    *result = type;
+    return true;
 }
 
 /////////////////////////////////////////////////////////////////////
 // TypeCallsite
 /////////////////////////////////////////////////////////////////////
 
 inline
 TypeCallsite::TypeCallsite(JSContext *cx, JSScript *script, jsbytecode *pc,
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -4771,34 +4771,16 @@ baseops::GetAttributes(JSContext *cx, Ha
     if (!nobj->isNative())
         return JSObject::getGenericAttributes(cx, nobj, id, attrsp);
 
     *attrsp = GetShapeAttributes(shape);
     return true;
 }
 
 bool
-baseops::GetElementAttributes(JSContext *cx, HandleObject obj, uint32_t index, unsigned *attrsp)
-{
-    RootedObject nobj(cx);
-    RootedShape shape(cx);
-    if (!baseops::LookupElement(cx, obj, index, &nobj, &shape))
-        return false;
-    if (!shape) {
-        *attrsp = 0;
-        return true;
-    }
-    if (!nobj->isNative())
-        return JSObject::getElementAttributes(cx, nobj, index, attrsp);
-
-    *attrsp = GetShapeAttributes(shape);
-    return true;
-}
-
-bool
 baseops::SetAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp)
 {
     RootedObject nobj(cx);
     RootedShape shape(cx);
     if (!baseops::LookupProperty<CanGC>(cx, obj, id, &nobj, &shape))
         return false;
     if (!shape)
         return true;
@@ -4808,36 +4790,16 @@ baseops::SetAttributes(JSContext *cx, Ha
         shape = obj->nativeLookup(cx, id);
     }
     return nobj->isNative()
            ? JSObject::changePropertyAttributes(cx, nobj, shape, *attrsp)
            : JSObject::setGenericAttributes(cx, nobj, id, attrsp);
 }
 
 bool
-baseops::SetElementAttributes(JSContext *cx, HandleObject obj, uint32_t index, unsigned *attrsp)
-{
-    RootedObject nobj(cx);
-    RootedShape shape(cx);
-    if (!baseops::LookupElement(cx, obj, index, &nobj, &shape))
-        return false;
-    if (!shape)
-        return true;
-    if (nobj->isNative() && IsImplicitDenseElement(shape)) {
-        if (!JSObject::sparsifyDenseElement(cx, obj, index))
-            return false;
-        jsid id = INT_TO_JSID(index);
-        shape = obj->nativeLookup(cx, HandleId::fromMarkedLocation(&id)); // not a gcthing
-    }
-    return nobj->isNative()
-           ? JSObject::changePropertyAttributes(cx, nobj, shape, *attrsp)
-           : JSObject::setElementAttributes(cx, nobj, index, attrsp);
-}
-
-bool
 baseops::DeleteGeneric(JSContext *cx, HandleObject obj, HandleId id, bool *succeeded)
 {
     RootedObject proto(cx);
     RootedShape shape(cx);
     if (!baseops::LookupProperty<CanGC>(cx, obj, id, &proto, &shape))
         return false;
     if (!shape || proto != obj) {
         /*
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -139,22 +139,16 @@ TypeOf(JSContext *cx, HandleObject obj);
 
 extern bool
 GetAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp);
 
 extern bool
 SetAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp);
 
 extern bool
-GetElementAttributes(JSContext *cx, HandleObject obj, uint32_t index, unsigned *attrsp);
-
-extern bool
-SetElementAttributes(JSContext *cx, HandleObject obj, uint32_t index, unsigned *attrsp);
-
-extern bool
 DeleteProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, bool *succeeded);
 
 extern bool
 DeleteElement(JSContext *cx, HandleObject obj, uint32_t index, bool *succeeded);
 
 extern bool
 DeleteSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, bool *succeeded);
 
@@ -876,41 +870,18 @@ class JSObject : public js::ObjectImpl
 
     static bool getGenericAttributes(JSContext *cx, js::HandleObject obj,
                                      js::HandleId id, unsigned *attrsp)
     {
         js::GenericAttributesOp op = obj->getOps()->getGenericAttributes;
         return (op ? op : js::baseops::GetAttributes)(cx, obj, id, attrsp);
     }
 
-    static bool getPropertyAttributes(JSContext *cx, js::HandleObject obj,
-                                      js::PropertyName *name, unsigned *attrsp)
-    {
-        JS::RootedId id(cx, js::NameToId(name));
-        return getGenericAttributes(cx, obj, id, attrsp);
-    }
-
-    static inline bool getElementAttributes(JSContext *cx, js::HandleObject obj,
-                                            uint32_t index, unsigned *attrsp);
-
-    static bool getSpecialAttributes(JSContext *cx, js::HandleObject obj,
-                                     js::SpecialId sid, unsigned *attrsp)
-    {
-        JS::RootedId id(cx, SPECIALID_TO_JSID(sid));
-        return getGenericAttributes(cx, obj, id, attrsp);
-    }
-
     static inline bool setGenericAttributes(JSContext *cx, js::HandleObject obj,
                                             js::HandleId id, unsigned *attrsp);
-    static inline bool setPropertyAttributes(JSContext *cx, js::HandleObject obj,
-                                             js::PropertyName *name, unsigned *attrsp);
-    static inline bool setElementAttributes(JSContext *cx, js::HandleObject obj,
-                                            uint32_t index, unsigned *attrsp);
-    static inline bool setSpecialAttributes(JSContext *cx, js::HandleObject obj,
-                                            js::SpecialId sid, unsigned *attrsp);
 
     static inline bool deleteProperty(JSContext *cx, js::HandleObject obj,
                                       js::HandlePropertyName name,
                                       bool *succeeded);
     static inline bool deleteElement(JSContext *cx, js::HandleObject obj,
                                      uint32_t index, bool *succeeded);
     static inline bool deleteSpecial(JSContext *cx, js::HandleObject obj,
                                      js::HandleSpecialId sid, bool *succeeded);
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -27,40 +27,16 @@ JSObject::setGenericAttributes(JSContext
                                js::HandleId id, unsigned *attrsp)
 {
     js::types::MarkTypePropertyConfigured(cx, obj, id);
     js::GenericAttributesOp op = obj->getOps()->setGenericAttributes;
     return (op ? op : js::baseops::SetAttributes)(cx, obj, id, attrsp);
 }
 
 /* static */ inline bool
-JSObject::setPropertyAttributes(JSContext *cx, js::HandleObject obj,
-                                js::PropertyName *name, unsigned *attrsp)
-{
-    JS::RootedId id(cx, js::NameToId(name));
-    return setGenericAttributes(cx, obj, id, attrsp);
-}
-
-/* static */ inline bool
-JSObject::setElementAttributes(JSContext *cx, js::HandleObject obj,
-                               uint32_t index, unsigned *attrsp)
-{
-    js::ElementAttributesOp op = obj->getOps()->setElementAttributes;
-    return (op ? op : js::baseops::SetElementAttributes)(cx, obj, index, attrsp);
-}
-
-/* static */ inline bool
-JSObject::setSpecialAttributes(JSContext *cx, js::HandleObject obj,
-                               js::SpecialId sid, unsigned *attrsp)
-{
-    JS::RootedId id(cx, SPECIALID_TO_JSID(sid));
-    return setGenericAttributes(cx, obj, id, attrsp);
-}
-
-/* static */ inline bool
 JSObject::changePropertyAttributes(JSContext *cx, js::HandleObject obj,
                                    js::HandleShape shape, unsigned attrs)
 {
     return !!changeProperty(cx, obj, shape, attrs, 0, shape->getter(), shape->setter());
 }
 
 /* static */ inline bool
 JSObject::deleteProperty(JSContext *cx, js::HandleObject obj, js::HandlePropertyName name,
@@ -742,26 +718,16 @@ JSObject::getElementIfPresent(JSContext 
         *present = false;
         return true;
     }
 
     *present = true;
     return getGeneric(cx, obj, receiver, id, vp);
 }
 
-/* static */ inline bool
-JSObject::getElementAttributes(JSContext *cx, js::HandleObject obj,
-                               uint32_t index, unsigned *attrsp)
-{
-    JS::RootedId id(cx);
-    if (!js::IndexToId(cx, index, &id))
-        return false;
-    return getGenericAttributes(cx, obj, id, attrsp);
-}
-
 inline js::GlobalObject &
 JSObject::global() const
 {
 #ifdef DEBUG
     JSObject *obj = const_cast<JSObject *>(this);
     while (JSObject *parent = obj->getParent())
         obj = parent;
 #endif
--- a/js/src/jsproxy.cpp
+++ b/js/src/jsproxy.cpp
@@ -2888,73 +2888,27 @@ proxy_GetGenericAttributes(JSContext *cx
     Rooted<PropertyDescriptor> desc(cx);
     if (!Proxy::getOwnPropertyDescriptor(cx, obj, id, &desc, 0))
         return false;
     *attrsp = desc.attributes();
     return true;
 }
 
 static bool
-proxy_GetPropertyAttributes(JSContext *cx, HandleObject obj, HandlePropertyName name, unsigned *attrsp)
-{
-    Rooted<jsid> id(cx, NameToId(name));
-    return proxy_GetGenericAttributes(cx, obj, id, attrsp);
-}
-
-static bool
-proxy_GetElementAttributes(JSContext *cx, HandleObject obj, uint32_t index, unsigned *attrsp)
-{
-    RootedId id(cx);
-    if (!IndexToId(cx, index, &id))
-        return false;
-    return proxy_GetGenericAttributes(cx, obj, id, attrsp);
-}
-
-static bool
-proxy_GetSpecialAttributes(JSContext *cx, HandleObject obj, HandleSpecialId sid, unsigned *attrsp)
-{
-    Rooted<jsid> id(cx, SPECIALID_TO_JSID(sid));
-    return proxy_GetGenericAttributes(cx, obj, id, attrsp);
-}
-
-static bool
 proxy_SetGenericAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp)
 {
     /* Lookup the current property descriptor so we have setter/getter/value. */
     Rooted<PropertyDescriptor> desc(cx);
     if (!Proxy::getOwnPropertyDescriptor(cx, obj, id, &desc, JSRESOLVE_ASSIGNING))
         return false;
     desc.setAttributes(*attrsp & (~JSPROP_SHORTID));
     return Proxy::defineProperty(cx, obj, id, &desc);
 }
 
 static bool
-proxy_SetPropertyAttributes(JSContext *cx, HandleObject obj, HandlePropertyName name, unsigned *attrsp)
-{
-    Rooted<jsid> id(cx, NameToId(name));
-    return proxy_SetGenericAttributes(cx, obj, id, attrsp);
-}
-
-static bool
-proxy_SetElementAttributes(JSContext *cx, HandleObject obj, uint32_t index, unsigned *attrsp)
-{
-    RootedId id(cx);
-    if (!IndexToId(cx, index, &id))
-        return false;
-    return proxy_SetGenericAttributes(cx, obj, id, attrsp);
-}
-
-static bool
-proxy_SetSpecialAttributes(JSContext *cx, HandleObject obj, HandleSpecialId sid, unsigned *attrsp)
-{
-    Rooted<jsid> id(cx, SPECIALID_TO_JSID(sid));
-    return proxy_SetGenericAttributes(cx, obj, id, attrsp);
-}
-
-static bool
 proxy_DeleteGeneric(JSContext *cx, HandleObject obj, HandleId id, bool *succeeded)
 {
     bool deleted;
     if (!Proxy::delete_(cx, obj, id, &deleted))
         return false;
     *succeeded = deleted;
     return js_SuppressDeletedProperty(cx, obj, id);
 }
@@ -3098,23 +3052,17 @@ Class js::ObjectProxyObject::class_ = {
         proxy_GetElement,
         proxy_GetElementIfPresent,
         proxy_GetSpecial,
         proxy_SetGeneric,
         proxy_SetProperty,
         proxy_SetElement,
         proxy_SetSpecial,
         proxy_GetGenericAttributes,
-        proxy_GetPropertyAttributes,
-        proxy_GetElementAttributes,
-        proxy_GetSpecialAttributes,
         proxy_SetGenericAttributes,
-        proxy_SetPropertyAttributes,
-        proxy_SetElementAttributes,
-        proxy_SetSpecialAttributes,
         proxy_DeleteProperty,
         proxy_DeleteElement,
         proxy_DeleteSpecial,
         NULL,                /* enumerate       */
         NULL,                /* thisObject      */
     }
 };
 
@@ -3157,23 +3105,17 @@ Class js::OuterWindowProxyObject::class_
         proxy_GetElement,
         proxy_GetElementIfPresent,
         proxy_GetSpecial,
         proxy_SetGeneric,
         proxy_SetProperty,
         proxy_SetElement,
         proxy_SetSpecial,
         proxy_GetGenericAttributes,
-        proxy_GetPropertyAttributes,
-        proxy_GetElementAttributes,
-        proxy_GetSpecialAttributes,
         proxy_SetGenericAttributes,
-        proxy_SetPropertyAttributes,
-        proxy_SetElementAttributes,
-        proxy_SetSpecialAttributes,
         proxy_DeleteProperty,
         proxy_DeleteElement,
         proxy_DeleteSpecial,
         NULL,                /* enumerate       */
         NULL,                /* thisObject      */
     }
 };
 
@@ -3228,23 +3170,17 @@ Class js::FunctionProxyObject::class_ = 
         proxy_GetElement,
         proxy_GetElementIfPresent,
         proxy_GetSpecial,
         proxy_SetGeneric,
         proxy_SetProperty,
         proxy_SetElement,
         proxy_SetSpecial,
         proxy_GetGenericAttributes,
-        proxy_GetPropertyAttributes,
-        proxy_GetElementAttributes,
-        proxy_GetSpecialAttributes,
         proxy_SetGenericAttributes,
-        proxy_SetPropertyAttributes,
-        proxy_SetElementAttributes,
-        proxy_SetSpecialAttributes,
         proxy_DeleteProperty,
         proxy_DeleteElement,
         proxy_DeleteSpecial,
         NULL,                /* enumerate       */
         NULL,                /* thisObject      */
     }
 };
 
--- a/js/src/vm/Interpreter-inl.h
+++ b/js/src/vm/Interpreter-inl.h
@@ -270,37 +270,37 @@ DefVarOrConstOperation(JSContext *cx, Ha
 
     /* Steps 8c, 8d. */
     if (!prop || (obj2 != varobj && varobj->is<GlobalObject>())) {
         RootedValue value(cx, UndefinedValue());
         if (!JSObject::defineProperty(cx, varobj, dn, value, JS_PropertyStub,
                                       JS_StrictPropertyStub, attrs)) {
             return false;
         }
-    } else {
+    } else if (attrs & JSPROP_READONLY) {
         /*
          * Extension: ordinarily we'd be done here -- but for |const|.  If we
          * see a redeclaration that's |const|, we consider it a conflict.
          */
         unsigned oldAttrs;
-        if (!JSObject::getPropertyAttributes(cx, varobj, dn, &oldAttrs))
+        RootedId id(cx, NameToId(dn));
+        if (!JSObject::getGenericAttributes(cx, varobj, id, &oldAttrs))
             return false;
-        if (attrs & JSPROP_READONLY) {
-            JSAutoByteString bytes;
-            if (AtomToPrintableString(cx, dn, &bytes)) {
-                JS_ALWAYS_FALSE(JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR,
-                                                             js_GetErrorMessage,
-                                                             NULL, JSMSG_REDECLARED_VAR,
-                                                             (oldAttrs & JSPROP_READONLY)
-                                                             ? "const"
-                                                             : "var",
-                                                             bytes.ptr()));
-            }
-            return false;
+
+        JSAutoByteString bytes;
+        if (AtomToPrintableString(cx, dn, &bytes)) {
+            JS_ALWAYS_FALSE(JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR,
+                                                         js_GetErrorMessage,
+                                                         NULL, JSMSG_REDECLARED_VAR,
+                                                         (oldAttrs & JSPROP_READONLY)
+                                                         ? "const"
+                                                         : "var",
+                                                         bytes.ptr()));
         }
+        return false;
     }
 
     return true;
 }
 
 static JS_ALWAYS_INLINE bool
 NegOperation(JSContext *cx, HandleScript script, jsbytecode *pc, HandleValue val,
              MutableHandleValue res)
--- a/js/src/vm/ScopeObject.cpp
+++ b/js/src/vm/ScopeObject.cpp
@@ -507,65 +507,23 @@ with_SetSpecial(JSContext *cx, HandleObj
 static bool
 with_GetGenericAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp)
 {
     RootedObject actual(cx, &obj->as<WithObject>().object());
     return JSObject::getGenericAttributes(cx, actual, id, attrsp);
 }
 
 static bool
-with_GetPropertyAttributes(JSContext *cx, HandleObject obj, HandlePropertyName name, unsigned *attrsp)
-{
-    RootedObject actual(cx, &obj->as<WithObject>().object());
-    return JSObject::getPropertyAttributes(cx, actual, name, attrsp);
-}
-
-static bool
-with_GetElementAttributes(JSContext *cx, HandleObject obj, uint32_t index, unsigned *attrsp)
-{
-    RootedObject actual(cx, &obj->as<WithObject>().object());
-    return JSObject::getElementAttributes(cx, actual, index, attrsp);
-}
-
-static bool
-with_GetSpecialAttributes(JSContext *cx, HandleObject obj, HandleSpecialId sid, unsigned *attrsp)
-{
-    RootedObject actual(cx, &obj->as<WithObject>().object());
-    return JSObject::getSpecialAttributes(cx, actual, sid, attrsp);
-}
-
-static bool
 with_SetGenericAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp)
 {
     RootedObject actual(cx, &obj->as<WithObject>().object());
     return JSObject::setGenericAttributes(cx, actual, id, attrsp);
 }
 
 static bool
-with_SetPropertyAttributes(JSContext *cx, HandleObject obj, HandlePropertyName name, unsigned *attrsp)
-{
-    RootedObject actual(cx, &obj->as<WithObject>().object());
-    return JSObject::setPropertyAttributes(cx, actual, name, attrsp);
-}
-
-static bool
-with_SetElementAttributes(JSContext *cx, HandleObject obj, uint32_t index, unsigned *attrsp)
-{
-    RootedObject actual(cx, &obj->as<WithObject>().object());
-    return JSObject::setElementAttributes(cx, actual, index, attrsp);
-}
-
-static bool
-with_SetSpecialAttributes(JSContext *cx, HandleObject obj, HandleSpecialId sid, unsigned *attrsp)
-{
-    RootedObject actual(cx, &obj->as<WithObject>().object());
-    return JSObject::setSpecialAttributes(cx, actual, sid, attrsp);
-}
-
-static bool
 with_DeleteProperty(JSContext *cx, HandleObject obj, HandlePropertyName name,
                     bool *succeeded)
 {
     RootedObject actual(cx, &obj->as<WithObject>().object());
     return JSObject::deleteProperty(cx, actual, name, succeeded);
 }
 
 static bool
@@ -630,23 +588,17 @@ Class WithObject::class_ = {
         with_GetElement,
         NULL,             /* getElementIfPresent */
         with_GetSpecial,
         with_SetGeneric,
         with_SetProperty,
         with_SetElement,
         with_SetSpecial,
         with_GetGenericAttributes,
-        with_GetPropertyAttributes,
-        with_GetElementAttributes,
-        with_GetSpecialAttributes,
         with_SetGenericAttributes,
-        with_SetPropertyAttributes,
-        with_SetElementAttributes,
-        with_SetSpecialAttributes,
         with_DeleteProperty,
         with_DeleteElement,
         with_DeleteSpecial,
         with_Enumerate,
         with_ThisObject,
     }
 };
 
@@ -1403,17 +1355,17 @@ class DebugScopeProxy : public BaseProxy
             desc.setAttributes(JSPROP_READONLY | JSPROP_ENUMERATE | JSPROP_PERMANENT);
             desc.value().set(v);
             desc.setShortId(0);
             desc.setGetter(NULL);
             desc.setSetter(NULL);
             return true;
         }
 
-        return JS_GetPropertyDescriptorById(cx, scope, id, 0, desc);
+        return JS_GetOwnPropertyDescriptorById(cx, scope, id, flags, desc);
     }
 
     bool get(JSContext *cx, HandleObject proxy, HandleObject receiver,  HandleId id,
              MutableHandleValue vp) MOZ_OVERRIDE
     {
         Rooted<DebugScopeObject*> debugScope(cx, &proxy->as<DebugScopeObject>());
         Rooted<ScopeObject*> scope(cx, &proxy->as<DebugScopeObject>().scope());
 
--- a/js/src/vm/TypedArrayObject.cpp
+++ b/js/src/vm/TypedArrayObject.cpp
@@ -1016,78 +1016,26 @@ ArrayBufferObject::obj_getGenericAttribu
 {
     RootedObject delegate(cx, ArrayBufferDelegate(cx, obj));
     if (!delegate)
         return false;
     return baseops::GetAttributes(cx, delegate, id, attrsp);
 }
 
 bool
-ArrayBufferObject::obj_getPropertyAttributes(JSContext *cx, HandleObject obj,
-                                             HandlePropertyName name, unsigned *attrsp)
-{
-    Rooted<jsid> id(cx, NameToId(name));
-    return obj_getGenericAttributes(cx, obj, id, attrsp);
-}
-
-bool
-ArrayBufferObject::obj_getElementAttributes(JSContext *cx, HandleObject obj,
-                                            uint32_t index, unsigned *attrsp)
-{
-    RootedObject delegate(cx, ArrayBufferDelegate(cx, obj));
-    if (!delegate)
-        return false;
-    return baseops::GetElementAttributes(cx, delegate, index, attrsp);
-}
-
-bool
-ArrayBufferObject::obj_getSpecialAttributes(JSContext *cx, HandleObject obj,
-                                            HandleSpecialId sid, unsigned *attrsp)
-{
-    Rooted<jsid> id(cx, SPECIALID_TO_JSID(sid));
-    return obj_getGenericAttributes(cx, obj, id, attrsp);
-}
-
-bool
 ArrayBufferObject::obj_setGenericAttributes(JSContext *cx, HandleObject obj,
                                             HandleId id, unsigned *attrsp)
 {
     RootedObject delegate(cx, ArrayBufferDelegate(cx, obj));
     if (!delegate)
         return false;
     return baseops::SetAttributes(cx, delegate, id, attrsp);
 }
 
 bool
-ArrayBufferObject::obj_setPropertyAttributes(JSContext *cx, HandleObject obj,
-                                             HandlePropertyName name, unsigned *attrsp)
-{
-    Rooted<jsid> id(cx, NameToId(name));
-    return obj_setGenericAttributes(cx, obj, id, attrsp);
-}
-
-bool
-ArrayBufferObject::obj_setElementAttributes(JSContext *cx, HandleObject obj,
-                                            uint32_t index, unsigned *attrsp)
-{
-    RootedObject delegate(cx, ArrayBufferDelegate(cx, obj));
-    if (!delegate)
-        return false;
-    return baseops::SetElementAttributes(cx, delegate, index, attrsp);
-}
-
-bool
-ArrayBufferObject::obj_setSpecialAttributes(JSContext *cx, HandleObject obj,
-                                            HandleSpecialId sid, unsigned *attrsp)
-{
-    Rooted<jsid> id(cx, SPECIALID_TO_JSID(sid));
-    return obj_setGenericAttributes(cx, obj, id, attrsp);
-}
-
-bool
 ArrayBufferObject::obj_deleteProperty(JSContext *cx, HandleObject obj, HandlePropertyName name,
                                       bool *succeeded)
 {
     RootedObject delegate(cx, ArrayBufferDelegate(cx, obj));
     if (!delegate)
         return false;
     return baseops::DeleteProperty(cx, delegate, name, succeeded);
 }
@@ -1227,71 +1175,23 @@ bool
 TypedArrayObject::obj_getGenericAttributes(JSContext *cx, HandleObject obj, HandleId id,
                                            unsigned *attrsp)
 {
     *attrsp = JSPROP_PERMANENT | JSPROP_ENUMERATE;
     return true;
 }
 
 bool
-TypedArrayObject::obj_getPropertyAttributes(JSContext *cx, HandleObject obj,
-                                            HandlePropertyName name, unsigned *attrsp)
-{
-    *attrsp = JSPROP_PERMANENT | JSPROP_ENUMERATE;
-    return true;
-}
-
-bool
-TypedArrayObject::obj_getElementAttributes(JSContext *cx, HandleObject obj, uint32_t index,
-                                           unsigned *attrsp)
-{
-    *attrsp = JSPROP_PERMANENT | JSPROP_ENUMERATE;
-    return true;
-}
-
-bool
-TypedArrayObject::obj_getSpecialAttributes(JSContext *cx, HandleObject obj, HandleSpecialId sid,
-                                           unsigned *attrsp)
-{
-    Rooted<jsid> id(cx, SPECIALID_TO_JSID(sid));
-    return obj_getGenericAttributes(cx, obj, id, attrsp);
-}
-
-bool
 TypedArrayObject::obj_setGenericAttributes(JSContext *cx, HandleObject obj, HandleId id,
                                            unsigned *attrsp)
 {
     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_SET_ARRAY_ATTRS);
     return false;
 }
 
-bool
-TypedArrayObject::obj_setPropertyAttributes(JSContext *cx, HandleObject obj,
-                                            HandlePropertyName name, unsigned *attrsp)
-{
-    JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_SET_ARRAY_ATTRS);
-    return false;
-}
-
-bool
-TypedArrayObject::obj_setElementAttributes(JSContext *cx, HandleObject obj, uint32_t index,
-                                           unsigned *attrsp)
-{
-    JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_SET_ARRAY_ATTRS);
-    return false;
-}
-
-bool
-TypedArrayObject::obj_setSpecialAttributes(JSContext *cx, HandleObject obj, HandleSpecialId sid,
-                                           unsigned *attrsp)
-{
-    JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_SET_ARRAY_ATTRS);
-    return false;
-}
-
 /* static */ int
 TypedArrayObject::lengthOffset()
 {
     return JSObject::getFixedSlotOffset(LENGTH_SLOT);
 }
 
 /* static */ int
 TypedArrayObject::dataOffset()
@@ -3489,23 +3389,17 @@ Class ArrayBufferObject::class_ = {
         ArrayBufferObject::obj_getElement,
         ArrayBufferObject::obj_getElementIfPresent,
         ArrayBufferObject::obj_getSpecial,
         ArrayBufferObject::obj_setGeneric,
         ArrayBufferObject::obj_setProperty,
         ArrayBufferObject::obj_setElement,
         ArrayBufferObject::obj_setSpecial,
         ArrayBufferObject::obj_getGenericAttributes,
-        ArrayBufferObject::obj_getPropertyAttributes,
-        ArrayBufferObject::obj_getElementAttributes,
-        ArrayBufferObject::obj_getSpecialAttributes,
         ArrayBufferObject::obj_setGenericAttributes,
-        ArrayBufferObject::obj_setPropertyAttributes,
-        ArrayBufferObject::obj_setElementAttributes,
-        ArrayBufferObject::obj_setSpecialAttributes,
         ArrayBufferObject::obj_deleteProperty,
         ArrayBufferObject::obj_deleteElement,
         ArrayBufferObject::obj_deleteSpecial,
         ArrayBufferObject::obj_enumerate,
         NULL,       /* thisObject      */
     }
 };
 
@@ -3657,23 +3551,17 @@ IMPL_TYPED_ARRAY_COMBINED_UNWRAPPERS(Flo
         _typedArray##Object::obj_getElement,                                   \
         _typedArray##Object::obj_getElementIfPresent,                          \
         _typedArray##Object::obj_getSpecial,                                   \
         _typedArray##Object::obj_setGeneric,                                   \
         _typedArray##Object::obj_setProperty,                                  \
         _typedArray##Object::obj_setElement,                                   \
         _typedArray##Object::obj_setSpecial,                                   \
         _typedArray##Object::obj_getGenericAttributes,                         \
-        _typedArray##Object::obj_getPropertyAttributes,                        \
-        _typedArray##Object::obj_getElementAttributes,                         \
-        _typedArray##Object::obj_getSpecialAttributes,                         \
         _typedArray##Object::obj_setGenericAttributes,                         \
-        _typedArray##Object::obj_setPropertyAttributes,                        \
-        _typedArray##Object::obj_setElementAttributes,                         \
-        _typedArray##Object::obj_setSpecialAttributes,                         \
         _typedArray##Object::obj_deleteProperty,                               \
         _typedArray##Object::obj_deleteElement,                                \
         _typedArray##Object::obj_deleteSpecial,                                \
         _typedArray##Object::obj_enumerate,                                    \
         NULL,                /* thisObject  */                                 \
     }                                                                          \
 }
 
--- a/js/src/vm/TypedArrayObject.h
+++ b/js/src/vm/TypedArrayObject.h
@@ -119,31 +119,18 @@ class ArrayBufferObject : public JSObjec
                                 MutableHandleValue vp, bool strict);
     static bool obj_setElement(JSContext *cx, HandleObject obj, uint32_t index,
                                MutableHandleValue vp, bool strict);
     static bool obj_setSpecial(JSContext *cx, HandleObject obj,
                                HandleSpecialId sid, MutableHandleValue vp, bool strict);
 
     static bool obj_getGenericAttributes(JSContext *cx, HandleObject obj,
                                          HandleId id, unsigned *attrsp);
-    static bool obj_getPropertyAttributes(JSContext *cx, HandleObject obj,
-                                          HandlePropertyName name, unsigned *attrsp);
-    static bool obj_getElementAttributes(JSContext *cx, HandleObject obj,
-                                         uint32_t index, unsigned *attrsp);
-    static bool obj_getSpecialAttributes(JSContext *cx, HandleObject obj,
-                                         HandleSpecialId sid, unsigned *attrsp);
-
     static bool obj_setGenericAttributes(JSContext *cx, HandleObject obj,
                                          HandleId id, unsigned *attrsp);
-    static bool obj_setPropertyAttributes(JSContext *cx, HandleObject obj,
-                                          HandlePropertyName name, unsigned *attrsp);
-    static bool obj_setElementAttributes(JSContext *cx, HandleObject obj,
-                                         uint32_t index, unsigned *attrsp);
-    static bool obj_setSpecialAttributes(JSContext *cx, HandleObject obj,
-                                         HandleSpecialId sid, unsigned *attrsp);
 
     static bool obj_deleteProperty(JSContext *cx, HandleObject obj, HandlePropertyName name,
                                    bool *succeeded);
     static bool obj_deleteElement(JSContext *cx, HandleObject obj, uint32_t index,
                                   bool *succeeded);
     static bool obj_deleteSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid,
                                   bool *succeeded);
 
@@ -290,31 +277,18 @@ class TypedArrayObject : public ArrayBuf
                                    MutableHandleObject objp, MutableHandleShape propp);
     static bool obj_lookupElement(JSContext *cx, HandleObject obj, uint32_t index,
                                   MutableHandleObject objp, MutableHandleShape propp);
     static bool obj_lookupSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid,
                                   MutableHandleObject objp, MutableHandleShape propp);
 
     static bool obj_getGenericAttributes(JSContext *cx, HandleObject obj,
                                          HandleId id, unsigned *attrsp);
-    static bool obj_getPropertyAttributes(JSContext *cx, HandleObject obj,
-                                          HandlePropertyName name, unsigned *attrsp);
-    static bool obj_getElementAttributes(JSContext *cx, HandleObject obj,
-                                         uint32_t index, unsigned *attrsp);
-    static bool obj_getSpecialAttributes(JSContext *cx, HandleObject obj,
-                                         HandleSpecialId sid, unsigned *attrsp);
-
     static bool obj_setGenericAttributes(JSContext *cx, HandleObject obj,
                                          HandleId id, unsigned *attrsp);
-    static bool obj_setPropertyAttributes(JSContext *cx, HandleObject obj,
-                                          HandlePropertyName name, unsigned *attrsp);
-    static bool obj_setElementAttributes(JSContext *cx, HandleObject obj,
-                                         uint32_t index, unsigned *attrsp);
-    static bool obj_setSpecialAttributes(JSContext *cx, HandleObject obj,
-                                         HandleSpecialId sid, unsigned *attrsp);
 
     static Value bufferValue(TypedArrayObject *tarr) {
         return tarr->getFixedSlot(BUFFER_SLOT);
     }
     static Value byteOffsetValue(TypedArrayObject *tarr) {
         return tarr->getFixedSlot(BYTEOFFSET_SLOT);
     }
     static Value byteLengthValue(TypedArrayObject *tarr) {
--- a/js/xpconnect/idl/nsIXPCScriptable.idl
+++ b/js/xpconnect/idl/nsIXPCScriptable.idl
@@ -1,16 +1,17 @@
 /* -*- Mode: C; tab-width: 8; 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"
 #include "nsIXPConnect.idl"
+#include "nsIClassInfo.idl"
 
 %{C++
 #ifdef XP_WIN
 #undef GetClassName
 #endif
 %}
 
 /**
--- a/js/xpconnect/idl/nsIXPConnect.idl
+++ b/js/xpconnect/idl/nsIXPConnect.idl
@@ -2,36 +2,25 @@
  *
  * 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/. */
 
 /* The core XPConnect public interfaces. */
 
 #include "nsISupports.idl"
-#include "nsIClassInfo.idl"
-#include "xpccomponents.idl"
-#include "xpcjsid.idl"
-#include "xpcexception.idl"
-#include "nsIInterfaceInfo.idl"
-#include "nsIInterfaceInfoManager.idl"
-#include "nsIExceptionService.idl"
-#include "nsIVariant.idl"
-#include "nsIObjectOutputStream.idl"
-#include "nsIObjectInputStream.idl"
 
 %{ C++
 #include "jspubtd.h"
 #include "js/TypeDecls.h"
-#include "xptinfo.h"
-#include "nsAXPCNativeCallContext.h"
 
 struct JSFreeOp;
 
 class nsWrapperCache;
+class nsAXPCNativeCallContext;
 %}
 
 /***************************************************************************/
 
 // NB: jsval and jsid are declared in nsrootidl.idl
 
 [ptr] native JSContextPtr(JSContext);
 [ptr] native JSClassPtr(JSClass);
@@ -53,16 +42,21 @@ class nsWrapperCache;
 
 // forward declarations...
 interface nsIXPCScriptable;
 interface nsIXPConnect;
 interface nsIXPConnectWrappedNative;
 interface nsIInterfaceInfo;
 interface nsIXPCSecurityManager;
 interface nsIPrincipal;
+interface nsIClassInfo;
+interface nsIVariant;
+interface nsIStackFrame;
+interface nsIObjectInputStream;
+interface nsIObjectOutputStream;
 
 /***************************************************************************/
 [uuid(909e8641-7c54-4dff-9b94-ba631f057b33)]
 interface nsIXPConnectJSObjectHolder : nsISupports
 {
     [notxpcom, nostdcall] JSObjectPtr GetJSObject();
 };
 
--- a/js/xpconnect/shell/xpcshell.cpp
+++ b/js/xpconnect/shell/xpcshell.cpp
@@ -1671,16 +1671,21 @@ main(int argc, char **argv, char **envp)
         ProcessArgsForCompartment(cx, argv, argc);
 
         nsCOMPtr<nsIXPConnect> xpc = do_GetService(nsIXPConnect::GetCID());
         if (!xpc) {
             printf("failed to get nsXPConnect service!\n");
             return 1;
         }
 
+        // Force the SafeJSContext to be created. This is a workaround for our
+        // implicit dependency on keeping at least one JSContext alive until the
+        // end of shutdown. This can go away when we get bug 905926 landed.
+        xpc->GetSafeJSContext();
+
         nsCOMPtr<nsIPrincipal> systemprincipal;
         // Fetch the system principal and store it away in a global, to use for
         // script compilation in Load() and ProcessFile() (including interactive
         // eval loop)
         {
 
             nsCOMPtr<nsIScriptSecurityManager> securityManager =
                 do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
--- a/js/xpconnect/src/XPCConvert.cpp
+++ b/js/xpconnect/src/XPCConvert.cpp
@@ -1165,24 +1165,23 @@ XPCConvert::JSValToXPCException(MutableH
                 JSString* str;
                 if (nullptr != (str = JS_ValueToString(cx, s)))
                     message.encodeLatin1(cx, str);
                 return JSErrorToXPCException(message.ptr(), ifaceName,
                                              methodName, report, exceptn);
             }
 
 
-            unsigned ignored;
             bool found;
 
             // heuristic to see if it might be usable as an xpcexception
-            if (!JS_GetPropertyAttributes(cx, obj, "message", &ignored, &found))
-               return NS_ERROR_FAILURE;
+            if (!JS_HasProperty(cx, obj, "message", &found))
+                return NS_ERROR_FAILURE;
 
-            if (found && !JS_GetPropertyAttributes(cx, obj, "result", &ignored, &found))
+            if (found && !JS_HasProperty(cx, obj, "result", &found))
                 return NS_ERROR_FAILURE;
 
             if (found) {
                 // lets try to build a wrapper around the JSObject
                 nsXPCWrappedJS* jswrapper;
                 nsresult rv =
                     nsXPCWrappedJS::GetNewOrUsed(obj, NS_GET_IID(nsIException),
                                                  nullptr, &jswrapper);
--- a/js/xpconnect/src/XPCJSContextStack.cpp
+++ b/js/xpconnect/src/XPCJSContextStack.cpp
@@ -120,17 +120,17 @@ SafeFinalize(JSFreeOp *fop, JSObject* ob
 {
     SandboxPrivate* sop =
         static_cast<SandboxPrivate*>(xpc_GetJSPrivate(obj));
     sop->ForgetGlobalObject();
     NS_IF_RELEASE(sop);
     DestroyProtoAndIfaceCache(obj);
 }
 
-static JSClass global_class = {
+JSClass xpc::SafeJSContextGlobalClass = {
     "global_for_XPCJSContextStack_SafeJSContext",
     XPCONNECT_GLOBAL_FLAGS,
     JS_PropertyStub, JS_DeletePropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
     JS_EnumerateStub, SafeGlobalResolve, JS_ConvertStub, SafeFinalize,
     NULL, NULL, NULL, NULL, TraceXPCGlobal
 };
 
 JSContext*
@@ -156,17 +156,17 @@ XPCJSContextStack::GetSafeJSContext()
         MOZ_CRASH();
     JSAutoRequest req(mSafeJSContext);
 
     JS::RootedObject glob(mSafeJSContext);
     JS_SetErrorReporter(mSafeJSContext, xpc::SystemErrorReporter);
 
     JS::CompartmentOptions options;
     options.setZone(JS::SystemZone);
-    glob = xpc::CreateGlobalObject(mSafeJSContext, &global_class, principal, options);
+    glob = xpc::CreateGlobalObject(mSafeJSContext, &SafeJSContextGlobalClass, principal, options);
     if (!glob)
         MOZ_CRASH();
 
     // Make sure the context is associated with a proper compartment
     // and not the default compartment.
     js::SetDefaultObjectForContext(mSafeJSContext, glob);
 
     // Note: make sure to set the private before calling
--- a/js/xpconnect/src/XPCWrappedNativeJSOps.cpp
+++ b/js/xpconnect/src/XPCWrappedNativeJSOps.cpp
@@ -730,23 +730,17 @@ XPCWrappedNativeJSClass XPC_WN_NoHelper_
         nullptr, // getElement
         nullptr, // getElementIfPresent
         nullptr, // getSpecial
         nullptr, // setGeneric
         nullptr, // setProperty
         nullptr, // setElement
         nullptr, // setSpecial
         nullptr, // getGenericAttributes
-        nullptr, // getAttributes
-        nullptr, // getElementAttributes
-        nullptr, // getSpecialAttributes
         nullptr, // setGenericAttributes
-        nullptr, // setAttributes
-        nullptr, // setElementAttributes
-        nullptr, // setSpecialAttributes
         nullptr, // deleteProperty
         nullptr, // deleteElement
         nullptr, // deleteSpecial
         XPC_WN_JSOp_Enumerate,
         XPC_WN_JSOp_ThisObject,
     }
   },
   0 // interfacesBitmap
--- a/js/xpconnect/src/XPCWrappedNativeScope.cpp
+++ b/js/xpconnect/src/XPCWrappedNativeScope.cpp
@@ -13,16 +13,17 @@
 #include "nsPrincipal.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/Preferences.h"
 
 #include "mozilla/dom/BindingUtils.h"
 
 using namespace mozilla;
 using namespace xpc;
+using namespace JS;
 
 /***************************************************************************/
 
 #ifdef XPC_TRACK_SCOPE_STATS
 static int DEBUG_TotalScopeCount;
 static int DEBUG_TotalLiveScopeCount;
 static int DEBUG_TotalMaxScopeCount;
 static int DEBUG_TotalScopeTraversalCount;
@@ -92,27 +93,34 @@ XPCWrappedNativeScope::GetNewOrUsed(JSCo
     XPCWrappedNativeScope* scope = GetObjectScope(aGlobal);
     if (!scope) {
         scope = new XPCWrappedNativeScope(cx, aGlobal);
     }
     return scope;
 }
 
 static bool
-RemoteXULForbidsXBLScope(nsIPrincipal *aPrincipal)
+RemoteXULForbidsXBLScope(nsIPrincipal *aPrincipal, HandleObject aGlobal)
 {
-  // We end up getting called during SSM bootstrapping to create the
-  // SafeJSContext. In that case, nsContentUtils isn't ready for us.
-  //
-  // Also check for random JSD scopes that don't have a principal.
-  if (!nsContentUtils::IsInitialized() || !aPrincipal)
+  // Check for random JSD scopes that don't have a principal.
+  if (!aPrincipal)
+      return false;
+
+  // The SafeJSContext is lazily created, and tends to be created at really
+  // weird times, at least for xpcshell (often very early in startup or late
+  // in shutdown). Its scope isn't system principal, so if we proceeded we'd
+  // end up calling into AllowXULXBLForPrincipal, which depends on all kinds
+  // of persistent storage and permission machinery that may or not be running.
+  // We know the answer to the question here, so just short-circuit.
+  if (JS_GetClass(aGlobal) == &SafeJSContextGlobalClass)
       return false;
 
   // AllowXULXBLForPrincipal will return true for system principal, but we
   // don't want that here.
+  MOZ_ASSERT(nsContentUtils::IsInitialized());
   if (nsContentUtils::IsSystemPrincipal(aPrincipal))
       return false;
 
   // If this domain isn't whitelisted, we're done.
   if (!nsContentUtils::AllowXULXBLForPrincipal(aPrincipal))
       return false;
 
   // Check the pref to determine how we should behave.
@@ -156,17 +164,17 @@ XPCWrappedNativeScope::XPCWrappedNativeS
     // Attach ourselves to the compartment private.
     CompartmentPrivate *priv = EnsureCompartmentPrivate(aGlobal);
     priv->scope = this;
 
     // Determine whether we would allow an XBL scope in this situation.
     // In addition to being pref-controlled, we also disable XBL scopes for
     // remote XUL domains, _except_ if we have an additional pref override set.
     nsIPrincipal *principal = GetPrincipal();
-    mAllowXBLScope = !RemoteXULForbidsXBLScope(principal);
+    mAllowXBLScope = !RemoteXULForbidsXBLScope(principal, aGlobal);
 
     // Determine whether to use an XBL scope.
     mUseXBLScope = mAllowXBLScope;
     if (mUseXBLScope) {
       js::Class *clasp = js::GetObjectClass(mGlobalJSObject);
       mUseXBLScope = !strcmp(clasp->name, "Window") ||
                      !strcmp(clasp->name, "ChromeWindow") ||
                      !strcmp(clasp->name, "ModalContentWindow");
--- a/js/xpconnect/src/dictionary_helper_gen.conf
+++ b/js/xpconnect/src/dictionary_helper_gen.conf
@@ -1,15 +1,14 @@
 # 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/.
 
 # Dictionary interface name, interface file name
 dictionaries = [
-     [ 'GeoPositionOptions', 'nsIDOMGeoGeolocation.idl' ],
      [ 'DOMFileMetadataParameters', 'nsIDOMLockedFile.idl' ],
      [ 'CameraSize', 'nsIDOMCameraManager.idl' ],
      [ 'CameraRegion', 'nsIDOMCameraManager.idl' ],
      [ 'CameraPosition', 'nsIDOMCameraManager.idl' ],
      [ 'CameraSelector', 'nsIDOMCameraManager.idl' ],
      [ 'CameraRecordingOptions', 'nsIDOMCameraManager.idl' ],
      [ 'SmsThreadListItem', 'nsIMobileMessageCallback.idl' ],
      [ 'MmsAttachment', 'nsIDOMMozMmsMessage.idl' ]
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -48,16 +48,18 @@
 
 #include "nsWrapperCacheInlines.h"
 #include "nsCycleCollectionNoteRootCallback.h"
 #include "nsCycleCollector.h"
 #include "nsDOMMutationObserver.h"
 #include "nsICycleCollectorListener.h"
 #include "nsThread.h"
 #include "mozilla/XPTInterfaceInfoManager.h"
+#include "nsIObjectInputStream.h"
+#include "nsIObjectOutputStream.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace xpc;
 using namespace JS;
 
 NS_IMPL_ISUPPORTS5(nsXPConnect,
                    nsIXPConnect,
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -92,17 +92,16 @@
 #include <string.h>
 
 #include "xpcpublic.h"
 #include "pldhash.h"
 #include "nscore.h"
 #include "nsXPCOM.h"
 #include "nsAutoPtr.h"
 #include "nsCycleCollectionParticipant.h"
-#include "mozilla/CycleCollectedJSRuntime.h"
 #include "nsDebug.h"
 #include "nsISupports.h"
 #include "nsIServiceManager.h"
 #include "nsIClassInfoImpl.h"
 #include "nsIComponentManager.h"
 #include "nsIComponentRegistrar.h"
 #include "nsISupportsPrimitives.h"
 #include "nsMemory.h"
@@ -155,16 +154,17 @@
 #include "nsIScriptObjectPrincipal.h"
 #include "nsISecurityCheckedComponent.h"
 #include "xpcObjectHelper.h"
 #include "nsIThreadInternal.h"
 
 #include "SandboxPrivate.h"
 #include "BackstagePass.h"
 #include "nsCxPusher.h"
+#include "nsAXPCNativeCallContext.h"
 
 #ifdef XP_WIN
 // Nasty MS defines
 #ifdef GetClassInfo
 #undef GetClassInfo
 #endif
 #ifdef GetClassName
 #undef GetClassName
@@ -1198,23 +1198,17 @@ XPC_WN_JSOp_ThisObject(JSContext *cx, JS
         nullptr, /* getElement    */                                          \
         nullptr, /* getElementIfPresent */                                    \
         nullptr, /* getSpecial    */                                          \
         nullptr, /* setGeneric    */                                          \
         nullptr, /* setProperty    */                                         \
         nullptr, /* setElement    */                                          \
         nullptr, /* setSpecial    */                                          \
         nullptr, /* getGenericAttributes  */                                  \
-        nullptr, /* getAttributes  */                                         \
-        nullptr, /* getElementAttributes  */                                  \
-        nullptr, /* getSpecialAttributes  */                                  \
         nullptr, /* setGenericAttributes  */                                  \
-        nullptr, /* setAttributes  */                                         \
-        nullptr, /* setElementAttributes  */                                  \
-        nullptr, /* setSpecialAttributes  */                                  \
         nullptr, /* deleteProperty */                                         \
         nullptr, /* deleteElement */                                          \
         nullptr, /* deleteSpecial */                                          \
         XPC_WN_JSOp_Enumerate,                                                \
         XPC_WN_JSOp_ThisObject,                                               \
     }
 
 #define XPC_WN_NoCall_ObjectOps                                               \
@@ -1232,23 +1226,17 @@ XPC_WN_JSOp_ThisObject(JSContext *cx, JS
         nullptr, /* getElement    */                                          \
         nullptr, /* getElementIfPresent */                                    \
         nullptr, /* getSpecial    */                                          \
         nullptr, /* setGeneric    */                                          \
         nullptr, /* setProperty    */                                         \
         nullptr, /* setElement    */                                          \
         nullptr, /* setSpecial    */                                          \
         nullptr, /* getGenericAttributes  */                                  \
-        nullptr, /* getAttributes  */                                         \
-        nullptr, /* getElementAttributes  */                                  \
-        nullptr, /* getSpecialAttributes  */                                  \
         nullptr, /* setGenericAttributes  */                                  \
-        nullptr, /* setAttributes  */                                         \
-        nullptr, /* setElementAttributes  */                                  \
-        nullptr, /* setSpecialAttributes  */                                  \
         nullptr, /* deleteProperty */                                         \
         nullptr, /* deleteElement */                                          \
         nullptr, /* deleteSpecial */                                          \
         XPC_WN_JSOp_Enumerate,                                                \
         XPC_WN_JSOp_ThisObject,                                               \
     }
 
 // Maybe this macro should check for class->enumerate ==
@@ -3864,16 +3852,18 @@ inline XPCWrappedNativeScope*
 GetObjectScope(JSObject *obj)
 {
     return EnsureCompartmentPrivate(obj)->scope;
 }
 
 extern bool gDebugMode;
 extern bool gDesiredDebugMode;
 
+extern JSClass SafeJSContextGlobalClass;
+
 JSObject* NewOutObject(JSContext* cx, JSObject* scope);
 bool IsOutObject(JSContext* cx, JSObject* obj);
 
 nsresult HasInstance(JSContext *cx, JS::HandleObject objArg, const nsID *iid, bool *bp);
 
 } // namespace xpc
 
 /***************************************************************************/
--- a/layout/base/nsRefreshDriver.cpp
+++ b/layout/base/nsRefreshDriver.cpp
@@ -1163,17 +1163,16 @@ nsRefreshDriver::Tick(int64_t aNowEpoch,
     // images to refresh, and then we refresh each image in that array.
     nsCOMArray<imgIContainer> imagesToRefresh(mRequests.Count());
     mRequests.EnumerateEntries(nsRefreshDriver::ImageRequestEnumerator,
                                &imagesToRefresh);
 
     for (uint32_t i = 0; i < imagesToRefresh.Length(); i++) {
       imagesToRefresh[i]->RequestRefresh(aNowTime);
     }
-    imagesToRefresh.Clear();
   }
 
   for (uint32_t i = 0; i < mPresShellsToInvalidateIfHidden.Length(); i++) {
     mPresShellsToInvalidateIfHidden[i]->InvalidatePresShellIfHidden();
   }
   mPresShellsToInvalidateIfHidden.Clear();
 
   if (mViewManagerFlushIsPending) {
--- a/layout/reftests/position-sticky/reftest.list
+++ b/layout/reftests/position-sticky/reftest.list
@@ -1,14 +1,14 @@
 test-pref(layout.css.sticky.enabled,false) == pref-1.html pref-1-disabled-ref.html
 test-pref(layout.css.sticky.enabled,true) == pref-1.html pref-1-enabled-ref.html
 default-preferences pref(layout.css.sticky.enabled,true)
 
 == top-1.html top-1-ref.html
-fuzzy-if(Android,4,914) == top-2.html top-2-ref.html
+fuzzy-if(Android,6,914) == top-2.html top-2-ref.html
 fuzzy-if(Android,4,2729) == top-3.html top-3-ref.html
 == top-4.html top-4-ref.html
 == top-5.html top-5-ref.html
 == top-6.html top-6-ref.html
 == bottom-1.html bottom-1-ref.html
 == bottom-2a.html bottom-2-ref.html
 == bottom-2b.html bottom-2-ref.html
 == bottom-2c.html bottom-2-ref.html
--- a/layout/style/nsCSSStyleSheet.cpp
+++ b/layout/style/nsCSSStyleSheet.cpp
@@ -35,16 +35,17 @@
 #include "nsContentUtils.h"
 #include "nsIScriptSecurityManager.h"
 #include "mozAutoDocUpdate.h"
 #include "nsRuleNode.h"
 #include "nsMediaFeatures.h"
 #include "nsDOMClassInfoID.h"
 #include "mozilla/Likely.h"
 #include "mozilla/dom/CSSStyleSheetBinding.h"
+#include "nsComponentManagerUtils.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 
 // -------------------------------
 // Style Rule List for the DOM
 //
--- a/layout/xul/base/src/nsBoxObject.cpp
+++ b/layout/xul/base/src/nsBoxObject.cpp
@@ -18,16 +18,17 @@
 #include "nsIDOMXULElement.h"
 #else
 #include "nsIDOMElement.h"
 #endif
 #include "nsLayoutUtils.h"
 #include "nsISupportsPrimitives.h"
 #include "nsSupportsPrimitives.h"
 #include "mozilla/dom/Element.h"
+#include "nsComponentManagerUtils.h"
 
 using namespace mozilla::dom;
 
 // Implementation /////////////////////////////////////////////////////////////////
 
 // Static member variable initialization
 
 // Implement our nsISupports methods
--- a/layout/xul/tree/nsTreeSelection.cpp
+++ b/layout/xul/tree/nsTreeSelection.cpp
@@ -13,16 +13,17 @@
 #include "nsDOMClassInfoID.h"
 #include "nsIContent.h"
 #include "nsGUIEvent.h"
 #include "nsINameSpaceManager.h"
 #include "nsGkAtoms.h"
 #include "nsAsyncDOMEvent.h"
 #include "nsEventDispatcher.h"
 #include "nsAutoPtr.h"
+#include "nsComponentManagerUtils.h"
 
 // A helper class for managing our ranges of selection.
 struct nsTreeRange
 {
   nsTreeSelection* mSelection;
 
   nsTreeRange* mPrev;
   nsTreeRange* mNext;
--- a/media/webrtc/signaling/src/media/VcmSIPCCBinding.cpp
+++ b/media/webrtc/signaling/src/media/VcmSIPCCBinding.cpp
@@ -64,21 +64,23 @@ typedef enum {
 
 using namespace CSF;
 
 VcmSIPCCBinding * VcmSIPCCBinding::gSelf = NULL;
 int VcmSIPCCBinding::gAudioCodecMask = 0;
 int VcmSIPCCBinding::gVideoCodecMask = 0;
 nsIThread *VcmSIPCCBinding::gMainThread = NULL;
 
-static mozilla::RefPtr<TransportFlow> vcmCreateTransportFlow(sipcc::PeerConnectionImpl *pc,
-                                                             int level, bool rtcp,
-                                                             const char *fingerprint_alg,
-                                                             const char *fingerprint
-                                                             );
+static mozilla::RefPtr<TransportFlow> vcmCreateTransportFlow(
+    sipcc::PeerConnectionImpl *pc,
+    int level,
+    bool rtcp,
+    sdp_setup_type_e setup_type,
+    const char *fingerprint_alg,
+    const char *fingerprint);
 
 // Convenience macro to acquire PC
 
 #define ENSURE_PC(pc, errval) \
   do { \
     if (!pc.impl()) {                                                 \
       CSFLogDebug(logTag, "%s: couldn't acquire peerconnection %s", __FUNCTION__, peerconnection); \
       return errval; \
@@ -1344,16 +1346,17 @@ int vcmRxStart(cc_mcapid_t mcap_id,
  *  @param[in]   stream_id    - stream id of the given media type.
  *  @param[in]   level        - the m-line index
  *  @param[in]   pc_stream_id - the media stream index (from PC.addStream())
  *  @param[in]   pc_track_id  - the track within the media stream
  *  @param[in]   call_handle  - call handle
  *  @param[in]   peerconnection - the peerconnection in use
  *  @param[in]   num_payloads   - number of negotiated payloads
  *  @param[in]   payloads       - negotiated codec details list
+ *  @param[in]   setup          - whether playing client or server role
  *  @param[in]   fingerprint_alg - the DTLS fingerprint algorithm
  *  @param[in]   fingerprint  - the DTLS fingerprint
  *  @param[in]   attrs        - media attributes
  *
  *  Returns: zero(0) for success; otherwise, ERROR for failure
  */
 
 static int vcmRxStartICE_m(cc_mcapid_t mcap_id,
@@ -1361,29 +1364,30 @@ static int vcmRxStartICE_m(cc_mcapid_t m
         cc_streamid_t stream_id,
         int level,
         int pc_stream_id,
         int pc_track_id,
         cc_call_handle_t  call_handle,
         const char *peerconnection,
         int num_payloads,
         const vcm_payload_info_t* payloads,
+        sdp_setup_type_e setup_type,
         const char *fingerprint_alg,
         const char *fingerprint,
         vcm_mediaAttrs_t *attrs)
 {
   CSFLogDebug( logTag, "%s(%s)", __FUNCTION__, peerconnection);
 
   // Find the PC.
   sipcc::PeerConnectionWrapper pc(peerconnection);
   ENSURE_PC(pc, VCM_ERROR);
 
   // Datachannel will use this though not for RTP
   mozilla::RefPtr<TransportFlow> rtp_flow =
-    vcmCreateTransportFlow(pc.impl(), level, false,
+    vcmCreateTransportFlow(pc.impl(), level, false, setup_type,
                            fingerprint_alg, fingerprint);
   if (!rtp_flow) {
     CSFLogError( logTag, "Could not create RTP flow");
     return VCM_ERROR;
   }
 
   if (CC_IS_DATACHANNEL(mcap_id)) {
     // That's all we need for DataChannels - a flow registered
@@ -1402,17 +1406,17 @@ static int vcmRxStartICE_m(cc_mcapid_t m
   if (!stream) {
     // This should never happen
     PR_ASSERT(PR_FALSE);
     return VCM_ERROR;
   }
 
   mozilla::RefPtr<TransportFlow> rtcp_flow = nullptr;
   if(!attrs->rtcp_mux) {
-    rtcp_flow = vcmCreateTransportFlow(pc.impl(), level, true,
+    rtcp_flow = vcmCreateTransportFlow(pc.impl(), level, true, setup_type,
                                        fingerprint_alg, fingerprint);
     if (!rtcp_flow) {
       CSFLogError( logTag, "Could not create RTCP flow");
       return VCM_ERROR;
     }
   }
 
   if (CC_IS_AUDIO(mcap_id)) {
@@ -1530,16 +1534,17 @@ static int vcmRxStartICE_m(cc_mcapid_t m
  *  @param[in]   stream_id    - stream id of the given media type.
  *  @param[in]   level        - the m-line index
  *  @param[in]   pc_stream_id - the media stream index (from PC.addStream())
  *  @param[i]n   pc_track_id  - the track within the media stream
  *  @param[in]   call_handle  - call handle
  *  @param[in]  peerconnection - the peerconnection in use
  *  @param[in]  num_payloads   - number of negotiated payloads
  *  @param[in]  payloads       - negotiated codec details list
+ *  @param[in]   setup_type    - whether playing client or server role
  *  @param[in]   fingerprint_alg - the DTLS fingerprint algorithm
  *  @param[in]   fingerprint  - the DTLS fingerprint
  *  @param[in]   attrs        - media attributes
  *
  *  Returns: zero(0) for success; otherwise, ERROR for failure
  */
 
 int vcmRxStartICE(cc_mcapid_t mcap_id,
@@ -1547,16 +1552,17 @@ int vcmRxStartICE(cc_mcapid_t mcap_id,
                   cc_streamid_t stream_id,
                   int level,
                   int pc_stream_id,
                   int pc_track_id,
                   cc_call_handle_t  call_handle,
                   const char *peerconnection,
                   int num_payloads,
                   const vcm_payload_info_t* payloads,
+                  sdp_setup_type_e setup_type,
                   const char *fingerprint_alg,
                   const char *fingerprint,
                   vcm_mediaAttrs_t *attrs)
 {
   int ret;
 
   mozilla::SyncRunnable::DispatchToThread(VcmSIPCCBinding::getMainThread(),
       WrapRunnableNMRet(&vcmRxStartICE_m,
@@ -1565,16 +1571,17 @@ int vcmRxStartICE(cc_mcapid_t mcap_id,
                         stream_id,
                         level,
                         pc_stream_id,
                         pc_track_id,
                         call_handle,
                         peerconnection,
                         num_payloads,
                         payloads,
+                        setup_type,
                         fingerprint_alg,
                         fingerprint,
                         attrs,
                         &ret));
 
   return ret;
 }
 
@@ -2004,16 +2011,17 @@ int vcmTxStart(cc_mcapid_t mcap_id,
  *  @param[in]   stream_id    - stream id of the given media type.
  *  @param[in]   level        - the m-line index
  *  @param[in]   pc_stream_id - the media stream index (from PC.addStream())
  *  @param[i]n   pc_track_id  - the track within the media stream
  *  @param[in]   call_handle  - call handle
  *  @param[in]   peerconnection - the peerconnection in use
  *  @param[in]   payload      - payload information
  *  @param[in]   tos          - bit marking
+ *  @param[in]   setup_type   - whether playing the client or server role
  *  @param[in]   fingerprint_alg - the DTLS fingerprint algorithm
  *  @param[in]   fingerprint  - the DTLS fingerprint
  *  @param[in]   attrs        - media attributes
  *
  *  Returns: zero(0) for success; otherwise, ERROR for failure
  *
  */
 #define EXTRACT_DYNAMIC_PAYLOAD_TYPE(PTYPE) ((PTYPE)>>16)
@@ -2023,39 +2031,40 @@ static int vcmTxStartICE_m(cc_mcapid_t m
         cc_streamid_t stream_id,
         int level,
         int pc_stream_id,
         int pc_track_id,
         cc_call_handle_t  call_handle,
         const char *peerconnection,
         const vcm_payload_info_t *payload,
         short tos,
+        sdp_setup_type_e setup_type,
         const char *fingerprint_alg,
         const char *fingerprint,
         vcm_mediaAttrs_t *attrs)
 {
   CSFLogDebug( logTag, "%s(%s)", __FUNCTION__, peerconnection);
 
   // Find the PC and get the stream
   sipcc::PeerConnectionWrapper pc(peerconnection);
   ENSURE_PC(pc, VCM_ERROR);
   nsRefPtr<sipcc::LocalSourceStreamInfo> stream = pc.impl()->media()->
     GetLocalStream(pc_stream_id);
 
   // Create the transport flows
   mozilla::RefPtr<TransportFlow> rtp_flow =
-      vcmCreateTransportFlow(pc.impl(), level, false,
+      vcmCreateTransportFlow(pc.impl(), level, false, setup_type,
                              fingerprint_alg, fingerprint);
   if (!rtp_flow) {
       CSFLogError( logTag, "Could not create RTP flow");
       return VCM_ERROR;
   }
   mozilla::RefPtr<TransportFlow> rtcp_flow = nullptr;
   if(!attrs->rtcp_mux) {
-    rtcp_flow = vcmCreateTransportFlow(pc.impl(), level, true,
+    rtcp_flow = vcmCreateTransportFlow(pc.impl(), level, true, setup_type,
                                        fingerprint_alg, fingerprint);
     if (!rtcp_flow) {
       CSFLogError( logTag, "Could not create RTCP flow");
       return VCM_ERROR;
     }
   }
 
   if (CC_IS_AUDIO(mcap_id)) {
@@ -2161,16 +2170,17 @@ static int vcmTxStartICE_m(cc_mcapid_t m
  *  @param[in]   stream_id    - stream id of the given media type.
  *  @param[in]   level        - the m-line index
  *  @param[in]   pc_stream_id - the media stream index (from PC.addStream())
  *  @param[i]n   pc_track_id  - the track within the media stream
  *  @param[in]   call_handle  - call handle
  *  @param[in]  peerconnection - the peerconnection in use
  *  @param[in]   payload      - payload type
  *  @param[in]   tos          - bit marking
+ *  @param[in]   setup_type   - whether playing client or server role.
  *  @param[in]   fingerprint_alg - the DTLS fingerprint algorithm
  *  @param[in]   fingerprint  - the DTLS fingerprint
  *  @param[in]   attrs        - media attributes
  *
  *  Returns: zero(0) for success; otherwise, ERROR for failure
  *
  */
 #define EXTRACT_DYNAMIC_PAYLOAD_TYPE(PTYPE) ((PTYPE)>>16)
@@ -2180,16 +2190,17 @@ int vcmTxStartICE(cc_mcapid_t mcap_id,
                   cc_streamid_t stream_id,
                   int level,
                   int pc_stream_id,
                   int pc_track_id,
                   cc_call_handle_t  call_handle,
                   const char *peerconnection,
                   const vcm_payload_info_t *payload,
                   short tos,
+                  sdp_setup_type_e setup_type,
                   const char *fingerprint_alg,
                   const char *fingerprint,
                   vcm_mediaAttrs_t *attrs)
 {
   int ret;
 
   mozilla::SyncRunnable::DispatchToThread(VcmSIPCCBinding::getMainThread(),
       WrapRunnableNMRet(&vcmTxStartICE_m,
@@ -2198,16 +2209,17 @@ int vcmTxStartICE(cc_mcapid_t mcap_id,
                         stream_id,
                         level,
                         pc_stream_id,
                         pc_track_id,
                         call_handle,
                         peerconnection,
                         payload,
                         tos,
+                        setup_type,
                         fingerprint_alg,
                         fingerprint,
                         attrs,
                         &ret));
 
   return ret;
 }
 
@@ -2695,18 +2707,18 @@ int vcmGetILBCMode()
 {
     return 0;
 }
 
 } // extern "C"
 
 static mozilla::RefPtr<TransportFlow>
 vcmCreateTransportFlow(sipcc::PeerConnectionImpl *pc, int level, bool rtcp,
-                       const char *fingerprint_alg,
-                       const char *fingerprint) {
+  sdp_setup_type_e setup_type, const char *fingerprint_alg,
+  const char *fingerprint) {
 
   // TODO(ekr@rtfm.com): Check that if the flow already exists the digest
   // is the same. The only way that can happen is if
   //
   // (a) We have an error or
   // (b) The other side bundled but had mismatched digests for each line
   //
   // Not clear that either of these cases matters.
@@ -2738,23 +2750,24 @@ vcmCreateTransportFlow(sipcc::PeerConnec
     //   setup attribute value of setup:active or setup:passive.  Note that
     //   if the answerer uses setup:passive, then the DTLS handshake will
     //   not begin until the answerer is received, which adds additional
     //   latency. setup:active allows the answer and the DTLS handshake to
     //   occur in parallel.  Thus, setup:active is RECOMMENDED.  Whichever
     //   party is active MUST initiate a DTLS handshake by sending a
     //   ClientHello over each flow (host/port quartet).
     //
-    // Currently we just hardwire the roles to be that the offerer is the
-    // server, which is what you would expect from the "recommended"
-    // behavior above.
-    //
-    // TODO(ekr@rtfm.com): implement the actpass logic above.
-    dtls->SetRole(pc->GetRole() == sipcc::PeerConnectionImpl::kRoleOfferer ?
-                  TransportLayerDtls::SERVER : TransportLayerDtls::CLIENT);
+
+    // setup_type should at this point be either PASSIVE or ACTIVE
+    // other a=setup values should have been negotiated out.
+    MOZ_ASSERT(setup_type == SDP_SETUP_PASSIVE ||
+               setup_type == SDP_SETUP_ACTIVE);
+    dtls->SetRole(
+      setup_type == SDP_SETUP_PASSIVE ?
+      TransportLayerDtls::SERVER : TransportLayerDtls::CLIENT);
     mozilla::RefPtr<DtlsIdentity> pcid = pc->GetIdentity();
     if (!pcid) {
       return nullptr;
     }
     dtls->SetIdentity(pcid);
 
     unsigned char remote_digest[TransportLayerDtls::kMaxDigestLength];
     size_t digest_len;
@@ -2854,9 +2867,57 @@ int vcmOnSdpParseError(const char *peerc
   if (!NS_SUCCEEDED(rv)) {
     CSFLogError( logTag, "%s(): Could not dispatch to main thread", __FUNCTION__);
     return VCM_ERROR;
   }
 
   return 0;
 }
 
-
+/**
+ * vcmDisableRtcpComponent_m
+ *
+ * If we are doing rtcp-mux we need to disable component number 2 in the ICE
+ * layer.  Otherwise we will wait for it to connect when it is unused
+ */
+static int vcmDisableRtcpComponent_m(const char *peerconnection, int level) {
+#ifdef MOZILLA_INTERNAL_API
+  MOZ_ASSERT(NS_IsMainThread());
+#endif
+  MOZ_ASSERT(level > 0);
+
+  sipcc::PeerConnectionWrapper pc(peerconnection);
+  ENSURE_PC(pc, VCM_ERROR);
+
+  CSFLogDebug( logTag, "%s: disabling rtcp component %d", __FUNCTION__, level);
+  mozilla::RefPtr<NrIceMediaStream> stream = pc.impl()->media()->
+    ice_media_stream(level-1);
+  MOZ_ASSERT(stream);
+  if (!stream) {
+    return VCM_ERROR;
+  }
+
+  // The second component is for RTCP
+  nsresult res = stream->DisableComponent(2);
+  MOZ_ASSERT(NS_SUCCEEDED(res));
+  if (!NS_SUCCEEDED(res)) {
+    return VCM_ERROR;
+  }
+
+  return 0;
+}
+
+/**
+ * vcmDisableRtcpComponent
+ *
+ * If we are doing rtcp-mux we need to disable component number 2 in the ICE
+ * layer.  Otherwise we will wait for it to connect when it is unused
+ */
+int vcmDisableRtcpComponent(const char *peerconnection, int level) {
+  int ret;
+  mozilla::SyncRunnable::DispatchToThread(VcmSIPCCBinding::getMainThread(),
+      WrapRunnableNMRet(&vcmDisableRtcpComponent_m,
+                        peerconnection,
+                        level,
+                        &ret));
+  return ret;
+}
+
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
@@ -330,17 +330,16 @@ private:
   nsRefPtr<RemoteSourceStreamInfo> mRemoteStream;
 };
 
 NS_IMPL_ISUPPORTS1(PeerConnectionImpl, IPeerConnection)
 
 PeerConnectionImpl::PeerConnectionImpl()
 : mTimeCard(PR_LOG_TEST(signalingLogInfo(),PR_LOG_ERROR) ?
             create_timecard() : nullptr)
-  , mRole(kRoleUnknown)
   , mCall(NULL)
   , mReadyState(kNew)
   , mSignalingState(kSignalingStable)
   , mIceState(kIceGathering)
   , mPCObserver(NULL)
   , mWindow(NULL)
   , mIdentity(NULL)
   , mSTSThread(NULL)
@@ -1017,18 +1016,16 @@ NS_IMETHODIMP
 PeerConnectionImpl::CreateOffer(MediaConstraints& constraints)
 {
   PC_AUTO_ENTER_API_CALL(true);
 
   Timecard *tc = mTimeCard;
   mTimeCard = nullptr;
   STAMP_TIMECARD(tc, "Create Offer");
 
-  mRole = kRoleOfferer;  // TODO(ekr@rtfm.com): Interrogate SIPCC here?
-
   cc_media_constraints_t* cc_constraints = nullptr;
   constraints.buildArray(&cc_constraints);
 
   mCall->createOffer(cc_constraints, tc);
   return NS_OK;
 }
 
 NS_IMETHODIMP
@@ -1049,18 +1046,16 @@ NS_IMETHODIMP
 PeerConnectionImpl::CreateAnswer(MediaConstraints& constraints)
 {
   PC_AUTO_ENTER_API_CALL(true);
 
   Timecard *tc = mTimeCard;
   mTimeCard = nullptr;
   STAMP_TIMECARD(tc, "Create Answer");
 
-  mRole = kRoleAnswerer;  // TODO(ekr@rtfm.com): Interrogate SIPCC here?
-
   cc_media_constraints_t* cc_constraints = nullptr;
   constraints.buildArray(&cc_constraints);
 
   mCall->createAnswer(cc_constraints, tc);
   return NS_OK;
 }
 
 NS_IMETHODIMP
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h
@@ -160,22 +160,16 @@ public:
   enum IceState {
     kIceGathering,
     kIceWaiting,
     kIceChecking,
     kIceConnected,
     kIceFailed
   };
 
-  enum Role {
-    kRoleUnknown,
-    kRoleOfferer,
-    kRoleAnswerer
-  };
-
   enum Error {
     kNoError                          = 0,
     kInvalidConstraintsType           = 1,
     kInvalidCandidateType             = 2,
     kInvalidMediastreamTrack          = 3,
     kInvalidState                     = 4,
     kInvalidSessionDescription        = 5,
     kIncompatibleSessionDescription   = 6,
@@ -190,21 +184,16 @@ public:
   static PeerConnectionImpl* CreatePeerConnection();
   static nsresult ConvertRTCConfiguration(const JS::Value& aSrc,
     IceConfiguration *aDst, JSContext* aCx);
   static nsresult ConvertConstraints(
     const JS::Value& aConstraints, MediaConstraints* aObj, JSContext* aCx);
   static already_AddRefed<DOMMediaStream> MakeMediaStream(nsPIDOMWindow* aWindow,
                                                           uint32_t aHint);
 
-  Role GetRole() const {
-    PC_AUTO_ENTER_API_CALL_NO_CHECK();
-    return mRole;
-  }
-
   nsresult CreateRemoteSourceStreamInfo(nsRefPtr<RemoteSourceStreamInfo>* aInfo);
 
   // Implementation of the only observer we need
   virtual void onCallEvent(
     ccapi_call_event_e aCallEvent,
     CSF::CC_CallInfoPtr aInfo
   );
 
@@ -334,19 +323,16 @@ private:
   // ICE callbacks run on the right thread.
   nsresult IceStateChange_m(IceState aState);
 
   // Timecard used to measure processing time. This should be the first class
   // attribute so that we accurately measure the time required to instantiate
   // any other attributes of this class.
   Timecard *mTimeCard;
 
-  // The role we are adopting
-  Role mRole;
-
   // The call
   CSF::CC_CallPtr mCall;
   ReadyState mReadyState;
   SignalingState mSignalingState;
 
   // ICE State
   IceState mIceState;
 
--- a/media/webrtc/signaling/src/sipcc/core/gsm/gsm_sdp.c
+++ b/media/webrtc/signaling/src/sipcc/core/gsm/gsm_sdp.c
@@ -523,16 +523,19 @@ gsmsdp_init_media (fsmdef_media_t *media
 
     media->hold  = FSM_HOLD_NONE;
     media->flags = 0;                    /* clear all flags      */
     media->cap_index = CC_MAX_MEDIA_CAP; /* max is invalid value */
     media->video = NULL;
     media->candidate_ct = 0;
     media->rtcp_mux = FALSE;
 
+    /* ACTPASS is the value we put in every offer */
+    media->setup = SDP_SETUP_ACTPASS;
+
     media->local_datachannel_port = 0;
     media->remote_datachannel_port = 0;
     media->datachannel_streams = WEBRTC_DATACHANNEL_STREAMS_DEFAULT;
     sstrncpy(media->datachannel_protocol, WEBRTC_DATA_CHANNEL_PROT, SDP_MAX_STRING_LEN);
 
     media->payloads = NULL;
     media->num_payloads = 0;
 }
@@ -1817,16 +1820,81 @@ gsmsdp_set_rtcp_mux_attribute (sdp_attr_
 
     result = sdp_attr_set_rtcp_mux_attribute(sdp_p, level, 0, sdp_attr, a_instance, rtcp_mux);
     if (result != SDP_SUCCESS) {
         GSM_ERR_MSG("Failed to set attribute");
     }
 }
 
 /*
+ * gsmsdp_set_setup_attribute
+ *
+ * Description:
+ *
+ * Adds a setup attribute to the specified SDP.
+ *
+ * Parameters:
+ *
+ * level        - The media level of the SDP where the media attribute exists.
+ * sdp_p        - Pointer to the SDP to set the ice candidate attribute against.
+ * setup_type   - Value for the a=setup line
+ */
+static void
+gsmsdp_set_setup_attribute(uint16_t level,
+  void *sdp_p, sdp_setup_type_e setup_type) {
+    uint16_t a_instance = 0;
+    sdp_result_e result;
+
+    result = sdp_add_new_attr(sdp_p, level, 0, SDP_ATTR_SETUP, &a_instance);
+    if (result != SDP_SUCCESS) {
+        GSM_ERR_MSG("Failed to add attribute");
+        return;
+    }
+
+    result = sdp_attr_set_setup_attribute(sdp_p, level, 0,
+      a_instance, setup_type);
+    if (result != SDP_SUCCESS) {
+        GSM_ERR_MSG("Failed to set attribute");
+    }
+}
+
+/*
+ * gsmsdp_set_connection_attribute
+ *
+ * Description:
+ *
+ * Adds a connection attribute to the specified SDP.
+ *
+ * Parameters:
+ *
+ * level        - The media level of the SDP where the media attribute exists.
+ * sdp_p        - Pointer to the SDP to set the ice candidate attribute against.
+ * connection_type - Value for the a=connection line
+ */
+static void
+gsmsdp_set_connection_attribute(uint16_t level,
+  void *sdp_p, sdp_connection_type_e connection_type) {
+    uint16_t a_instance = 0;
+    sdp_result_e result;
+
+    result = sdp_add_new_attr(sdp_p, level, 0, SDP_ATTR_CONNECTION,
+      &a_instance);
+    if (result != SDP_SUCCESS) {
+        GSM_ERR_MSG("Failed to add attribute");
+        return;
+    }
+
+    result = sdp_attr_set_connection_attribute(sdp_p, level, 0,
+      a_instance, connection_type);
+    if (result != SDP_SUCCESS) {
+        GSM_ERR_MSG("Failed to set attribute");
+    }
+}
+
+/*
  * gsmsdp_set_dtls_fingerprint_attribute
  *
  * Description:
  *
  * Adds an dtls fingerprint attribute attributes to the specified SDP.
  *
  * Parameters:
  *
@@ -4636,16 +4704,17 @@ gsmsdp_negotiate_media_lines (fsm_fcb_t 
     char           *session_pwd;
     cc_action_data_t  data;
     int             j=0;
     int             rtcpmux = 0;
     tinybool        rtcp_mux = FALSE;
     sdp_result_e    sdp_res;
     boolean         created_media_stream = FALSE;
     int             lsm_rc;
+    sdp_setup_type_e remote_setup_type;
 
     config_get_value(CFGID_SDPMODE, &sdpmode, sizeof(sdpmode));
 
     num_m_lines = sdp_get_num_media_lines(sdp_p->dest_sdp);
     if (num_m_lines == 0) {
         GSM_DEBUG(DEB_L_C_F_PREFIX"no media lines found.",
                   DEB_L_C_F_PREFIX_ARGS(GSM, dcb_p->line, dcb_p->call_id, fname));
         return CC_CAUSE_NO_MEDIA;
@@ -4934,16 +5003,50 @@ gsmsdp_negotiate_media_lines (fsm_fcb_t 
               }
             }
 
             if (!unsupported_line) {
 
               if (sdpmode) {
                   int j;
 
+                  /* Find the remote a=setup value */
+                  sdp_res = sdp_attr_get_setup_attribute(
+                      sdp_p->dest_sdp, i, 0, 1, &remote_setup_type);
+
+
+                  /* setup attribute
+                     We are setting our local SDP to be ACTIVE if the value
+                     in the remote SDP is missing, PASSIVE or ACTPASS.
+                     If the remote value is ACTIVE, then we will respond
+                     with PASSIVE.
+                     If the remote value is HOLDCONN we will respond with
+                     HOLDCONN and set the direction to INACTIVE
+                     The DTLS role will then be set when the TransportFlow
+                     is created */
+                  media->setup = SDP_SETUP_ACTIVE;
+
+                  if (sdp_res == SDP_SUCCESS) {
+                      if (remote_setup_type == SDP_SETUP_ACTIVE) {
+                          media->setup = SDP_SETUP_PASSIVE;
+                      } else if (remote_setup_type == SDP_SETUP_HOLDCONN) {
+                          media->setup = SDP_SETUP_HOLDCONN;
+                          media->direction = SDP_DIRECTION_INACTIVE;
+                      }
+                  }
+
+                  gsmsdp_set_setup_attribute(media->level, dcb_p->sdp->src_sdp,
+                    media->setup);
+
+                  /* TODO(ehugg) we are not yet supporting existing connections
+                     See bug 857115.  We currently always respond with
+                     connection:new */
+                  gsmsdp_set_connection_attribute(media->level,
+                    dcb_p->sdp->src_sdp, SDP_CONNECTION_NEW);
+
                   /* Set ICE */
                   for (j=0; j<media->candidate_ct; j++) {
                     gsmsdp_set_ice_attribute (SDP_ATTR_ICE_CANDIDATE, media->level,
                                               sdp_p->src_sdp, media->candidatesp[j]);
                   }
 
                   /* Set RTCPMux if we have it turned on in our config
                      and the other side requests it */
@@ -5451,16 +5554,23 @@ gsmsdp_add_media_line (fsmdef_dcb_t *dcb
           /* Add supported rtcp-fb types */
           if (media_cap->type == SDP_MEDIA_VIDEO) {
               gsmsdp_add_rtcp_fb (level, dcb_p->sdp->src_sdp, RTP_VP8,
                   SDP_RTCP_FB_NACK_TO_BITMAP(SDP_RTCP_FB_NACK_BASIC) |
                   SDP_RTCP_FB_NACK_TO_BITMAP(SDP_RTCP_FB_NACK_PLI) |
                   SDP_RTCP_FB_CCM_TO_BITMAP(SDP_RTCP_FB_CCM_FIR));
           }
 
+          /* setup and connection attributes */
+          gsmsdp_set_setup_attribute(level, dcb_p->sdp->src_sdp, media->setup);
+
+          /* This is a new media line so we should send connection:new */
+          gsmsdp_set_connection_attribute(level, dcb_p->sdp->src_sdp,
+            SDP_CONNECTION_NEW);
+
           /*
            * wait until here to set ICE candidates as SDP is now initialized
            */
           for (i=0; i<media->candidate_ct; i++) {
             gsmsdp_set_ice_attribute (SDP_ATTR_ICE_CANDIDATE, level, dcb_p->sdp->src_sdp, media->candidatesp[i]);
           }
 
           config_get_value(CFGID_RTCPMUX, &rtcpmux, sizeof(rtcpmux));
@@ -6829,16 +6939,27 @@ gsmsdp_install_peer_ice_attributes(fsm_f
             return (CC_CAUSE_SETTING_ICE_SESSION_PARAMETERS_FAILED);
     }
 
     /* Now process all the media lines */
     GSMSDP_FOR_ALL_MEDIA(media, dcb_p) {
       if (!GSMSDP_MEDIA_ENABLED(media))
         continue;
 
+      /* If we are muxing, disable the second
+         component of the ICE stream */
+      if (media->rtcp_mux) {
+        vcm_res = vcmDisableRtcpComponent(dcb_p->peerconnection,
+          media->level);
+
+        if (vcm_res) {
+          return (CC_CAUSE_SETTING_ICE_SESSION_PARAMETERS_FAILED);
+        }
+      }
+
       sdp_res = sdp_attr_get_ice_attribute(sdp_p->dest_sdp, media->level, 0,
         SDP_ATTR_ICE_UFRAG, 1, &ufrag);
       if (sdp_res != SDP_SUCCESS)
         ufrag = NULL;
 
       sdp_res = sdp_attr_get_ice_attribute(sdp_p->dest_sdp, media->level, 0,
         SDP_ATTR_ICE_PWD, 1, &pwd);
       if (sdp_res != SDP_SUCCESS)
--- a/media/webrtc/signaling/src/sipcc/core/gsm/h/fsm.h
+++ b/media/webrtc/signaling/src/sipcc/core/gsm/h/fsm.h
@@ -203,16 +203,21 @@ typedef struct fsmdef_media_t_ {
     int candidate_ct;
 
     /*
      * rtcp-mux indicates media stream is muxed for RTP and RTCP
      */
     boolean        rtcp_mux;
 
     /*
+     * The value of the a=setup line
+     */
+    sdp_setup_type_e setup;
+
+    /*
      * port number used in m= data channel line
      */
     uint16_t       local_datachannel_port;
     uint16_t       remote_datachannel_port;
 
     /*
      * Data Channel properties
      */
--- a/media/webrtc/signaling/src/sipcc/core/gsm/lsm.c
+++ b/media/webrtc/signaling/src/sipcc/core/gsm/lsm.c
@@ -1001,16 +1001,17 @@ lsm_rx_start (lsm_lcb_t *lcb, const char
                     ret_val = vcmRxStartICE(media->cap_index, group_id, media->refid,
                     media->level,
                     pc_stream_id,
                     pc_track_id,
                     lsm_get_ms_ui_call_handle(dcb->line, call_id, CC_NO_CALL_ID),
                     dcb->peerconnection,
                     media->num_payloads,
                     media->payloads,
+                    media->setup,
                     FSM_NEGOTIATED_CRYPTO_DIGEST_ALGORITHM(media),
                     FSM_NEGOTIATED_CRYPTO_DIGEST(media),
                     &attrs);
                 } else if (!sdpmode) {
                     if (media->payloads == NULL) {
                         LSM_ERR_MSG(get_debug_string(DEBUG_INPUT_NULL), fname1);
                         return;
                     }
@@ -1271,16 +1272,17 @@ lsm_tx_start (lsm_lcb_t *lcb, const char
                   /* TODO(emannion): his perhaps needs some error checking for validity.
                      See gsmsdp_get_media_cap_entry_by_index. */
                   dcb->media_cap_tbl->cap[media->cap_index].pc_stream,
                   dcb->media_cap_tbl->cap[media->cap_index].pc_track,
                   lsm_get_ms_ui_call_handle(dcb->line, call_id, CC_NO_CALL_ID),
                   dcb->peerconnection,
                   media->payloads,
                   (short)dscp,
+                  media->setup,
                   FSM_NEGOTIATED_CRYPTO_DIGEST_ALGORITHM(media),
                   FSM_NEGOTIATED_CRYPTO_DIGEST(media),
                   &attrs) == -1)
               {
                 LSM_DEBUG(DEB_L_C_F_PREFIX"%s: vcmTxStartICE failed",
                   DEB_L_C_F_PREFIX_ARGS(LSM, dcb->line, dcb->call_id, fname1), fname);
                 dcb->dsp_out_of_resources = TRUE;
                 return;
--- a/media/webrtc/signaling/src/sipcc/core/includes/config.h
+++ b/media/webrtc/signaling/src/sipcc/core/includes/config.h
@@ -174,17 +174,17 @@ static const unsigned char gCallWaiting 
 static const int gDeviceSecurityMode = 1;
 static const int gCcm2_sip_port = 5060;
 static const int gCcm3_sip_port = 5060;
 static const boolean gCcm1_isvalid = TRUE;
 static const int gDscpCallControl = 1;
 static const int gSpeakerEnabled = 1;
 static const char gExternalNumberMask[] = "";
 static const char gVersion[] = "0.1";
-static const boolean gRTCPMUX = FALSE;
+static const boolean gRTCPMUX = TRUE;
 static boolean gRTPSAVPF = TRUE;           /* TRUE = RTP/SAVPF , FALSE = RTP/SAVP */
 static const boolean gMAXAVBITRATE = FALSE;      /* Following six are OPUS fmtp options */
 static const boolean gMAXCODEDAUDIOBW = FALSE;
 static const boolean gUSEDTX = FALSE;
 static const boolean gSTEREO = FALSE;
 static const boolean gUSEINBANDFEC = FALSE;
 static const boolean gCBR = FALSE;
 static const boolean gMAXPTIME = FALSE;
--- a/media/webrtc/signaling/src/sipcc/core/sdp/sdp.h
+++ b/media/webrtc/signaling/src/sipcc/core/sdp/sdp.h
@@ -514,16 +514,24 @@ typedef enum {
     SDP_RTCP_FB_CCM_FIR = 0,
     SDP_RTCP_FB_CCM_TMMBR,
     SDP_RTCP_FB_CCM_TSTR,
     SDP_RTCP_FB_CCM_VBCM,
     SDP_MAX_RTCP_FB_CCM,
     SDP_RTCP_FB_CCM_UNKNOWN
 } sdp_rtcp_fb_ccm_type_e;
 
+typedef enum {
+    SDP_CONNECTION_NOT_FOUND = -1,
+    SDP_CONNECTION_NEW = 0,
+    SDP_CONNECTION_EXISTING,
+    SDP_MAX_CONNECTION,
+    SDP_CONNECTION_UNKNOWN
+} sdp_connection_type_e;
+
 #define SDP_RTCP_FB_NACK_TO_BITMAP(type) (1 << (type))
 #define SDP_RTCP_FB_ACK_TO_BITMAP(type)  (1 << (SDP_MAX_RTCP_FB_NACK + (type)))
 #define SDP_RTCP_FB_CCM_TO_BITMAP(type)  (1 << (SDP_MAX_RTCP_FB_NACK + \
                                                 SDP_MAX_RTCP_FB_ACK + (type)))
 
 /*
  * sdp_srtp_fec_order_t
  *  This type defines the order in which to perform FEC
@@ -1012,16 +1020,18 @@ typedef struct sdp_attr {
         sdp_rtr_t             rtr;
         sdp_comediadir_t      comediadir;
         sdp_srtp_crypto_context_t srtp_context;
         sdp_mptime_t          mptime;
         sdp_stream_data_t     stream_data;
         char                  unknown[SDP_MAX_STRING_LEN+1];
         sdp_source_filter_t   source_filter;
         sdp_fmtp_fb_t         rtcp_fb;
+        sdp_setup_type_e      setup;
+        sdp_connection_type_e connection;
     } attr;
     struct sdp_attr          *next_p;
 } sdp_attr_t;
 
 typedef struct sdp_srtp_crypto_suite_list_ {
     sdp_srtp_crypto_suite_t crypto_suite_val;
     char * crypto_suite_str;
     unsigned char key_size_bytes;
@@ -2064,16 +2074,33 @@ sdp_result_e
 sdp_attr_get_rtcp_mux_attribute (void *sdp_ptr, u16 level,
                                   u8 cap_num, sdp_attr_e sdp_attr, u16 inst_num,
                                   tinybool *rtcp_mux);
 
 sdp_result_e
 sdp_attr_set_rtcp_mux_attribute(void *sdp_ptr, u16 level,
                               u8 cap_num, sdp_attr_e sdp_attr, u16 inst_num, const tinybool rtcp_mux);
 
+
+sdp_result_e
+sdp_attr_get_setup_attribute (void *sdp_ptr, u16 level,
+    u8 cap_num, u16 inst_num, sdp_setup_type_e *setup_type);
+
+sdp_result_e
+sdp_attr_set_setup_attribute(void *sdp_ptr, u16 level,
+    u8 cap_num, u16 inst_num, sdp_setup_type_e setup_type);
+
+sdp_result_e
+sdp_attr_get_connection_attribute (void *sdp_ptr, u16 level,
+    u8 cap_num, u16 inst_num, sdp_connection_type_e *connection_type);
+
+sdp_result_e
+sdp_attr_set_connection_attribute(void *sdp_ptr, u16 level,
+    u8 cap_num, u16 inst_num, sdp_connection_type_e connection_type);
+
 sdp_result_e
 sdp_attr_get_dtls_fingerprint_attribute (void *sdp_ptr, u16 level,
                                   u8 cap_num, sdp_attr_e sdp_attr, u16 inst_num,
                                   char **out);
 
 sdp_result_e
 sdp_attr_set_dtls_fingerprint_attribute(void *sdp_ptr, u16 level,
                               u8 cap_num, sdp_attr_e sdp_attr, u16 inst_num, const char *dtls_fingerprint);
--- a/media/webrtc/signaling/src/sipcc/core/sdp/sdp_attr.c
+++ b/media/webrtc/signaling/src/sipcc/core/sdp/sdp_attr.c
@@ -4981,8 +4981,132 @@ sdp_result_e sdp_parse_attr_rtcp_fb (sdp
 
     /* Just store the rest of the line in "extra" -- this will return
        a failure result if there is no more text, but that's fine. */
     ptr = sdp_getnextstrtok(ptr, rtcp_fb_p->extra,
                             sizeof(rtcp_fb_p->extra), "\r\n", &result);
 
     return SDP_SUCCESS;
 }
+
+sdp_result_e sdp_build_attr_setup(sdp_t *sdp_p,
+                                  sdp_attr_t *attr_p,
+                                  flex_string *fs)
+{
+    switch (attr_p->attr.setup) {
+    case SDP_SETUP_ACTIVE:
+    case SDP_SETUP_PASSIVE:
+    case SDP_SETUP_ACTPASS:
+    case SDP_SETUP_HOLDCONN:
+        flex_string_sprintf(fs, "a=%s:%s\r\n",
+            sdp_attr[attr_p->type].name,
+            sdp_setup_type_val[attr_p->attr.setup].name);
+        break;
+    default:
+        CSFLogError(logTag, "%s Error: Invalid setup enum (%d)",
+                    sdp_p->debug_str, attr_p->attr.setup);
+        return SDP_FAILURE;
+    }
+
+    return SDP_SUCCESS;
+}
+
+sdp_result_e sdp_parse_attr_setup(sdp_t *sdp_p,
+                                   sdp_attr_t *attr_p,
+                                   const char *ptr)
+{
+    int i = find_token_enum("setup attribute", sdp_p, &ptr,
+        sdp_setup_type_val,
+        SDP_MAX_SETUP, SDP_SETUP_UNKNOWN);
+
+    if (i < 0) {
+        sdp_parse_error(sdp_p->peerconnection,
+          "%s Warning: could not parse setup attribute",
+          sdp_p->debug_str);
+        sdp_p->conf_p->num_invalid_param++;
+        return SDP_INVALID_PARAMETER;
+    }
+
+    attr_p->attr.setup = (sdp_setup_type_e) i;
+
+    switch (attr_p->attr.setup) {
+    case SDP_SETUP_ACTIVE:
+    case SDP_SETUP_PASSIVE:
+    case SDP_SETUP_ACTPASS:
+    case SDP_SETUP_HOLDCONN:
+        /* All these values are OK */
+        break;
+    case SDP_SETUP_UNKNOWN:
+        sdp_parse_error(sdp_p->peerconnection,
+            "%s Warning: Unknown setup attribute",
+            sdp_p->debug_str);
+        return SDP_INVALID_PARAMETER;
+        break;
+    default:
+        /* This is an internal error, not a parsing error */
+        CSFLogError(logTag, "%s Error: Invalid setup enum (%d)",
+                    sdp_p->debug_str, attr_p->attr.setup);
+        return SDP_FAILURE;
+        break;
+    }
+
+    return SDP_SUCCESS;
+}
+
+sdp_result_e sdp_build_attr_connection(sdp_t *sdp_p,
+                                       sdp_attr_t *attr_p,
+                                       flex_string *fs)
+{
+    switch (attr_p->attr.connection) {
+    case SDP_CONNECTION_NEW:
+    case SDP_CONNECTION_EXISTING:
+        flex_string_sprintf(fs, "a=%s:%s\r\n",
+            sdp_attr[attr_p->type].name,
+            sdp_connection_type_val[attr_p->attr.connection].name);
+        break;
+    default:
+        CSFLogError(logTag, "%s Error: Invalid connection enum (%d)",
+                    sdp_p->debug_str, attr_p->attr.connection);
+        return SDP_FAILURE;
+    }
+
+    return SDP_SUCCESS;
+}
+
+sdp_result_e sdp_parse_attr_connection(sdp_t *sdp_p,
+                                       sdp_attr_t *attr_p,
+                                       const char *ptr)
+{
+    int i = find_token_enum("connection attribute", sdp_p, &ptr,
+        sdp_connection_type_val,
+        SDP_MAX_CONNECTION, SDP_CONNECTION_UNKNOWN);
+
+    if (i < 0) {
+        sdp_parse_error(sdp_p->peerconnection,
+          "%s Warning: could not parse connection attribute",
+          sdp_p->debug_str);
+        sdp_p->conf_p->num_invalid_param++;
+        return SDP_INVALID_PARAMETER;
+    }
+
+    attr_p->attr.connection = (sdp_connection_type_e) i;
+
+    switch (attr_p->attr.connection) {
+    case SDP_CONNECTION_NEW:
+    case SDP_CONNECTION_EXISTING:
+        /* All these values are OK */
+        break;
+    case SDP_CONNECTION_UNKNOWN:
+        sdp_parse_error(sdp_p->peerconnection,
+            "%s Warning: Unknown connection attribute",
+            sdp_p->debug_str);
+        return SDP_INVALID_PARAMETER;
+        break;
+    default:
+        /* This is an internal error, not a parsing error */
+        CSFLogError(logTag, "%s Error: Invalid connection enum (%d)",
+                    sdp_p->debug_str, attr_p->attr.connection);
+        return SDP_FAILURE;
+        break;
+    }
+
+    return SDP_SUCCESS;
+}
--- a/media/webrtc/signaling/src/sipcc/core/sdp/sdp_attr_access.c
+++ b/media/webrtc/signaling/src/sipcc/core/sdp/sdp_attr_access.c
@@ -4079,16 +4079,173 @@ sdp_result_e sdp_attr_set_rtcp_mux_attri
         sdp_p->conf_p->num_invalid_param++;
         return (SDP_INVALID_PARAMETER);
     }
 
     attr_p->attr.boolean_val = rtcp_mux;
     return (SDP_SUCCESS);
 }
 
+
+/* Function:    sdp_attr_get_setup_attribute
+ * Description: Returns the value of a setup attribute at a given level
+ *
+ * Parameters:  sdp_ptr     The SDP handle returned by sdp_init_description.
+ *              level       The level to check for the attribute.
+ *              cap_num     The capability number associated with the
+ *                          attribute if any.  If none, should be zero.
+ *              inst_num    The attribute instance number to check.
+ *              setup_type  Returns sdp_setup_type_e enum
+ * Returns:
+ *              SDP_SUCCESS           Attribute param was set successfully.
+ *              SDP_INVALID_SDP_PTR   SDP pointer invalid
+ *              SDP_INVALID_PARAMETER Specified attribute is not defined.
+ */
+sdp_result_e sdp_attr_get_setup_attribute (void *sdp_ptr, u16 level,
+    u8 cap_num, u16 inst_num, sdp_setup_type_e *setup_type)
+{
+    sdp_t       *sdp_p = (sdp_t *)sdp_ptr;
+    sdp_attr_t  *attr_p;
+
+    if (!sdp_verify_sdp_ptr(sdp_p)) {
+        return SDP_INVALID_SDP_PTR;
+    }
+
+    attr_p = sdp_find_attr(sdp_p, level, cap_num, SDP_ATTR_SETUP, inst_num);
+    if (!attr_p) {
+        if (sdp_p->debug_flag[SDP_DEBUG_ERRORS]) {
+            CSFLogError(logTag,
+                "%s setup attribute, level %u instance %u not found.",
+                sdp_p->debug_str, level, inst_num);
+        }
+        sdp_p->conf_p->num_invalid_param++;
+        return SDP_INVALID_PARAMETER;
+    }
+
+    *setup_type = attr_p->attr.setup;
+    return SDP_SUCCESS;
+}
+
+/* Function:    sdp_attr_set_setup_attribute
+ * Description: Sets the value of a setup attribute parameter
+ *
+ * Parameters:  sdp_ptr        The SDP handle returned by sdp_init_description.
+ *              level          The level to set the attribute.
+ *              cap_num        The capability number associated with the
+ *                             attribute if any.  If none, should be zero.
+ *              inst_num       The attribute instance number to check.
+ *              setup_type     setup attribute value to set
+ * Returns:     SDP_SUCCESS            Attribute param was set successfully.
+ *              SDP_INVALID_SDP_PTR    SDP ptr invalid
+ *              SDP_INVALID_PARAMETER  Specified attribute is not defined.
+ */
+sdp_result_e
+sdp_attr_set_setup_attribute(void *sdp_ptr, u16 level,
+    u8 cap_num, u16 inst_num, sdp_setup_type_e setup_type)
+{
+    sdp_t       *sdp_p = (sdp_t *)sdp_ptr;
+    sdp_attr_t  *attr_p;
+
+    if (!sdp_verify_sdp_ptr(sdp_p)) {
+        return SDP_INVALID_SDP_PTR;
+    }
+
+    attr_p = sdp_find_attr(sdp_p, level, cap_num, SDP_ATTR_SETUP, inst_num);
+    if (!attr_p) {
+        if (sdp_p->debug_flag[SDP_DEBUG_ERRORS]) {
+            CSFLogError(logTag, "%s setup attribute, level %u instance %u "
+                      "not found.", sdp_p->debug_str, level, inst_num);
+        }
+        sdp_p->conf_p->num_invalid_param++;
+        return SDP_INVALID_PARAMETER;
+    }
+
+    attr_p->attr.setup = setup_type;
+    return SDP_SUCCESS;
+}
+
+/* Function:    sdp_attr_get_connection_attribute
+ * Description: Returns the value of a connection attribute at a given level
+ *
+ * Parameters:  sdp_ptr     The SDP handle returned by sdp_init_description.
+ *              level       The level to check for the attribute.
+ *              cap_num     The capability number associated with the
+ *                          attribute if any.  If none, should be zero.
+ *              inst_num    The attribute instance number to check.
+ *              connection_type  Returns sdp_connection_type_e enum
+ * Returns:
+ *              SDP_SUCCESS           Attribute param was set successfully.
+ *              SDP_INVALID_SDP_PTR   SDP pointer invalid
+ *              SDP_INVALID_PARAMETER Specified attribute is not defined.
+ */
+sdp_result_e sdp_attr_get_connection_attribute (void *sdp_ptr, u16 level,
+    u8 cap_num, u16 inst_num, sdp_connection_type_e *connection_type)
+{
+    sdp_t       *sdp_p = (sdp_t *)sdp_ptr;
+    sdp_attr_t  *attr_p;
+
+    if (!sdp_verify_sdp_ptr(sdp_p)) {
+        return SDP_INVALID_SDP_PTR;
+    }
+
+    attr_p = sdp_find_attr(sdp_p, level, cap_num, SDP_ATTR_CONNECTION,
+        inst_num);
+    if (!attr_p) {
+        if (sdp_p->debug_flag[SDP_DEBUG_ERRORS]) {
+            CSFLogError(logTag,
+                "%s setup attribute, level %u instance %u not found.",
+                sdp_p->debug_str, level, inst_num);
+        }
+        sdp_p->conf_p->num_invalid_param++;
+        return SDP_INVALID_PARAMETER;
+    }
+
+    *connection_type = attr_p->attr.connection;
+    return SDP_SUCCESS;
+}
+
+/* Function:    sdp_attr_set_connection_attribute
+ * Description: Sets the value of a connection attribute parameter
+ *
+ * Parameters:  sdp_ptr        The SDP handle returned by sdp_init_description.
+ *              level          The level to set the attribute.
+ *              cap_num        The capability number associated with the
+ *                             attribute if any.  If none, should be zero.
+ *              inst_num       The attribute instance number to check.
+ *              connection_type     connection attribute value to set
+ * Returns:     SDP_SUCCESS            Attribute param was set successfully.
+ *              SDP_INVALID_SDP_PTR    SDP ptr invalid
+ *              SDP_INVALID_PARAMETER  Specified attribute is not defined.
+ */
+sdp_result_e
+sdp_attr_set_connection_attribute(void *sdp_ptr, u16 level,
+    u8 cap_num, u16 inst_num, sdp_connection_type_e connection_type)
+{
+    sdp_t       *sdp_p = (sdp_t *)sdp_ptr;
+    sdp_attr_t  *attr_p;
+
+    if (!sdp_verify_sdp_ptr(sdp_p)) {
+        return SDP_INVALID_SDP_PTR;
+    }
+
+    attr_p = sdp_find_attr(sdp_p, level, cap_num, SDP_ATTR_CONNECTION,
+        inst_num);
+    if (!attr_p) {
+        if (sdp_p->debug_flag[SDP_DEBUG_ERRORS]) {
+            CSFLogError(logTag, "%s connection attribute, level %u instance %u "
+                      "not found.", sdp_p->debug_str, level, inst_num);
+        }
+        sdp_p->conf_p->num_invalid_param++;
+        return SDP_INVALID_PARAMETER;
+    }
+
+    attr_p->attr.connection = connection_type;
+    return SDP_SUCCESS;
+}
+
 /* Function:    sdp_attr_get_dtls_fingerprint_attribute
  * Description: Returns the value of dtls fingerprint attribute at a given level
  *
  * Parameters:  sdp_ptr     The SDP handle returned by sdp_init_description.
  *              level       The level to check for the attribute.
  *              cap_num     The capability number associated with the
  *                          attribute if any.  If none, should be zero.
  *              inst_num    The attribute instance number to check.
--- a/media/webrtc/signaling/src/sipcc/core/sdp/sdp_main.c
+++ b/media/webrtc/signaling/src/sipcc/core/sdp/sdp_main.c
@@ -164,17 +164,21 @@ const sdp_attrarray_t sdp_attr[SDP_MAX_A
       sdp_parse_attr_ice_attr, sdp_build_attr_ice_attr},
     {"rtcp-mux", sizeof("rtcp-mux"),
       sdp_parse_attr_rtcp_mux_attr, sdp_build_attr_rtcp_mux_attr},
     {"fingerprint", sizeof("fingerprint"),
       sdp_parse_attr_fingerprint_attr, sdp_build_attr_simple_string},
     {"maxptime", sizeof("maxptime"),
       sdp_parse_attr_simple_u32, sdp_build_attr_simple_u32},
     {"rtcp-fb", sizeof("rtcp-fb"),
-      sdp_parse_attr_rtcp_fb, sdp_build_attr_rtcp_fb}
+      sdp_parse_attr_rtcp_fb, sdp_build_attr_rtcp_fb},
+    {"setup", sizeof("setup"),
+      sdp_parse_attr_setup, sdp_build_attr_setup},
+    {"connection", sizeof("connection"),
+      sdp_parse_attr_connection, sdp_build_attr_connection},
 };
 
 /* Note: These *must* be in the same order as the enum types. */
 const sdp_namearray_t sdp_media[SDP_MAX_MEDIA_TYPES] =
 {
     {"audio",        sizeof("audio")},
     {"video",        sizeof("video")},
     {"application",  sizeof("application")},
@@ -478,16 +482,31 @@ const sdp_namearray_t sdp_rtcp_fb_ack_ty
 const sdp_namearray_t sdp_rtcp_fb_ccm_type_val[SDP_MAX_RTCP_FB_CCM] =
 {
     SDP_NAME("fir"),
     SDP_NAME("tmmbr"),
     SDP_NAME("tstr"),
     SDP_NAME("vbcm")
 };
 
+/* Maintain the same order as defined in typedef sdp_setup_type_e */
+const sdp_namearray_t sdp_setup_type_val[SDP_MAX_SETUP] =
+{
+    SDP_NAME("active"),
+    SDP_NAME("passive"),
+    SDP_NAME("actpass"),
+    SDP_NAME("holdconn")
+};
+
+/* Maintain the same order as defined in typedef sdp_connection_type_e */
+const sdp_namearray_t sdp_connection_type_val[SDP_MAX_CONNECTION] =
+{
+    SDP_NAME("new"),
+    SDP_NAME("existing")
+};
 
 /*  Maintain same order as defined in typedef sdp_srtp_crypto_suite_t */
 const sdp_srtp_crypto_suite_list sdp_srtp_crypto_suite_array[SDP_SRTP_MAX_NUM_CRYPTO_SUITES] =
 {
   {SDP_SRTP_UNKNOWN_CRYPTO_SUITE, UNKNOWN_CRYPTO_SUITE, 0, 0},
   {SDP_SRTP_AES_CM_128_HMAC_SHA1_32, AES_CM_128_HMAC_SHA1_32,
       SDP_SRTP_AES_CM_128_HMAC_SHA1_32_KEY_BYTES,
       SDP_SRTP_AES_CM_128_HMAC_SHA1_32_SALT_BYTES},
--- a/media/webrtc/signaling/src/sipcc/core/sdp/sdp_private.h
+++ b/media/webrtc/signaling/src/sipcc/core/sdp/sdp_private.h
@@ -32,16 +32,18 @@ extern const sdp_namearray_t sdp_srtp_co
 extern const sdp_namearray_t sdp_bw_modifier_val[];
 extern const sdp_namearray_t sdp_group_attr_val[];
 extern const sdp_namearray_t sdp_src_filter_mode_val[];
 extern const sdp_namearray_t sdp_rtcp_unicast_mode_val[];
 extern const sdp_namearray_t sdp_rtcp_fb_type_val[];
 extern const sdp_namearray_t sdp_rtcp_fb_nack_type_val[];
 extern const sdp_namearray_t sdp_rtcp_fb_ack_type_val[];
 extern const sdp_namearray_t sdp_rtcp_fb_ccm_type_val[];
+extern const sdp_namearray_t sdp_setup_type_val[];
+extern const sdp_namearray_t sdp_connection_type_val[];
 
 
 extern const  sdp_srtp_crypto_suite_list sdp_srtp_crypto_suite_array[];
 /* Function Prototypes */
 
 /* sdp_access.c */
 extern sdp_mca_t *sdp_find_media_level(sdp_t *sdp_p, u16 level);
 extern sdp_bw_data_t* sdp_find_bw_line (void *sdp_ptr, u16 level, u16 inst_num);
@@ -144,16 +146,28 @@ extern sdp_result_e sdp_build_attr_srtpc
                                                sdp_attr_t *attr_p,
                                                flex_string *fs);
 extern sdp_result_e sdp_parse_attr_rtcp_fb(sdp_t *sdp_p,
                                            sdp_attr_t *attr_p,
                                            const char *ptr);
 extern sdp_result_e sdp_build_attr_rtcp_fb(sdp_t *sdp_p,
                                            sdp_attr_t *attr_p,
                                            flex_string *fs);
+extern sdp_result_e sdp_parse_attr_setup(sdp_t *sdp_p,
+                                         sdp_attr_t *attr_p,
+                                         const char *ptr);
+extern sdp_result_e sdp_build_attr_setup(sdp_t *sdp_p,
+                                         sdp_attr_t *attr_p,
+                                         flex_string *fs);
+extern sdp_result_e sdp_parse_attr_connection(sdp_t *sdp_p,
+                                              sdp_attr_t *attr_p,
+                                              const char *ptr);
+extern sdp_result_e sdp_build_attr_connection(sdp_t *sdp_p,
+                                              sdp_attr_t *attr_p,
+                                              flex_string *fs);
 extern sdp_result_e sdp_parse_attr_mptime(
     sdp_t *sdp_p, sdp_attr_t *attr_p, const char *ptr);
 extern sdp_result_e sdp_build_attr_mptime(
     sdp_t *sdp_p, sdp_attr_t *attr_p, flex_string *fs);
 
 extern sdp_result_e sdp_parse_attr_x_sidin(
     sdp_t *sdp_p, sdp_attr_t *attr_p, const char *ptr);
 extern sdp_result_e sdp_build_attr_x_sidin(
--- a/media/webrtc/signaling/src/sipcc/include/ccsdp.h
+++ b/media/webrtc/signaling/src/sipcc/include/ccsdp.h
@@ -237,20 +237,33 @@ typedef enum {
     SDP_ATTR_FRAMERATE,
     SDP_ATTR_ICE_CANDIDATE,
     SDP_ATTR_ICE_UFRAG,
     SDP_ATTR_ICE_PWD,
     SDP_ATTR_RTCP_MUX,
     SDP_ATTR_DTLS_FINGERPRINT,
     SDP_ATTR_MAXPTIME,
     SDP_ATTR_RTCP_FB,  /* RFC 4585 */
+    SDP_ATTR_SETUP,
+    SDP_ATTR_CONNECTION,
     SDP_MAX_ATTR_TYPES,
     SDP_ATTR_INVALID
 } sdp_attr_e;
 
+/* This is here so that it can be used in the VcmSIPCCBinding interface */
+typedef enum {
+    SDP_SETUP_NOT_FOUND = -1,
+    SDP_SETUP_ACTIVE = 0,
+    SDP_SETUP_PASSIVE,
+    SDP_SETUP_ACTPASS,
+    SDP_SETUP_HOLDCONN,
+    SDP_MAX_SETUP,
+    SDP_SETUP_UNKNOWN
+} sdp_setup_type_e;
+
 /**
  * Gets the value of the fmtp attribute- parameter-sets parameter for H.264 codec
  *
  * @param[in]  sdp_handle     The SDP handle
  * @param[in]  level       The level to check for the attribute.
  * @param[in]  cap_num     The capability number associated with the attribute if any.  If none, should be zero.
  * @param[in]  inst_num    The attribute instance number to check.
  *
--- a/media/webrtc/signaling/src/sipcc/include/vcm.h
+++ b/media/webrtc/signaling/src/sipcc/include/vcm.h
@@ -580,16 +580,17 @@ int vcmRxStart(cc_mcapid_t mcap_id,
  *  @param[in]   stream_id    - stream id of the given media type.
  *  @param[in]   level        - the m-line index
  *  @param[in]   pc_stream_id - the media stream index (from PC.addStream())
  *  @param[in]   pc_track_id  - the track within the media stream
  *  @param[in]   call_handle  - call handle
  *  @param[in]   peerconnection - the peerconnection in use
  *  @param[in]   num_payloads  - number of codecs negotiated
  *  @param[in]   payloads      - list of negotiated codec details
+ *  @param[in]   setup_t       - whether playing client or server role
  *  @param[in]   fingerprint_alg - the DTLS fingerprint algorithm
  *  @param[in]   fingerprint  - the DTLS fingerprint
  *  @param[in]   attrs        - media attributes
  *
  *  Returns: zero(0) for success; otherwise, ERROR for failure
  *
  */
 
@@ -598,16 +599,17 @@ int vcmRxStartICE(cc_mcapid_t mcap_id,
         cc_streamid_t stream_id,
         int level,
         int pc_stream_id,
         int pc_track_id,
         cc_call_handle_t  call_handle,
         const char *peerconnection,
         int num_payloads,
         const vcm_payload_info_t* payloads,
+        sdp_setup_type_e setup_type,
         const char *fingerprint_alg,
         const char *fingerprint,
         vcm_mediaAttrs_t *attrs);
 
 /**
  *  start tx stream
  *  Note: For video calls, for a given call handle there will be
  *        two media lines and the corresponding group_id/stream_id pair.
@@ -658,16 +660,17 @@ int vcmTxStart(cc_mcapid_t mcap_id,
  *  @param[in]   stream_id    - stream id of the given media type.
  *  @param[in]   level        - the m-line index
  *  @param[in]   pc_stream_id - the media stream index (from PC.addStream())
  *  @param[in]   pc_track_id  - the track within the media stream
  *  @param[in]   call_handle  - call handle
  *  @param[in]   peerconnection - the peerconnection in use
  *  @param[in]   payload      - payload information
  *  @param[in]   tos          - bit marking
+ *  @param[in]   setup_type   - whether playing client or server role
  *  @param[in]   fingerprint_alg - the DTLS fingerprint algorithm
  *  @param[in]   fingerprint  - the DTLS fingerprint
  *  @param[in]   attrs        - media attributes
  *
  *  Returns: zero(0) for success; otherwise, ERROR for failure
  *
  */
 
@@ -676,16 +679,17 @@ int vcmTxStart(cc_mcapid_t mcap_id,
         cc_streamid_t stream_id,
         int level,
         int pc_stream_id,
         int pc_track_id,
         cc_call_handle_t  call_handle,
         const char *peerconnection,
         const vcm_payload_info_t *payload,
         short tos,
+        sdp_setup_type_e setup_type,
         const char *fingerprint_alg,
         const char *fingerprint,
         vcm_mediaAttrs_t *attrs);
 
 
   short vcmGetDtlsIdentity(const char *peerconnection,
         char *digest_alg,
         size_t max_digest_alg_len,
@@ -1030,16 +1034,24 @@ int vcmGetILBCMode();
  * vcmOnSdpParseError
  *
  * This method is called for each parsing error of SDP.  It does not necessarily
  * mean the SDP read was fatal and can be called many times for the same SDP.
  *
  */
 int vcmOnSdpParseError(const char *peercconnection, const char *message);
 
+/**
+ * vcmDisableRtcpComponent
+ *
+ * If we are doing rtcp-mux we need to disable component number 2 in the ICE
+ * layer.  Otherwise we will wait for it to connect when it is unused
+ */
+int vcmDisableRtcpComponent(const char *peerconnection, int level);
+
 //Using C++ for gips. This is the end of extern "C" above.
 #ifdef __cplusplus
 }
 #endif
 
 
 
 
--- a/media/webrtc/signaling/test/signaling_unittests.cpp
+++ b/media/webrtc/signaling/test/signaling_unittests.cpp
@@ -32,17 +32,17 @@
 #include "nricectx.h"
 #include "mozilla/SyncRunnable.h"
 
 #include "mtransport_test_utils.h"
 MtransportTestUtils *test_utils;
 nsCOMPtr<nsIThread> gThread;
 
 static int kDefaultTimeout = 5000;
-static bool fRtcpMux = false;
+static bool fRtcpMux = true;
 
 static std::string callerName = "caller";
 static std::string calleeName = "callee";
 
 namespace test {
 
 std::string indent(const std::string &s, int width = 4) {
   std::string prefix;
@@ -2467,16 +2467,362 @@ TEST_F(SignalingTest, FullCallAudioNoMux
   a2_.CheckMediaPipeline(0, 1, 0);
 
   // Now check video mux.
   a2_.CheckMediaPipeline(0, 2, fRtcpMux ?
     PIPELINE_RTCP_MUX | PIPELINE_VIDEO :
     PIPELINE_VIDEO);
 }
 
+// In this test we will change the offer SDP's a=setup value
+// from actpass to passive.  This will make the answer do active.
+TEST_F(SignalingTest, AudioCallForceDtlsRoles)
+{
+  sipcc::MediaConstraints constraints;
+  size_t match;
+
+  a1_.CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO);
+
+  // By default the offer should give actpass
+  std::string offer(a1_.offer());
+  match = offer.find("\r\na=setup:actpass");
+  ASSERT_NE(match, std::string::npos);
+  // Now replace the actpass with passive so that the answer will
+  // return active
+  offer.replace(match, strlen("\r\na=setup:actpass"),
+    "\r\na=setup:passive");
+  std::cout << "Modified SDP " << std::endl
+            << indent(offer) << std::endl;
+
+  a1_.SetLocal(TestObserver::OFFER, offer.c_str(), false);
+  a2_.SetRemote(TestObserver::OFFER, offer.c_str(), false);
+  a2_.CreateAnswer(constraints, offer.c_str(), OFFER_AUDIO | ANSWER_AUDIO);
+
+  // Now the answer should contain a=setup:active
+  std::string answer(a2_.answer());
+  match = answer.find("\r\na=setup:active");
+  ASSERT_NE(match, std::string::npos);
+
+  // This should setup the DTLS with the same roles
+  // as the regular tests above.
+  a2_.SetLocal(TestObserver::ANSWER, a2_.answer(), false);
+  a1_.SetRemote(TestObserver::ANSWER, a2_.answer(), false);
+
+  ASSERT_TRUE_WAIT(a1_.IceCompleted() == true, kDefaultTimeout);
+  ASSERT_TRUE_WAIT(a2_.IceCompleted() == true, kDefaultTimeout);
+
+  // Wait for some data to get written
+  ASSERT_TRUE_WAIT(a1_.GetPacketsSent(0) >= 40 &&
+                   a2_.GetPacketsReceived(0) >= 40, kDefaultTimeout * 2);
+
+  a1_.CloseSendStreams();
+  a2_.CloseReceiveStreams();
+
+  ASSERT_GE(a1_.GetPacketsSent(0), 40);
+  ASSERT_GE(a2_.GetPacketsReceived(0), 40);
+}
+
+// In this test we will change the offer SDP's a=setup value
+// from actpass to active.  This will make the answer do passive
+TEST_F(SignalingTest, AudioCallReverseDtlsRoles)
+{
+  sipcc::MediaConstraints constraints;
+  size_t match;
+
+  a1_.CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO);
+
+  // By default the offer should give actpass
+  std::string offer(a1_.offer());
+  match = offer.find("\r\na=setup:actpass");
+  ASSERT_NE(match, std::string::npos);
+  // Now replace the actpass with active so that the answer will
+  // return passive
+  offer.replace(match, strlen("\r\na=setup:actpass"),
+    "\r\na=setup:active");
+  std::cout << "Modified SDP " << std::endl
+            << indent(offer) << std::endl;
+
+  a1_.SetLocal(TestObserver::OFFER, offer.c_str(), false);
+  a2_.SetRemote(TestObserver::OFFER, offer.c_str(), false);
+  a2_.CreateAnswer(constraints, offer.c_str(), OFFER_AUDIO | ANSWER_AUDIO);
+
+  // Now the answer should contain a=setup:passive
+  std::string answer(a2_.answer());
+  match = answer.find("\r\na=setup:passive");
+  ASSERT_NE(match, std::string::npos);
+
+  // This should setup the DTLS with the opposite roles
+  // than the regular tests above.
+  a2_.SetLocal(TestObserver::ANSWER, a2_.answer(), false);
+  a1_.SetRemote(TestObserver::ANSWER, a2_.answer(), false);
+
+  ASSERT_TRUE_WAIT(a1_.IceCompleted() == true, kDefaultTimeout);
+  ASSERT_TRUE_WAIT(a2_.IceCompleted() == true, kDefaultTimeout);
+
+  // Wait for some data to get written
+  ASSERT_TRUE_WAIT(a1_.GetPacketsSent(0) >= 40 &&
+                   a2_.GetPacketsReceived(0) >= 40, kDefaultTimeout * 2);
+
+  a1_.CloseSendStreams();
+  a2_.CloseReceiveStreams();
+
+  ASSERT_GE(a1_.GetPacketsSent(0), 40);
+  ASSERT_GE(a2_.GetPacketsReceived(0), 40);
+}
+
+// In this test we will change the answer SDP's a=setup value
+// from active to passive.  This will make both sides do
+// active and should not connect.
+TEST_F(SignalingTest, AudioCallMismatchDtlsRoles)
+{
+  sipcc::MediaConstraints constraints;
+  size_t match;
+
+  a1_.CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO);
+
+  // By default the offer should give actpass
+  std::string offer(a1_.offer());
+  match = offer.find("\r\na=setup:actpass");
+  ASSERT_NE(match, std::string::npos);
+  a1_.SetLocal(TestObserver::OFFER, offer.c_str(), false);
+  a2_.SetRemote(TestObserver::OFFER, offer.c_str(), false);
+  a2_.CreateAnswer(constraints, offer.c_str(), OFFER_AUDIO | ANSWER_AUDIO);
+
+  // Now the answer should contain a=setup:active
+  std::string answer(a2_.answer());
+  match = answer.find("\r\na=setup:active");
+  ASSERT_NE(match, std::string::npos);
+
+  // Now replace the active with passive so that the offerer will
+  // also do active.
+  answer.replace(match, strlen("\r\na=setup:active"),
+    "\r\na=setup:passive");
+  std::cout << "Modified SDP " << std::endl
+            << indent(answer) << std::endl;
+
+  // This should setup the DTLS with both sides playing active
+  a2_.SetLocal(TestObserver::ANSWER, answer.c_str(), false);
+  a1_.SetRemote(TestObserver::ANSWER, answer.c_str(), false);
+
+  ASSERT_TRUE_WAIT(a1_.IceCompleted() == true, kDefaultTimeout);
+  ASSERT_TRUE_WAIT(a2_.IceCompleted() == true, kDefaultTimeout);
+
+  // Not using ASSERT_TRUE_WAIT here because we expect failure
+  PR_Sleep(kDefaultTimeout * 2); // Wait for some data to get written
+
+  a1_.CloseSendStreams();
+  a2_.CloseReceiveStreams();
+
+  ASSERT_GE(a1_.GetPacketsSent(0), 40);
+  // In this case we should receive nothing.
+  ASSERT_EQ(a2_.GetPacketsReceived(0), 0);
+}
+
+// In this test we will change the offer SDP's a=setup value
+// from actpass to garbage.  It should ignore the garbage value
+// and respond with setup:active
+TEST_F(SignalingTest, AudioCallGarbageSetup)
+{
+  sipcc::MediaConstraints constraints;
+  size_t match;
+
+  a1_.CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO);
+
+  // By default the offer should give actpass
+  std::string offer(a1_.offer());
+  match = offer.find("\r\na=setup:actpass");
+  ASSERT_NE(match, std::string::npos);
+  // Now replace the actpass with a garbage value
+  offer.replace(match, strlen("\r\na=setup:actpass"),
+    "\r\na=setup:G4rb4g3V4lu3");
+  std::cout << "Modified SDP " << std::endl
+            << indent(offer) << std::endl;
+
+  a1_.SetLocal(TestObserver::OFFER, offer.c_str(), false);
+  a2_.SetRemote(TestObserver::OFFER, offer.c_str(), false);
+  a2_.CreateAnswer(constraints, offer.c_str(), OFFER_AUDIO | ANSWER_AUDIO);
+
+  // Now the answer should contain a=setup:active
+  std::string answer(a2_.answer());
+  match = answer.find("\r\na=setup:active");
+  ASSERT_NE(match, std::string::npos);
+
+  // This should setup the DTLS with the same roles
+  // as the regular tests above.
+  a2_.SetLocal(TestObserver::ANSWER, a2_.answer(), false);
+  a1_.SetRemote(TestObserver::ANSWER, a2_.answer(), false);
+
+  ASSERT_TRUE_WAIT(a1_.IceCompleted() == true, kDefaultTimeout);
+  ASSERT_TRUE_WAIT(a2_.IceCompleted() == true, kDefaultTimeout);
+
+  // Wait for some data to get written
+  ASSERT_TRUE_WAIT(a1_.GetPacketsSent(0) >= 40 &&
+                   a2_.GetPacketsReceived(0) >= 40, kDefaultTimeout * 2);
+
+  a1_.CloseSendStreams();
+  a2_.CloseReceiveStreams();
+
+  ASSERT_GE(a1_.GetPacketsSent(0), 40);
+  ASSERT_GE(a2_.GetPacketsReceived(0), 40);
+}
+
+// In this test we will change the offer SDP's a=connection value
+// from new to garbage.  It should ignore the garbage value
+// and respond with connection:new
+TEST_F(SignalingTest, AudioCallGarbageConnection)
+{
+  sipcc::MediaConstraints constraints;
+  size_t match;
+
+  a1_.CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO);
+
+  // By default the offer should give connection:new
+  std::string offer(a1_.offer());
+  match = offer.find("\r\na=connection:new");
+  ASSERT_NE(match, std::string::npos);
+  // Now replace the 'new' with a garbage value
+  offer.replace(match, strlen("\r\na=connection:new"),
+    "\r\na=connection:G4rb4g3V4lu3");
+  std::cout << "Modified SDP " << std::endl
+            << indent(offer) << std::endl;
+
+  a1_.SetLocal(TestObserver::OFFER, offer.c_str(), false);
+  a2_.SetRemote(TestObserver::OFFER, offer.c_str(), false);
+  a2_.CreateAnswer(constraints, offer.c_str(), OFFER_AUDIO | ANSWER_AUDIO);
+
+  // Now the answer should contain a=connection:new
+  std::string answer(a2_.answer());
+  match = answer.find("\r\na=connection:new");
+  ASSERT_NE(match, std::string::npos);
+
+  // This should setup the DTLS with the same roles
+  // as the regular tests above.
+  a2_.SetLocal(TestObserver::ANSWER, a2_.answer(), false);
+  a1_.SetRemote(TestObserver::ANSWER, a2_.answer(), false);
+
+  ASSERT_TRUE_WAIT(a1_.IceCompleted() == true, kDefaultTimeout);
+  ASSERT_TRUE_WAIT(a2_.IceCompleted() == true, kDefaultTimeout);
+
+  // Wait for some data to get written
+  ASSERT_TRUE_WAIT(a1_.GetPacketsSent(0) >= 40 &&
+                   a2_.GetPacketsReceived(0) >= 40, kDefaultTimeout * 2);
+
+  a1_.CloseSendStreams();
+  a2_.CloseReceiveStreams();
+
+  ASSERT_GE(a1_.GetPacketsSent(0), 40);
+  ASSERT_GE(a2_.GetPacketsReceived(0), 40);
+}
+
+// In this test we will change the offer SDP to remove the
+// a=setup and a=connection lines.  Answer should respond with
+// a=setup:active and a=connection:new
+TEST_F(SignalingTest, AudioCallOfferNoSetupOrConnection)
+{
+  sipcc::MediaConstraints constraints;
+  size_t match;
+
+  a1_.CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO);
+
+  // By default the offer should give setup:actpass and connection:new
+  std::string offer(a1_.offer());
+  match = offer.find("\r\na=setup:actpass");
+  ASSERT_NE(match, std::string::npos);
+  // Remove the a=setup line
+  offer.replace(match, strlen("\r\na=setup:actpass"), "");
+  match = offer.find("\r\na=connection:new");
+  ASSERT_NE(match, std::string::npos);
+  // Remove the a=connection line
+  offer.replace(match, strlen("\r\na=connection:new"), "");
+  std::cout << "Modified SDP " << std::endl
+            << indent(offer) << std::endl;
+
+  a1_.SetLocal(TestObserver::OFFER, offer.c_str(), false);
+  a2_.SetRemote(TestObserver::OFFER, offer.c_str(), false);
+  a2_.CreateAnswer(constraints, offer.c_str(), OFFER_AUDIO | ANSWER_AUDIO);
+
+  // Now the answer should contain a=setup:active and a=connection:new
+  std::string answer(a2_.answer());
+  match = answer.find("\r\na=setup:active");
+  ASSERT_NE(match, std::string::npos);
+  match = answer.find("\r\na=connection:new");
+  ASSERT_NE(match, std::string::npos);
+
+  // This should setup the DTLS with the same roles
+  // as the regular tests above.
+  a2_.SetLocal(TestObserver::ANSWER, a2_.answer(), false);
+  a1_.SetRemote(TestObserver::ANSWER, a2_.answer(), false);
+
+  ASSERT_TRUE_WAIT(a1_.IceCompleted() == true, kDefaultTimeout);
+  ASSERT_TRUE_WAIT(a2_.IceCompleted() == true, kDefaultTimeout);
+
+  // Wait for some data to get written
+  ASSERT_TRUE_WAIT(a1_.GetPacketsSent(0) >= 40 &&
+                   a2_.GetPacketsReceived(0) >= 40, kDefaultTimeout * 2);
+
+  a1_.CloseSendStreams();
+  a2_.CloseReceiveStreams();
+
+  ASSERT_GE(a1_.GetPacketsSent(0), 40);
+  ASSERT_GE(a2_.GetPacketsReceived(0), 40);
+}
+
+// In this test we will change the answer SDP to remove the
+// a=setup and a=connection lines.  ICE should still connect
+// since active will be assumed.
+TEST_F(SignalingTest, AudioCallAnswerNoSetupOrConnection)
+{
+  sipcc::MediaConstraints constraints;
+  size_t match;
+
+  a1_.CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO);
+
+  // By default the offer should give setup:actpass and connection:new
+  std::string offer(a1_.offer());
+  match = offer.find("\r\na=setup:actpass");
+  ASSERT_NE(match, std::string::npos);
+  match = offer.find("\r\na=connection:new");
+  ASSERT_NE(match, std::string::npos);
+
+  a1_.SetLocal(TestObserver::OFFER, offer.c_str(), false);
+  a2_.SetRemote(TestObserver::OFFER, offer.c_str(), false);
+  a2_.CreateAnswer(constraints, offer.c_str(), OFFER_AUDIO | ANSWER_AUDIO);
+
+  // Now the answer should contain a=setup:active and a=connection:new
+  std::string answer(a2_.answer());
+  match = answer.find("\r\na=setup:active");
+  ASSERT_NE(match, std::string::npos);
+  // Remove the a=setup line
+  answer.replace(match, strlen("\r\na=setup:active"), "");
+  match = answer.find("\r\na=connection:new");
+  ASSERT_NE(match, std::string::npos);
+  // Remove the a=connection line
+  answer.replace(match, strlen("\r\na=connection:new"), "");
+  std::cout << "Modified SDP " << std::endl
+            << indent(answer) << std::endl;
+
+  // This should setup the DTLS with the same roles
+  // as the regular tests above.
+  a2_.SetLocal(TestObserver::ANSWER, a2_.answer(), false);
+  a1_.SetRemote(TestObserver::ANSWER, a2_.answer(), false);
+
+  ASSERT_TRUE_WAIT(a1_.IceCompleted() == true, kDefaultTimeout);
+  ASSERT_TRUE_WAIT(a2_.IceCompleted() == true, kDefaultTimeout);
+
+  // Wait for some data to get written
+  ASSERT_TRUE_WAIT(a1_.GetPacketsSent(0) >= 40 &&
+                   a2_.GetPacketsReceived(0) >= 40, kDefaultTimeout * 2);
+
+  a1_.CloseSendStreams();
+  a2_.CloseReceiveStreams();
+
+  ASSERT_GE(a1_.GetPacketsSent(0), 40);
+  ASSERT_GE(a2_.GetPacketsReceived(0), 40);
+}
+
 } // End namespace test.
 
 bool is_color_terminal(const char *terminal) {
   if (!terminal) {
     return false;
   }
   const char *color_terms[] = {
     "xterm",
--- a/mfbt/RefPtr.h
+++ b/mfbt/RefPtr.h
@@ -63,42 +63,42 @@ class RefCounted
   protected:
     RefCounted() : refCnt(0) { }
     ~RefCounted() {
       MOZ_ASSERT(refCnt == detail::DEAD);
     }
 
   public:
     // Compatibility with nsRefPtr.
-    void AddRef() {
+    void AddRef() const {
       MOZ_ASSERT(refCnt >= 0);
       ++refCnt;
     }
 
-    void Release() {
+    void Release() const {
       MOZ_ASSERT(refCnt > 0);
       if (0 == --refCnt) {
 #ifdef DEBUG
         refCnt = detail::DEAD;
 #endif
-        delete static_cast<T*>(this);
+        delete static_cast<const T*>(this);
       }
     }
 
     // Compatibility with wtf::RefPtr.
     void ref() { AddRef(); }
     void deref() { Release(); }
     int refCount() const { return refCnt; }
     bool hasOneRef() const {
       MOZ_ASSERT(refCnt > 0);
       return refCnt == 1;
     }
 
   private:
-    typename Conditional<Atomicity == AtomicRefCount, Atomic<int>, int>::Type refCnt;
+    mutable typename Conditional<Atomicity == AtomicRefCount, Atomic<int>, int>::Type refCnt;
 };
 
 }
 
 template<typename T>
 class RefCounted : public detail::RefCounted<T, detail::NonAtomicRefCount>
 {
   public:
--- a/mobile/android/base/BrowserApp.java
+++ b/mobile/android/base/BrowserApp.java
@@ -8,16 +8,17 @@ package org.mozilla.gecko;
 import org.mozilla.gecko.animation.PropertyAnimator;
 import org.mozilla.gecko.db.BrowserContract.Combined;
 import org.mozilla.gecko.db.BrowserDB;
 import org.mozilla.gecko.gfx.BitmapUtils;
 import org.mozilla.gecko.gfx.GeckoLayerClient;
 import org.mozilla.gecko.gfx.ImmutableViewportMetrics;
 import org.mozilla.gecko.gfx.LayerView;
 import org.mozilla.gecko.gfx.PanZoomController;
+import org.mozilla.gecko.health.BrowserHealthRecorder;
 import org.mozilla.gecko.health.BrowserHealthReporter;
 import org.mozilla.gecko.home.BrowserSearch;
 import org.mozilla.gecko.home.HomePager;
 import org.mozilla.gecko.home.HomePager.OnUrlOpenListener;
 import org.mozilla.gecko.menu.GeckoMenu;
 import org.mozilla.gecko.util.Clipboard;
 import org.mozilla.gecko.util.FloatUtils;
 import org.mozilla.gecko.util.GamepadUtils;
@@ -1459,23 +1460,47 @@ abstract public class BrowserApp extends
                 final String keywordUrl = BrowserDB.getUrlForKeyword(getContentResolver(), keyword);
 
                 // If there isn't a bookmark keyword, just load the URL.
                 if (TextUtils.isEmpty(keywordUrl)) {
                     Tabs.getInstance().loadUrl(url, Tabs.LOADURL_USER_ENTERED);
                     return;
                 }
 
+                recordSearch(null, "barkeyword");
+
                 // Otherwise, construct a search query from the bookmark keyword.
                 final String searchUrl = keywordUrl.replace("%s", URLEncoder.encode(keywordSearch));
                 Tabs.getInstance().loadUrl(searchUrl, Tabs.LOADURL_USER_ENTERED);
             }
         });
     }
 
+    /**
+     * Record in Health Report that a search has occurred.
+     *
+     * @param identifier
+     *        a search identifier, such as "partnername". Can be null.
+     * @param where
+     *        where the search was initialized; one of the values in
+     *        {@link BrowserHealthRecorder#SEARCH_LOCATIONS}.
+     */
+    private static void recordSearch(String identifier, String where) {
+        Log.i(LOGTAG, "Recording search: " + identifier + ", " + where);
+        try {
+            JSONObject message = new JSONObject();
+            message.put("type", BrowserHealthRecorder.EVENT_SEARCH);
+            message.put("location", where);
+            message.put("identifier", identifier);
+            GeckoAppShell.getEventDispatcher().dispatchEvent(message);
+        } catch (Exception e) {
+            Log.w(LOGTAG, "Error recording search.", e);
+        }
+    }
+
     boolean dismissEditingMode() {
         if (!mBrowserToolbar.isEditing()) {
             return false;
         }
 
         mBrowserToolbar.cancelEdit();
 
         // Resetting the visibility of HomePager, which might have been hidden
@@ -2204,16 +2229,17 @@ abstract public class BrowserApp extends
         if (!maybeSwitchToTab(url, flags)) {
             openUrl(url);
         }
     }
 
     // BrowserSearch.OnSearchListener
     @Override
     public void onSearch(String engineId, String text) {
+        recordSearch(engineId, "barsuggest");
         openUrl(text, engineId);
     }
 
     // BrowserSearch.OnEditSuggestionListener
     @Override
     public void onEditSuggestion(String suggestion) {
         mBrowserToolbar.onEditSuggestion(suggestion);
     }
--- a/mobile/android/base/BrowserToolbar.java
+++ b/mobile/android/base/BrowserToolbar.java
@@ -856,35 +856,35 @@ public class BrowserToolbar extends Geck
 
     public void updateTabCountAndAnimate(int count) {
         // Don't animate if the toolbar is hidden.
         if (!isVisible()) {
             updateTabCount(count);
             return;
         }
 
-        // If toolbar is in edit mode, this means the entry is expanded and the
-        // tabs button is translated offscreen. Don't trigger tabs counter
+        // If toolbar is in edit mode on a phone, this means the entry is expanded
+        // and the tabs button is translated offscreen. Don't trigger tabs counter
         // updates until the tabs button is back on screen.
         // See stopEditing()
-        if (!isEditing()) {
+        if (!isEditing() || HardwareUtils.isTablet()) {
             mTabsCounter.setCount(count);
 
             mTabs.setContentDescription((count > 1) ?
                                         mActivity.getString(R.string.num_tabs, count) :
                                         mActivity.getString(R.string.one_tab));
         }
     }
 
     public void updateTabCount(int count) {
-        // If toolbar is in edit mode, this means the entry is expanded and the
-        // tabs button is translated offscreen. Don't trigger tabs counter
+        // If toolbar is in edit mode on a phone, this means the entry is expanded
+        // and the tabs button is translated offscreen. Don't trigger tabs counter
         // updates until the tabs button is back on screen.
         // See stopEditing()
-        if (isEditing()) {
+        if (isEditing() && !HardwareUtils.isTablet()) {
             return;
         }
 
         // Set TabCounter based on visibility
         if (isVisible() && ViewHelper.getAlpha(mTabsCounter) != 0) {
             mTabsCounter.setCountWithAnimation(count);
         } else {
             mTabsCounter.setCount(count);
@@ -1373,19 +1373,20 @@ public class BrowserToolbar extends Geck
         final String url = mUrlEditText.getText().toString();
         if (!isEditing()) {
             return url;
         }
         mIsEditing = false;
 
         if (HardwareUtils.isTablet() || Build.VERSION.SDK_INT < 11) {
             hideUrlEditContainer();
-            updateTabCountAndAnimate(Tabs.getInstance().getDisplayCount());
 
             if (!HardwareUtils.isTablet()) {
+                updateTabCountAndAnimate(Tabs.getInstance().getDisplayCount());
+
                 if (mUrlBarRightEdge != null) {
                     ViewHelper.setTranslationX(mUrlBarRightEdge, 0);
                 }
 
                 ViewHelper.setTranslationX(mTabs, 0);
                 ViewHelper.setTranslationX(mTabsCounter, 0);
                 ViewHelper.setTranslationX(mActionItemBar, 0);
 
--- a/mobile/android/base/GeckoApp.java
+++ b/mobile/android/base/GeckoApp.java
@@ -2342,17 +2342,20 @@ abstract public class GeckoApp
         CellLocation cl = tm.getCellLocation();
         String mcc = "", mnc = "";
         if (cl instanceof GsmCellLocation) {
             JSONObject obj = new JSONObject();
             GsmCellLocation gcl = (GsmCellLocation)cl;
             try {
                 obj.put("lac", gcl.getLac());
                 obj.put("cid", gcl.getCid());
-                obj.put("psc", gcl.getPsc());
+
+                int psc = (Build.VERSION.SDK_INT >= 9) ? gcl.getPsc() : -1;
+                obj.put("psc", psc);
+
                 switch(tm.getNetworkType()) {
                 case TelephonyManager.NETWORK_TYPE_GPRS:
                 case TelephonyManager.NETWORK_TYPE_EDGE:
                     obj.put("radio", "gsm");
                     break;
                 case TelephonyManager.NETWORK_TYPE_UMTS:
                 case TelephonyManager.NETWORK_TYPE_HSDPA:
                 case TelephonyManager.NETWORK_TYPE_HSUPA:
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -329,17 +329,16 @@ var BrowserApp = {
     ClipboardHelper.init();
     CharacterEncoding.init();
     ActivityObserver.init();
     WebappsUI.init();
     RemoteDebugger.init();
     Reader.init();
     UserAgentOverrides.init();
     DesktopUserAgent.init();
-    ExternalApps.init();
     Distribution.init();
     Tabs.init();
 #ifdef ACCESSIBILITY
     AccessFu.attach(window);
 #endif
 
     // Init LoginManager
     Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager);
@@ -363,16 +362,19 @@ var BrowserApp = {
     if (pinned) {
       WebAppRT.init(status, url, function(aUrl) {
         BrowserApp.addTab(aUrl);
       });
     } else {
       SearchEngines.init();
       this.initContextMenu();
     }
+    // The order that context menu items are added is important
+    // Make sure the "Open in App" context menu item appears at the bottom of the list
+    ExternalApps.init();
 
     // XXX maybe we don't do this if the launch was kicked off from external
     Services.io.offline = false;
 
     // Broadcast a UIReady message so add-ons know we are finished with startup
     let event = document.createEvent("Events");
     event.initEvent("UIReady", true, false);
     window.dispatchEvent(event);
--- a/mozglue/linker/ElfLoader.h
+++ b/mozglue/linker/ElfLoader.h
@@ -65,17 +65,17 @@ IsSignalHandlingBroken();
  * RefCounted<LibHandle>::Release to support some reentrancy. See further
  * below.
  */
 class LibHandle;
 
 namespace mozilla {
 namespace detail {
 
-template <> inline void RefCounted<LibHandle, AtomicRefCount>::Release();
+template <> inline void RefCounted<LibHandle, AtomicRefCount>::Release() const;
 
 template <> inline RefCounted<LibHandle, AtomicRefCount>::~RefCounted()
 {
   MOZ_ASSERT(refCnt == 0x7fffdead);
 }
 
 } /* namespace detail */
 } /* namespace mozilla */
@@ -210,30 +210,30 @@ private:
  * to 1 on normal builds, and 0x7fffdead on debug builds so that the LibHandle
  * can still be referenced while the destructor is executing. The refCnt is
  * allowed to grow > 0x7fffdead, but not to decrease under that value, which
  * would mean too many Releases from within the destructor.
  */
 namespace mozilla {
 namespace detail {
 
-template <> inline void RefCounted<LibHandle, AtomicRefCount>::Release() {
+template <> inline void RefCounted<LibHandle, AtomicRefCount>::Release() const {
 #ifdef DEBUG
   if (refCnt > 0x7fff0000)
     MOZ_ASSERT(refCnt > 0x7fffdead);
 #endif
   MOZ_ASSERT(refCnt > 0);
   if (refCnt > 0) {
     if (0 == --refCnt) {
 #ifdef DEBUG
       refCnt = 0x7fffdead;
 #else
       refCnt = 1;
 #endif
-      delete static_cast<LibHandle*>(this);
+      delete static_cast<const LibHandle*>(this);
     }
   }
 }
 
 } /* namespace detail */
 } /* namespace mozilla */
 
 /**
--- a/toolkit/content/widgets/remote-browser.xml
+++ b/toolkit/content/widgets/remote-browser.xml
@@ -33,33 +33,34 @@
 
       <field name="_remoteWebNavigation">null</field>
 
       <property name="webNavigation" readonly="true">
         <getter>
           <![CDATA[
             if (!this._remoteWebNavigation) {
               let jsm = "resource://gre/modules/RemoteWebNavigation.jsm";
-              let RemoteWebNavigation = Components.utils.import(jsm, {}).RemoteWebNavigation;
+              let RemoteWebNavigation = Cu.import(jsm, {}).RemoteWebNavigation;
               this._remoteWebNavigation = new RemoteWebNavigation(this);
             }
             return this._remoteWebNavigation;
           ]]>
         </getter>
       </property>
 
       <field name="_remoteWebProgress">null</field>
 
       <property name="webProgress" readonly="true">
       	<getter>
       	  <![CDATA[
             if (!this._remoteWebProgress) {
               let jsm = "resource://gre/modules/RemoteWebProgress.jsm";
-              let RemoteWebProgress = Components.utils.import(jsm, {}).RemoteWebProgress;
-              this._remoteWebProgress = new RemoteWebProgress(this);
+              let RemoteWebProgressManager = Cu.import(jsm, {}).RemoteWebProgressManager;
+              this._remoteWebProgress = new RemoteWebProgressManager(this)
+                                         .topLevelWebProgress;
             }
             return this._remoteWebProgress;
       	  ]]>
       	</getter>
       </property>
 
       <field name="_documentURI">null</field>
 
@@ -102,18 +103,16 @@
           this.messageManager.loadFrameScript("chrome://global/content/browser-child.js", true);
 
           if (this.hasAttribute("selectpopup")) {
             this.messageManager.addMessageListener("Forms:ShowDropDown", this);
             this.messageManager.addMessageListener("Forms:HideDropDown", this);
             this.messageManager.loadFrameScript("chrome://global/content/select-child.js", true);
           }
 
-          this.webProgress._init();
-
           let jsm = "resource://gre/modules/RemoteController.jsm";
           let RemoteController = Components.utils.import(jsm, {}).RemoteController;
           this._controller = new RemoteController(this);
           this.controllers.appendController(this._controller);
 
           jsm = "resource://gre/modules/RemoteAddonsParent.jsm";
           let RemoteAddonsParent = Components.utils.import(jsm, {}).RemoteAddonsParent;
           RemoteAddonsParent.init();
--- a/toolkit/modules/RemoteSecurityUI.jsm
+++ b/toolkit/modules/RemoteSecurityUI.jsm
@@ -8,41 +8,27 @@ this.EXPORTED_SYMBOLS = ["RemoteSecurity
 const Ci = Components.interfaces;
 const Cc = Components.classes;
 const Cu = Components.utils;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 function RemoteSecurityUI()
 {
+    this._SSLStatus = null;
     this._state = 0;
-    this._SSLStatus = null;
 }
 
 RemoteSecurityUI.prototype = {
   QueryInterface: XPCOMUtils.generateQI([Ci.nsISSLStatusProvider, Ci.nsISecureBrowserUI]),
 
+  // nsISSLStatusProvider
+  get SSLStatus() { return this._SSLStatus; },
+
   // nsISecureBrowserUI
   get state() { return this._state; },
   get tooltipText() { return ""; },
 
-  // nsISSLStatusProvider
-  get SSLStatus() { return this._SSLStatus; },
-
-  _update: function (state, status) {
-      let deserialized = null;
-      if (status) {
-        let helper = Cc["@mozilla.org/network/serialization-helper;1"]
-                      .getService(Components.interfaces.nsISerializationHelper);
-
-        deserialized = helper.deserializeObject(status)
-        deserialized.QueryInterface(Ci.nsISSLStatus);
-      }
-
-      // We must check the Extended Validation (EV) state here, on the chrome
-      // process, because NSS is needed for that determination.
-      if (deserialized && deserialized.isExtendedValidation)
-        state |= Ci.nsIWebProgressListener.STATE_IDENTITY_EV_TOPLEVEL;
-
-      this._state = state;
-      this._SSLStatus = deserialized;
+  _update: function (aStatus, aState) {
+    this._SSLStatus = aStatus;
+    this._state = aState;
   }
 };
--- a/toolkit/modules/RemoteWebProgress.jsm
+++ b/toolkit/modules/RemoteWebProgress.jsm
@@ -1,14 +1,14 @@
 // -*- Mode: javascript; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 // 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/.
 
-this.EXPORTED_SYMBOLS = ["RemoteWebProgress"];
+this.EXPORTED_SYMBOLS = ["RemoteWebProgressManager"];
 
 const Ci = Components.interfaces;
 const Cc = Components.classes;
 const Cu = Components.utils;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 function newURI(spec)
@@ -23,129 +23,159 @@ function RemoteWebProgressRequest(spec)
 }
 
 RemoteWebProgressRequest.prototype = {
   QueryInterface : XPCOMUtils.generateQI([Ci.nsIChannel]),
 
   get URI() { return this.uri.clone(); }
 };
 
-function RemoteWebProgress(browser)
-{
-  this._browser = browser;
+function RemoteWebProgress(aManager, aIsTopLevel) {
+  this._manager = aManager;
+
   this._isLoadingDocument = false;
   this._DOMWindow = null;
-  this._isTopLevel = null;
+  this._isTopLevel = aIsTopLevel;
   this._loadType = 0;
-  this._progressListeners = [];
 }
 
 RemoteWebProgress.prototype = {
   NOTIFY_STATE_REQUEST:  0x00000001,
   NOTIFY_STATE_DOCUMENT: 0x00000002,
   NOTIFY_STATE_NETWORK:  0x00000004,
   NOTIFY_STATE_WINDOW:   0x00000008,
   NOTIFY_STATE_ALL:      0x0000000f,
   NOTIFY_PROGRESS:       0x00000010,
   NOTIFY_STATUS:         0x00000020,
   NOTIFY_SECURITY:       0x00000040,
   NOTIFY_LOCATION:       0x00000080,
   NOTIFY_REFRESH:        0x00000100,
   NOTIFY_ALL:            0x000001ff,
 
-  _init: function WP_Init() {
-    this._browser.messageManager.addMessageListener("Content:StateChange", this);
-    this._browser.messageManager.addMessageListener("Content:LocationChange", this);
-    this._browser.messageManager.addMessageListener("Content:SecurityChange", this);
-    this._browser.messageManager.addMessageListener("Content:StatusChange", this);
-  },
-
-  _destroy: function WP_Destroy() {
-    this._browser = null;
-  },
-
   get isLoadingDocument() { return this._isLoadingDocument },
   get DOMWindow() { return this._DOMWindow; },
   get DOMWindowID() { return 0; },
-  get isTopLevel() {
-    // When this object is accessed directly, it's usually obtained
-    // through browser.webProgress and thus represents the top-level
-    // document.
-    // However, during message handling it temporarily represents
-    // the webProgress that generated the notification, which may or
-    // may not be a toplevel frame.
-    return this._isTopLevel === null ? true : this._isTopLevel;
-  },
+  get isTopLevel() { return this._isTopLevel },
   get loadType() { return this._loadType; },
 
-  addProgressListener: function WP_AddProgressListener (aListener) {
+  addProgressListener: function (aListener) {
+    this._manager.addProgressListener(aListener);
+  },
+
+  removeProgressListener: function (aListener) {
+    this._manager.removeProgressListener(aListener);
+  }
+};
+
+function RemoteWebProgressManager (aBrowser) {
+  this._browser = aBrowser;
+  this._topLevelWebProgress = new RemoteWebProgress(this, true);
+  this._progressListeners = [];
+
+  this._browser.messageManager.addMessageListener("Content:StateChange", this);
+  this._browser.messageManager.addMessageListener("Content:LocationChange", this);
+  this._browser.messageManager.addMessageListener("Content:SecurityChange", this);
+  this._browser.messageManager.addMessageListener("Content:StatusChange", this);
+}
+
+RemoteWebProgressManager.prototype = {
+  get topLevelWebProgress() {
+    return this._topLevelWebProgress;
+  },
+
+  addProgressListener: function (aListener) {
     let listener = aListener.QueryInterface(Ci.nsIWebProgressListener);
     this._progressListeners.push(listener);
   },
 
-  removeProgressListener: function WP_RemoveProgressListener (aListener) {
+  removeProgressListener: function (aListener) {
     this._progressListeners =
-      this._progressListeners.filter(function (l) l != aListener);
+      this._progressListeners.filter(l => l != aListener);
   },
 
-  _uriSpec: function (spec) {
-    if (!spec)
-      return null;
-    return new RemoteWebProgressRequest(spec);
+  _fixSSLStatusAndState: function (aStatus, aState) {
+    let deserialized = null;
+    if (aStatus) {
+      let helper = Cc["@mozilla.org/network/serialization-helper;1"]
+                    .getService(Components.interfaces.nsISerializationHelper);
+
+      deserialized = helper.deserializeObject(aStatus)
+      deserialized.QueryInterface(Ci.nsISSLStatus);
+    }
+
+    // We must check the Extended Validation (EV) state here, on the chrome
+    // process, because NSS is needed for that determination.
+    if (deserialized && deserialized.isExtendedValidation)
+      aState |= Ci.nsIWebProgressListener.STATE_IDENTITY_EV_TOPLEVEL;
+
+    return [deserialized, aState];
   },
 
-  receiveMessage: function WP_ReceiveMessage(aMessage) {
-    this._isLoadingDocument = aMessage.json.isLoadingDocument;
-    this._DOMWindow = aMessage.objects.DOMWindow;
-    this._isTopLevel = aMessage.json.isTopLevel;
-    this._loadType = aMessage.json.loadType;
+  receiveMessage: function (aMessage) {
+    let json = aMessage.json;
+    let objects = aMessage.objects;
+
+    // The top-level WebProgress is always the same, but because we don't
+    // really have a concept of subframes/content we always creat a new object
+    // for those.
+    let webProgress = json.isTopLevel ? this._topLevelWebProgress
+                                      : new RemoteWebProgress(this, false);
 
-    this._browser._contentWindow = aMessage.objects.contentWindow;
+    // The WebProgressRequest object however is always dynamic.
+    let request = json.requestURI ? new RemoteWebProgressRequest(json.requestURI)
+                                  : null;
 
-    let req = this._uriSpec(aMessage.json.requestURI);
+    // Update the actual WebProgress fields.
+    webProgress._isLoadingDocument = json.isLoadingDocument;
+    webProgress._DOMWindow = objects.DOMWindow;
+    webProgress._loadType = json.loadType;
+
+    if (json.isTopLevel)
+      this._browser._contentWindow = objects.contentWindow;
+
     switch (aMessage.name) {
     case "Content:StateChange":
-      for each (let p in this._progressListeners) {
-        p.onStateChange(this, req, aMessage.json.stateFlags, aMessage.json.status);
+      for (let p of this._progressListeners) {
+        p.onStateChange(webProgress, request, json.stateFlags, json.status);
       }
       break;
 
     case "Content:LocationChange":
-      let location = newURI(aMessage.json.location);
+      let location = newURI(json.location);
 
-      if (aMessage.json.isTopLevel) {
+      if (json.isTopLevel) {
         this._browser.webNavigation._currentURI = location;
-        this._browser.webNavigation.canGoBack = aMessage.json.canGoBack;
-        this._browser.webNavigation.canGoForward = aMessage.json.canGoForward;
-        this._browser._characterSet = aMessage.json.charset;
-        this._browser._documentURI = newURI(aMessage.json.documentURI);
+        this._browser.webNavigation.canGoBack = json.canGoBack;
+        this._browser.webNavigation.canGoForward = json.canGoForward;
+        this._browser._characterSet = json.charset;
+        this._browser._documentURI = newURI(json.documentURI);
         this._browser._imageDocument = null;
       }
 
-      for each (let p in this._progressListeners) {
-        p.onLocationChange(this, req, location);
+      for (let p of this._progressListeners) {
+        p.onLocationChange(webProgress, request, location);
       }
       break;
 
     case "Content:SecurityChange":
-      // Invoking this getter triggers the generation of the underlying object,
-      // which we need to access with ._securityUI, because .securityUI returns
-      // a wrapper that makes _update inaccessible.
-      void this._browser.securityUI;
-      this._browser._securityUI._update(aMessage.json.state, aMessage.json.status);
+      let [status, state] = this._fixSSLStatusAndState(json.status, json.state);
 
-      // The state passed might not be correct due to checks performed
-      // on the chrome side. _update fixes that.
-      for each (let p in this._progressListeners) {
-        p.onSecurityChange(this, req, this._browser.securityUI.state);
+      if (json.isTopLevel) {
+        // Invoking this getter triggers the generation of the underlying object,
+        // which we need to access with ._securityUI, because .securityUI returns
+        // a wrapper that makes _update inaccessible.
+        void this._browser.securityUI;
+        this._browser._securityUI._update(status, state);
+      }
+
+      for (let p of this._progressListeners) {
+        p.onSecurityChange(webProgress, request, state);
       }
       break;
 
     case "Content:StatusChange":
-      for each (let p in this._progressListeners) {
-        p.onStatusChange(this, req, aMessage.json.status, aMessage.json.message);
+      for (let p of this._progressListeners) {
+        p.onStatusChange(webProgress, request, json.status, json.message);
       }
       break;
     }
-
-    this._isTopLevel = null;
   }
 };
new file mode 100644
--- /dev/null
+++ b/widget/windows/winrt/APZController.cpp
@@ -0,0 +1,107 @@
+/* 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 "APZController.h"
+#include "base/message_loop.h"
+#include "mozilla/layers/GeckoContentController.h"
+#include "nsThreadUtils.h"
+#include "MetroUtils.h"
+#include "nsPrintfCString.h"
+
+namespace mozilla {
+namespace widget {
+namespace winrt {
+
+class RequestContentRepaintEvent : public nsRunnable
+{
+    typedef mozilla::layers::FrameMetrics FrameMetrics;
+
+public:
+    RequestContentRepaintEvent(const FrameMetrics& aFrameMetrics) : mFrameMetrics(aFrameMetrics)
+    {
+    }
+
+    NS_IMETHOD Run() {
+        // This event shuts down the worker thread and so must be main thread.
+        MOZ_ASSERT(NS_IsMainThread());
+
+        CSSToScreenScale resolution = mFrameMetrics.mZoom;
+        CSSRect compositedRect = mFrameMetrics.CalculateCompositedRectInCssPixels();
+
+        NS_ConvertASCIItoUTF16 data(nsPrintfCString("{ " \
+                                                    "  \"resolution\": %.2f, " \
+                                                    "  \"scrollId\": %d, " \
+                                                    "  \"compositedRect\": { \"width\": %d, \"height\": %d }, " \
+                                                    "  \"displayPort\":    { \"x\": %d, \"y\": %d, \"width\": %d, \"height\": %d }, " \
+                                                    "  \"scrollTo\":       { \"x\": %d, \"y\": %d }" \
+                                                    "}",
+                                                    (float)(resolution.scale / mFrameMetrics.mDevPixelsPerCSSPixel.scale),
+                                                    (int)mFrameMetrics.mScrollId,
+                                                    (int)compositedRect.width,
+                                                    (int)compositedRect.height,
+                                                    (int)mFrameMetrics.mDisplayPort.x,
+                                                    (int)mFrameMetrics.mDisplayPort.y,
+                                                    (int)mFrameMetrics.mDisplayPort.width,
+                                                    (int)mFrameMetrics.mDisplayPort.height,
+                                                    (int)mFrameMetrics.mScrollOffset.x,
+                                                    (int)mFrameMetrics.mScrollOffset.y));
+
+        MetroUtils::FireObserver("apzc-request-content-repaint", data.get());
+        return NS_OK;
+    }
+protected:
+    const FrameMetrics mFrameMetrics;
+};
+
+void
+APZController::RequestContentRepaint(const FrameMetrics& aFrameMetrics)
+{
+  // Send the result back to the main thread so that it can shutdown
+  nsCOMPtr<nsIRunnable> r1 = new RequestContentRepaintEvent(aFrameMetrics);
+  if (!NS_IsMainThread()) {
+    NS_DispatchToMainThread(r1);
+  } else {
+    r1->Run();
+  }
+}
+
+void
+APZController::HandleDoubleTap(const CSSIntPoint& aPoint)
+{
+}
+
+void
+APZController::HandleSingleTap(const CSSIntPoint& aPoint)
+{
+}
+
+void
+APZController::HandleLongTap(const CSSIntPoint& aPoint)
+{
+}
+
+void
+APZController::SendAsyncScrollDOMEvent(FrameMetrics::ViewID aScrollId, const CSSRect &aContentRect, const CSSSize &aScrollableSize)
+{
+}
+
+void
+APZController::PostDelayedTask(Task* aTask, int aDelayMs)
+{
+  MessageLoop::current()->PostDelayedTask(FROM_HERE, aTask, aDelayMs);
+}
+
+void
+APZController::HandlePanBegin()
+{
+  MetroUtils::FireObserver("apzc-handle-pan-begin", L"");
+}
+
+void
+APZController::HandlePanEnd()
+{
+  MetroUtils::FireObserver("apzc-handle-pan-end", L"");
+}
+
+} } }
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/widget/windows/winrt/APZController.h
@@ -0,0 +1,32 @@
+/* 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/. */
+
+#pragma once
+
+#include "mozwrlbase.h"
+
+#include "mozilla/layers/GeckoContentController.h"
+#include "FrameMetrics.h"
+#include "Units.h"
+
+namespace mozilla {
+namespace widget {
+namespace winrt {
+
+class APZController : public mozilla::layers::GeckoContentController
+{
+  typedef mozilla::layers::FrameMetrics FrameMetrics;
+
+public:
+  virtual void RequestContentRepaint(const FrameMetrics& aFrameMetrics);
+  virtual void HandleDoubleTap(const mozilla::CSSIntPoint& aPoint);
+  virtual void HandleSingleTap(const mozilla::CSSIntPoint& aPoint);
+  virtual void HandleLongTap(const mozilla::CSSIntPoint& aPoint);
+  virtual void SendAsyncScrollDOMEvent(FrameMetrics::ViewID aScrollId, const mozilla::CSSRect &aContentRect, const mozilla::CSSSize &aScrollableSize);
+  virtual void PostDelayedTask(Task* aTask, int aDelayMs);
+  virtual void HandlePanBegin();
+  virtual void HandlePanEnd();
+};
+
+} } }
\ No newline at end of file
--- a/widget/windows/winrt/FrameworkView.cpp
+++ b/widget/windows/winrt/FrameworkView.cpp
@@ -192,17 +192,16 @@ FrameworkView::ShutdownXPCOM()
     mAutomationProvider.As(&provider);
     if (provider) {
       provider->Disconnect();
     }
   }
   mAutomationProvider = nullptr;
 
   mMetroInput = nullptr;
-  mD2DWindowSurface = nullptr;
   delete sSettingsArray;
   sSettingsArray = nullptr;
   mWidget = nullptr;
   mMetroApp = nullptr;
   mWindow = nullptr;
 }
 
 void
--- a/widget/windows/winrt/FrameworkView.h
+++ b/widget/windows/winrt/FrameworkView.h
@@ -2,16 +2,17 @@
 /* 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/. */
 
 #pragma once
 
 #include "nsGUIEvent.h"
 #include "MetroWidget.h"
+#include "MetroInput.h"
 #include "gfxWindowsPlatform.h"
 #include "gfxD2DSurface.h"
 #include "nsDataHashtable.h"
 
 #include "mozwrlbase.h"
 
 #include <windows.system.h>
 #include <Windows.ApplicationModel.core.h>
@@ -171,17 +172,16 @@ private:
   EventRegistrationToken mAutomationProviderRequested;
   EventRegistrationToken mDataTransferRequested;
   EventRegistrationToken mSearchQuerySubmitted;
   EventRegistrationToken mPlayToRequested;
   EventRegistrationToken mSettingsPane;
   EventRegistrationToken mPrintManager;
 
 private:
-  nsRefPtr<gfxD2DSurface> mD2DWindowSurface;
   nsIntRect mWindowBounds; // in device-pixel coordinates
   float mDPI;
   bool mShuttingDown;
   nsAutoString mActivationURI;
   nsAutoString mActivationCommandLine;
   Microsoft::WRL::ComPtr<IInspectable> mAutomationProvider;
   //Microsoft::WRL::ComPtr<ID2D1PrintControl> mD2DPrintControl;
   // Private critical section protects D2D device context for on-screen
--- a/widget/windows/winrt/MetroApp.cpp
+++ b/widget/windows/winrt/MetroApp.cpp
@@ -102,16 +102,17 @@ MetroApp::ShutdownXPCOM()
   // Shut down xpcom
   XRE_metroShutdown();
 }
 
 // Request a shutdown of the application
 void
 MetroApp::CoreExit()
 {
+  LogFunction();
   HRESULT hr;
   ComPtr<ICoreApplicationExit> coreExit;
   HStringReference className(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication);
   hr = GetActivationFactory(className.Get(), coreExit.GetAddressOf());
   NS_ASSERTION(SUCCEEDED(hr), "Activation of ICoreApplicationExit");
   if (SUCCEEDED(hr)) {
     coreExit->Exit();
   }
--- a/widget/windows/winrt/MetroInput.cpp
+++ b/widget/windows/winrt/MetroInput.cpp
@@ -1,14 +1,15 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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/. */
 
 // Moz headers (alphabetical)
+#include "MetroInput.h"
 #include "MetroUtils.h" // Logging, POINT_CEIL_*, ActivateGenericInstance, etc
 #include "MetroWidget.h" // MetroInput::mWidget
 #include "mozilla/dom/Touch.h"  // Touch
 #include "nsTArray.h" // Touch lists
 #include "nsIDOMSimpleGestureEvent.h" // Constants for gesture events
 #include "InputData.h"
 #include "UIABridgePrivate.h"
 
@@ -156,18 +157,16 @@ MetroInput::MetroInput(MetroWidget* aWid
                        UI::Core::ICoreWindow* aWindow)
               : mWidget(aWidget),
                 mWindow(aWindow)
 {
   LogFunction();
   NS_ASSERTION(aWidget, "Attempted to create MetroInput for null widget!");
   NS_ASSERTION(aWindow, "Attempted to create MetroInput for null window!");
 
-  mWidget->SetMetroInput(this);
-
   mTokenPointerPressed.value = 0;
   mTokenPointerReleased.value = 0;
   mTokenPointerMoved.value = 0;
   mTokenPointerEntered.value = 0;
   mTokenPointerExited.value = 0;
   mTokenEdgeStarted.value = 0;
   mTokenEdgeCanceled.value = 0;
   mTokenEdgeCompleted.value = 0;
@@ -923,37 +922,16 @@ MetroInput::OnRightTapped(UI::Input::IGe
   Foundation::Point position;
   aArgs->get_Position(&position);
   HandleLongTap(
     LayoutDeviceIntPoint::FromUntyped(MetroUtils::LogToPhys(position)));
 
   return S_OK;
 }
 
-// Used by MetroWidget GeckoContentController callbacks
-void
-MetroInput::HandleDoubleTap(const LayoutDeviceIntPoint& aPoint)
-{
-#ifdef DEBUG_INPUT
-  LogFunction();
-#endif
-  nsSimpleGestureEvent* tapEvent =
-    new nsSimpleGestureEvent(true,
-                             NS_SIMPLE_GESTURE_TAP,
-                             mWidget.Get(),
-                             0,
-                             0.0);
-
-  tapEvent->inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
-  tapEvent->refPoint = aPoint;
-  tapEvent->clickCount = 2;
-  tapEvent->pressure = 1;
-  DispatchAsyncEventIgnoreStatus(tapEvent);
-}
-
 void
 MetroInput::HandleSingleTap(const LayoutDeviceIntPoint& aPoint)
 {
 #ifdef DEBUG_INPUT
   LogFunction();
 #endif
 
   // send mousemove
--- a/widget/windows/winrt/MetroInput.h
+++ b/widget/windows/winrt/MetroInput.h
@@ -142,18 +142,16 @@ public:
   HRESULT OnManipulationUpdated(IGestureRecognizer* aSender,
                                 IManipulationUpdatedEventArgs* aArgs);
   HRESULT OnManipulationCompleted(IGestureRecognizer* aSender,
                                   IManipulationCompletedEventArgs* aArgs);
   HRESULT OnTapped(IGestureRecognizer* aSender, ITappedEventArgs* aArgs);
   HRESULT OnRightTapped(IGestureRecognizer* aSender,
                         IRightTappedEventArgs* aArgs);
 
-  // Used by MetroWidget GeckoContentController callbacks
-  void HandleDoubleTap(const mozilla::LayoutDeviceIntPoint& aPoint);
   void HandleSingleTap(const mozilla::LayoutDeviceIntPoint& aPoint);
   void HandleLongTap(const mozilla::LayoutDeviceIntPoint& aPoint);
 
 private:
   Microsoft::WRL::ComPtr<ICoreWindow> mWindow;
   Microsoft::WRL::ComPtr<MetroWidget> mWidget;
   Microsoft::WRL::ComPtr<IGestureRecognizer> mGestureRecognizer;
 
--- a/widget/windows/winrt/MetroWidget.cpp
+++ b/widget/windows/winrt/MetroWidget.cpp
@@ -957,17 +957,18 @@ MetroWidget::ShouldUseAPZC()
 }
 
 CompositorParent* MetroWidget::NewCompositorParent(int aSurfaceWidth, int aSurfaceHeight)
 {
   CompositorParent *compositor = nsBaseWidget::NewCompositorParent(aSurfaceWidth, aSurfaceHeight);
 
   if (ShouldUseAPZC()) {
     mRootLayerTreeId = compositor->RootLayerTreeId();
-    CompositorParent::SetControllerForLayerTree(mRootLayerTreeId, this);
+    mController = new APZController();
+    CompositorParent::SetControllerForLayerTree(mRootLayerTreeId, mController);
 
     MetroWidget::sAPZC = CompositorParent::GetAPZCTreeManager(compositor->RootLayerTreeId());
     MetroWidget::sAPZC->SetDPI(GetDPI());
 
     nsresult rv;
     nsCOMPtr<nsIObserverService> observerService = do_GetService("@mozilla.org/observer-service;1", &rv);
     if (NS_SUCCEEDED(rv)) {
       observerService->AddObserver(this, "scroll-offset-changed", false);
@@ -1469,134 +1470,16 @@ MetroWidget::PickerClosed()
 bool
 MetroWidget::HasPendingInputEvent()
 {
   if (HIWORD(GetQueueStatus(QS_INPUT)))
     return true;
   return false;
 }
 
-// GeckoContentController interface impl
-
-class RequestContentRepaintEvent : public nsRunnable
-{
-public:
-    RequestContentRepaintEvent(const FrameMetrics& aFrameMetrics) : mFrameMetrics(aFrameMetrics)
-    {
-    }
-
-    NS_IMETHOD Run() {
-        // This event shuts down the worker thread and so must be main thread.
-        MOZ_ASSERT(NS_IsMainThread());
-
-        CSSToScreenScale resolution = mFrameMetrics.mZoom;
-        CSSRect compositedRect = mFrameMetrics.CalculateCompositedRectInCssPixels();
-
-        NS_ConvertASCIItoUTF16 data(nsPrintfCString("{ " \
-                                                    "  \"resolution\": %.2f, " \
-                                                    "  \"scrollId\": %d, " \
-                                                    "  \"compositedRect\": { \"width\": %d, \"height\": %d }, " \
-                                                    "  \"displayPort\":    { \"x\": %d, \"y\": %d, \"width\": %d, \"height\": %d }, " \
-                                                    "  \"scrollTo\":       { \"x\": %d, \"y\": %d }" \
-                                                    "}",
-                                                    (float)(resolution.scale / mFrameMetrics.mDevPixelsPerCSSPixel.scale),
-                                                    (int)mFrameMetrics.mScrollId,
-                                                    (int)compositedRect.width,
-                                                    (int)compositedRect.height,
-                                                    (int)mFrameMetrics.mDisplayPort.x,
-                                                    (int)mFrameMetrics.mDisplayPort.y,
-                                                    (int)mFrameMetrics.mDisplayPort.width,
-                                                    (int)mFrameMetrics.mDisplayPort.height,
-                                                    (int)mFrameMetrics.mScrollOffset.x,
-                                                    (int)mFrameMetrics.mScrollOffset.y));
-
-        MetroUtils::FireObserver("apzc-request-content-repaint", data.get());
-        return NS_OK;
-    }
-protected:
-    const FrameMetrics mFrameMetrics;
-};
-
-void
-MetroWidget::RequestContentRepaint(const FrameMetrics& aFrameMetrics)
-{
-  LogFunction();
-
-  // Send the result back to the main thread so that it can shutdown
-  nsCOMPtr<nsIRunnable> r1 = new RequestContentRepaintEvent(aFrameMetrics);
-  if (!NS_IsMainThread()) {
-    NS_DispatchToMainThread(r1);
-  } else {
-    r1->Run();
-  }
-}
-
-void
-MetroWidget::HandleDoubleTap(const CSSIntPoint& aPoint)
-{
-  LogFunction();
-
-  if (!mMetroInput) {
-    return;
-  }
-
-  mMetroInput->HandleDoubleTap(CSSIntPointToLayoutDeviceIntPoint(aPoint));
-}
-
-void
-MetroWidget::HandleSingleTap(const CSSIntPoint& aPoint)
-{
-  LogFunction();
-
-  if (!mMetroInput) {
-    return;
-  }
-
-  mMetroInput->HandleSingleTap(CSSIntPointToLayoutDeviceIntPoint(aPoint));
-}
-
-void
-MetroWidget::HandleLongTap(const CSSIntPoint& aPoint)
-{
-  LogFunction();
-
-  if (!mMetroInput) {
-    return;
-  }
-
-  mMetroInput->HandleLongTap(CSSIntPointToLayoutDeviceIntPoint(aPoint));
-}
-
-void
-MetroWidget::SendAsyncScrollDOMEvent(FrameMetrics::ViewID aScrollId, const CSSRect &aContentRect, const CSSSize &aScrollableSize)
-{
-  LogFunction();
-}
-
-void
-MetroWidget::PostDelayedTask(Task* aTask, int aDelayMs)
-{
-  LogFunction();
-  MessageLoop::current()->PostDelayedTask(FROM_HERE, aTask, aDelayMs);
-}
-
-void
-MetroWidget::HandlePanBegin()
-{
-  LogFunction();
-  MetroUtils::FireObserver("apzc-handle-pan-begin", L"");
-}
-
-void
-MetroWidget::HandlePanEnd()
-{
-  LogFunction();
-  MetroUtils::FireObserver("apzc-handle-pan-end", L"");
-}
-
 NS_IMETHODIMP
 MetroWidget::Observe(nsISupports *subject, const char *topic, const PRUnichar *data)
 {
   NS_ENSURE_ARG_POINTER(topic);
   if (!strcmp(topic, "scroll-offset-changed")) {
     uint64_t scrollId;
     int32_t presShellId;
     CSSIntPoint scrollOffset;
--- a/widget/windows/winrt/MetroWidget.h
+++ b/widget/windows/winrt/MetroWidget.h
@@ -17,21 +17,21 @@
 #include "nsWindowDbg.h"
 #include "WindowHook.h"
 #include "TaskbarWindowPreview.h"
 #include "nsIdleService.h"
 #ifdef ACCESSIBILITY
 #include "mozilla/a11y/Accessible.h"
 #endif
 #include "mozilla/layers/CompositorParent.h"
-#include "mozilla/layers/GeckoContentController.h"
 #include "mozilla/layers/APZCTreeManager.h"
 #include "mozilla/layers/LayerManagerComposite.h"
 #include "Units.h"
-#include "MetroInput.h"
+#include "nsDeque.h"
+#include "APZController.h"
 
 #include "mozwrlbase.h"
 
 #include <windows.system.h>
 #include <windows.ui.core.h>
 #include <Windows.ApplicationModel.core.h>
 #include <Windows.ApplicationModel.h>
 #include <Windows.Applicationmodel.Activation.h>
@@ -43,27 +43,26 @@ namespace winrt {
 
 class FrameworkView;
 
 } } }
 
 class DispatchMsg;
 
 class MetroWidget : public nsWindowBase,
-                    public mozilla::layers::GeckoContentController,
                     public nsIObserver
 {
   typedef mozilla::widget::WindowHook WindowHook;
   typedef mozilla::widget::TaskbarWindowPreview TaskbarWindowPreview;
   typedef ABI::Windows::UI::Input::IPointerPoint IPointerPoint;
   typedef ABI::Windows::UI::Core::IPointerEventArgs IPointerEventArgs;
   typedef ABI::Windows::UI::Core::IKeyEventArgs IKeyEventArgs;
   typedef ABI::Windows::UI::Core::ICharacterReceivedEventArgs ICharacterReceivedEventArgs;
   typedef mozilla::widget::winrt::FrameworkView FrameworkView;
-  typedef mozilla::layers::FrameMetrics FrameMetrics;
+  typedef mozilla::widget::winrt::APZController APZController;
 
   static LRESULT CALLBACK
   StaticWindowProcedure(HWND aWnd, UINT aMsg, WPARAM aWParan, LPARAM aLParam);
   LRESULT WindowProcedure(HWND aWnd, UINT aMsg, WPARAM aWParan, LPARAM aLParam);
 
 public:
   MetroWidget();
   virtual ~MetroWidget();
@@ -195,31 +194,16 @@ public:
   void SetView(FrameworkView* aView);
   void FindMetroWindow();
   virtual void SetTransparencyMode(nsTransparencyMode aMode);
   virtual nsTransparencyMode GetTransparencyMode();
 
   nsresult RequestContentScroll();
   void RequestContentRepaintImplMainThread();
 
-  // GeckoContentController interface impl
-  virtual void RequestContentRepaint(const FrameMetrics& aFrameMetrics);
-  virtual void HandleDoubleTap(const mozilla::CSSIntPoint& aPoint);
-  virtual void HandleSingleTap(const mozilla::CSSIntPoint& aPoint);
-  virtual void HandleLongTap(const mozilla::CSSIntPoint& aPoint);
-  virtual void SendAsyncScrollDOMEvent(FrameMetrics::ViewID aScrollId, const mozilla::CSSRect &aContentRect, const mozilla::CSSSize &aScrollableSize);
-  virtual void PostDelayedTask(Task* aTask, int aDelayMs);
-  virtual void HandlePanBegin();
-  virtual void HandlePanEnd();
-
-  void SetMetroInput(mozilla::widget::winrt::MetroInput* aMetroInput)
-  {
-    mMetroInput = aMetroInput;
-  }
-
 protected:
   friend class FrameworkView;
 
   struct OleInitializeWrapper {
     HRESULT const hr;
 
     OleInitializeWrapper()
       : hr(::OleInitialize(NULL))
@@ -233,34 +217,33 @@ protected:
       }
     }
   };
 
   void SetSubclass();
   void RemoveSubclass();
   nsIWidgetListener* GetPaintListener();
 
+  // Async event dispatching
+  void DispatchAsyncScrollEvent(DispatchMsg* aEvent);
+  void DeliverNextScrollEvent();
+  void DeliverNextKeyboardEvent();
+  DispatchMsg* CreateDispatchMsg(UINT aMsg, WPARAM aWParam, LPARAM aLParam);
+
+public:
+  static nsRefPtr<mozilla::layers::APZCTreeManager> sAPZC;
+
+protected:
   OleInitializeWrapper mOleInitializeWrapper;
   WindowHook mWindowHook;
   Microsoft::WRL::ComPtr<FrameworkView> mView;
   nsTransparencyMode mTransparencyMode;
   nsIntRegion mInvalidatedRegion;
   nsCOMPtr<nsIdleService> mIdleService;
   HWND mWnd;
   static HWND sICoreHwnd;
   WNDPROC mMetroWndProc;
   bool mTempBasicLayerInUse;
-  Microsoft::WRL::ComPtr<mozilla::widget::winrt::MetroInput> mMetroInput;
-  mozilla::layers::FrameMetrics mFrameMetrics;
   uint64_t mRootLayerTreeId;
-
-  // Async event dispatching
-  void DispatchAsyncScrollEvent(DispatchMsg* aEvent);
-  void DeliverNextScrollEvent();
-  void DeliverNextKeyboardEvent();
-  DispatchMsg* CreateDispatchMsg(UINT aMsg, WPARAM aWParam, LPARAM aLParam);
-
   nsDeque mMsgEventQueue;
   nsDeque mKeyEventQueue;
-
-public:
-  static nsRefPtr<mozilla::layers::APZCTreeManager> sAPZC;
+  nsRefPtr<APZController> mController;
 };
--- a/widget/windows/winrt/moz.build
+++ b/widget/windows/winrt/moz.build
@@ -14,16 +14,17 @@ CPP_SOURCES += [
     'MetroInput.cpp',
     'MetroUtils.cpp',
     'MetroWidget.cpp',
     'ToastNotificationHandler.cpp',
     'UIAAccessibilityBridge.cpp',
     'UIABridge.cpp',
     'nsMetroFilePicker.cpp',
     'nsWinMetroUtils.cpp',
+    'APZController.cpp',
 ]
 
 EXTRA_COMPONENTS += [
     'MetroUIUtils.js',
     'MetroUIUtils.manifest',
 ]
 
 LIBXUL_LIBRARY = True
--- a/xpcom/base/nsCycleCollector.cpp
+++ b/xpcom/base/nsCycleCollector.cpp
@@ -100,17 +100,16 @@
 
 /* This must occur *after* base/process_util.h to avoid typedefs conflicts. */
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/Util.h"
 
 #include "mozilla/CycleCollectedJSRuntime.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsCycleCollectionNoteRootCallback.h"
-#include "nsBaseHashtable.h"
 #include "nsHashKeys.h"
 #include "nsDeque.h"
 #include "nsCycleCollector.h"
 #include "nsThreadUtils.h"
 #include "prenv.h"
 #include "prprf.h"
 #include "plstr.h"
 #include "nsPrintfCString.h"
@@ -836,17 +835,17 @@ public:
         // We also don't measure the things pointed to by mEntries[] because
         // those pointers are non-owning.
 
         return n;
     }
 };
 
 static bool
-AddPurpleRoot(GCGraphBuilder &builder, void *root, nsCycleCollectionParticipant *cp);
+AddPurpleRoot(GCGraphBuilder &aBuilder, void *aRoot, nsCycleCollectionParticipant *aParti);
 
 struct SelectPointersVisitor
 {
     SelectPointersVisitor(GCGraphBuilder &aBuilder)
         : mBuilder(aBuilder)
     {}
 
     void
@@ -888,16 +887,17 @@ enum ccType {
 // Top level structure for the cycle collector.
 ////////////////////////////////////////////////////////////////////////
 
 class nsCycleCollector
 {
     friend class GCGraphBuilder;
 
     bool mCollectionInProgress;
+    // mScanInProgress should be false when we're collecting white objects.
     bool mScanInProgress;
     nsCycleCollectorResults *mResults;
     TimeStamp mCollectionStart;
 
     CycleCollectedJSRuntime *mJSRuntime;
 
     GCGraph mGraph;
 
@@ -931,26 +931,27 @@ public:
     inline CycleCollectedJSRuntime*
     JSRuntime() const
     {
         return mJSRuntime;
     }
 
     void SetBeforeUnlinkCallback(CC_BeforeUnlinkCallback aBeforeUnlinkCB)
     {
+        CheckThreadSafety();
         mBeforeUnlinkCB = aBeforeUnlinkCB;
     }
 
     void SetForgetSkippableCallback(CC_ForgetSkippableCallback aForgetSkippableCB)
     {
+        CheckThreadSafety();
         mForgetSkippableCB = aForgetSkippableCB;
     }
 
-    void SelectPurple(GCGraphBuilder &builder);
-    void MarkRoots(GCGraphBuilder &builder);
+    void MarkRoots(GCGraphBuilder &aBuilder);
     void ScanRoots();
     void ScanWeakMaps();
 
     void ForgetSkippable(bool aRemoveChildlessNodes, bool aAsyncSnowWhiteFreeing);
 
     // returns whether anything was collected
     bool CollectWhite(nsICycleCollectorListener *aListener);
 
@@ -973,17 +974,17 @@ public:
     // Prepare for and cleanup after one or more collection(s).
     bool PrepareForCollection(nsCycleCollectorResults *aResults,
                               nsTArray<PtrInfo*> *aWhiteNodes);
     void FixGrayBits(bool aForceGC);
     bool ShouldMergeZones(ccType aCCType);
     void CleanupAfterCollection();
 
     // Start and finish an individual collection.
-    bool BeginCollection(ccType aCCType, nsICycleCollectorListener *aListener);
+    void BeginCollection(ccType aCCType, nsICycleCollectorListener *aListener);
     bool FinishCollection(nsICycleCollectorListener *aListener);
 
     bool FreeSnowWhite(bool aUntilNoSWInPurpleBuffer);
 
     uint32_t SuspectedCount();
     void Shutdown();
 
     void ClearGraph()
@@ -1558,17 +1559,16 @@ private:
 
 public:
     GCGraphBuilder(nsCycleCollector *aCollector,
                    GCGraph &aGraph,
                    CycleCollectedJSRuntime *aJSRuntime,
                    nsICycleCollectorListener *aListener,
                    bool aMergeZones);
     ~GCGraphBuilder();
-    bool Initialized();
 
     bool WantAllTraces() const
     {
         return nsCycleCollectionNoteRootCallback::WantAllTraces();
     }
 
     uint32_t Count() const { return mPtrToNodeMap.entryCount; }
 
@@ -1652,18 +1652,17 @@ GCGraphBuilder::GCGraphBuilder(nsCycleCo
       mJSParticipant(nullptr),
       mJSZoneParticipant(nullptr),
       mListener(aListener),
       mMergeZones(aMergeZones),
       mRanOutOfMemory(false)
 {
     if (!PL_DHashTableInit(&mPtrToNodeMap, &PtrNodeOps, nullptr,
                            sizeof(PtrToNodeEntry), 32768)) {
-        mPtrToNodeMap.ops = nullptr;
-        mRanOutOfMemory = true;
+        MOZ_CRASH();
     }
 
     if (aJSRuntime) {
         mJSParticipant = aJSRuntime->GCThingParticipant();
         mJSZoneParticipant = aJSRuntime->ZoneParticipant();
     }
 
     uint32_t flags = 0;
@@ -1686,22 +1685,16 @@ GCGraphBuilder::GCGraphBuilder(nsCycleCo
 }
 
 GCGraphBuilder::~GCGraphBuilder()
 {
     if (mPtrToNodeMap.ops)
         PL_DHashTableFinish(&mPtrToNodeMap);
 }
 
-bool
-GCGraphBuilder::Initialized()
-{
-    return !!mPtrToNodeMap.ops;
-}
-
 PtrInfo*
 GCGraphBuilder::AddNode(void *s, nsCycleCollectionParticipant *aParticipant)
 {
     PtrToNodeEntry *e = static_cast<PtrToNodeEntry*>(PL_DHashTableOperate(&mPtrToNodeMap, s, PL_DHASH_ADD));
     if (!e) {
         mRanOutOfMemory = true;
         return nullptr;
     }
@@ -1891,22 +1884,22 @@ GCGraphBuilder::NoteWeakMapping(void *ma
 
     if (mListener) {
         mListener->NoteWeakMapEntry((uint64_t)map, (uint64_t)key,
                                     (uint64_t)kdelegate, (uint64_t)val);
     }
 }
 
 static bool
-AddPurpleRoot(GCGraphBuilder &builder, void *root, nsCycleCollectionParticipant *cp)
+AddPurpleRoot(GCGraphBuilder &aBuilder, void *aRoot, nsCycleCollectionParticipant *aParti)
 {
-    CanonicalizeParticipant(&root, &cp);
-
-    if (builder.WantAllTraces() || !cp->CanSkipInCC(root)) {
-        PtrInfo *pinfo = builder.AddNode(root, cp);
+    CanonicalizeParticipant(&aRoot, &aParti);
+
+    if (aBuilder.WantAllTraces() || !aParti->CanSkipInCC(aRoot)) {
+        PtrInfo *pinfo = aBuilder.AddNode(aRoot, aParti);
         if (!pinfo) {
             return false;
         }
     }
 
     return true;
 }
 
@@ -2015,17 +2008,17 @@ public:
             CanonicalizeParticipant(&o, &cp);
             SnowWhiteObject swo = { o, cp, aEntry->mRefCnt };
             if (mObjects.AppendElement(swo)) {
                 aBuffer.Remove(aEntry);
             }
         }
     }
 
-    bool HasSnowWhiteObjects()
+    bool HasSnowWhiteObjects() const
     {
       return mObjects.Length() > 0;
     }
 private:
     FallibleTArray<SnowWhiteObject> mObjects;
 };
 
 class RemoveSkippableVisitor : public SnowWhiteKiller
@@ -2094,64 +2087,63 @@ nsPurpleBuffer::RemoveSkippable(nsCycleC
     RemoveSkippableVisitor visitor(aCollector, Count(), aRemoveChildlessNodes,
                                    aAsyncSnowWhiteFreeing, aCb);
     VisitEntries(visitor);
 }
 
 bool
 nsCycleCollector::FreeSnowWhite(bool aUntilNoSWInPurpleBuffer)
 {
+    CheckThreadSafety();
+
     bool hadSnowWhiteObjects = false;
     do {
         SnowWhiteKiller visitor(mPurpleBuf.Count());
         mPurpleBuf.VisitEntries(visitor);
         hadSnowWhiteObjects = hadSnowWhiteObjects ||
                               visitor.HasSnowWhiteObjects();
         if (!visitor.HasSnowWhiteObjects()) {
             break;
         }
     } while (aUntilNoSWInPurpleBuffer);
     return hadSnowWhiteObjects;
 }
 
 void
-nsCycleCollector::SelectPurple(GCGraphBuilder &builder)
-{
-    mPurpleBuf.SelectPointers(builder);
-}
-
-void
 nsCycleCollector::ForgetSkippable(bool aRemoveChildlessNodes,
                                   bool aAsyncSnowWhiteFreeing)
 {
+    CheckThreadSafety();
     if (mJSRuntime) {
         mJSRuntime->PrepareForForgetSkippable();
     }
     mPurpleBuf.RemoveSkippable(this, aRemoveChildlessNodes,
                                aAsyncSnowWhiteFreeing, mForgetSkippableCB);
 }
 
 MOZ_NEVER_INLINE void
-nsCycleCollector::MarkRoots(GCGraphBuilder &builder)
+nsCycleCollector::MarkRoots(GCGraphBuilder &aBuilder)
 {
-    mGraph.mRootCount = builder.Count();
+    mGraph.mRootCount = aBuilder.Count();
 
     // read the PtrInfo out of the graph that we are building
     NodePool::Enumerator queue(mGraph.mNodes);
     while (!queue.IsDone()) {
         PtrInfo *pi = queue.GetNext();
         CC_AbortIfNull(pi);
-        builder.Traverse(pi);
-        if (queue.AtBlockEnd())
-            builder.SetLastChild();
+        aBuilder.Traverse(pi);
+        if (queue.AtBlockEnd()) {
+            aBuilder.SetLastChild();
+        }
     }
-    if (mGraph.mRootCount > 0)
-        builder.SetLastChild();
-
-    if (builder.RanOutOfMemory()) {
+    if (mGraph.mRootCount > 0) {
+        aBuilder.SetLastChild();
+    }
+
+    if (aBuilder.RanOutOfMemory()) {
         NS_ASSERTION(false,
                      "Ran out of memory while building cycle collector graph");
         Telemetry::Accumulate(Telemetry::CYCLE_COLLECTOR_OOM, true);
     }
 }
 
 
 ////////////////////////////////////////////////////////////////////////
@@ -2591,20 +2583,16 @@ nsCycleCollector::FixGrayBits(bool aForc
         Telemetry::Accumulate(Telemetry::CYCLE_COLLECTOR_NEED_GC, needGC);
         if (!needGC)
             return;
         if (mResults)
             mResults->mForcedGC = true;
     }
 
     TimeLog timeLog;
-
-    // mJSRuntime->Collect() must be called from the main thread,
-    // because it invokes XPCJSRuntime::GCCallback(cx, JSGC_BEGIN)
-    // which returns false if not in the main thread.
     mJSRuntime->Collect(aForceGC ? JS::gcreason::SHUTDOWN_CC : JS::gcreason::CC_FORCED);
     timeLog.Checkpoint("GC()");
 }
 
 bool
 nsCycleCollector::PrepareForCollection(nsCycleCollectorResults *aResults,
                                        nsTArray<PtrInfo*> *aWhiteNodes)
 {
@@ -2680,19 +2668,20 @@ nsCycleCollector::ShutdownCollect(nsICyc
     for (uint32_t i = 0; i < DEFAULT_SHUTDOWN_COLLECTIONS; ++i) {
         NS_ASSERTION(i < NORMAL_SHUTDOWN_COLLECTIONS, "Extra shutdown CC");
 
         // Synchronous cycle collection. Always force a JS GC beforehand.
         FixGrayBits(true);
         if (aListener && NS_FAILED(aListener->Begin()))
             aListener = nullptr;
         FreeSnowWhite(true);
-        if (!(BeginCollection(ShutdownCC, aListener) &&
-              FinishCollection(aListener)))
+        BeginCollection(ShutdownCC, aListener);
+        if (!FinishCollection(aListener)) {
             break;
+        }
     }
 
     CleanupAfterCollection();
 }
 
 void
 nsCycleCollector::Collect(ccType aCCType,
                           nsCycleCollectorResults *aResults,
@@ -2715,20 +2704,17 @@ nsCycleCollector::Collect(ccType aCCType
     }
 
     FreeSnowWhite(true);
 
     if (aListener && NS_FAILED(aListener->Begin())) {
         aListener = nullptr;
     }
 
-    if (!BeginCollection(aCCType, aListener)) {
-        return;
-    }
-
+    BeginCollection(aCCType, aListener);
     FinishCollection(aListener);
     CleanupAfterCollection();
 }
 
 // Don't merge too many times in a row, and do at least a minimum
 // number of unmerged CCs in a row.
 static const uint32_t kMinConsecutiveUnmerged = 3;
 static const uint32_t kMaxConsecutiveMerged = 3;
@@ -2758,45 +2744,39 @@ nsCycleCollector::ShouldMergeZones(ccTyp
         mMergedInARow++;
         return true;
     } else {
         mMergedInARow = 0;
         return false;
     }
 }
 
-bool
+void
 nsCycleCollector::BeginCollection(ccType aCCType,
                                   nsICycleCollectorListener *aListener)
 {
     // aListener should be Begin()'d before this
     TimeLog timeLog;
 
     bool mergeZones = ShouldMergeZones(aCCType);
     if (mResults) {
         mResults->mMergedZones = mergeZones;
     }
 
     GCGraphBuilder builder(this, mGraph, mJSRuntime, aListener,
                            mergeZones);
-    if (!builder.Initialized()) {
-        NS_ASSERTION(false, "Failed to initialize GCGraphBuilder, will probably leak.");
-        Telemetry::Accumulate(Telemetry::CYCLE_COLLECTOR_OOM, true);
-        return false;
-    }
 
     if (mJSRuntime) {
         mJSRuntime->BeginCycleCollection(builder);
         timeLog.Checkpoint("mJSRuntime->BeginCycleCollection()");
     }
 
     mScanInProgress = true;
-    SelectPurple(builder);
-
-    timeLog.Checkpoint("SelectPurple()");
+    mPurpleBuf.SelectPointers(builder);
+    timeLog.Checkpoint("SelectPointers()");
 
     if (builder.Count() > 0) {
         // The main Bacon & Rajan collection algorithm.
 
         MarkRoots(builder);
         timeLog.Checkpoint("MarkRoots()");
 
         ScanRoots();
@@ -2816,18 +2796,16 @@ nsCycleCollector::BeginCollection(ccType
                     aListener->DescribeRoot((uint64_t)pi->mPointer,
                                             pi->mInternalRefs);
                 }
             }
         }
     } else {
         mScanInProgress = false;
     }
-
-    return true;
 }
 
 bool
 nsCycleCollector::FinishCollection(nsICycleCollectorListener *aListener)
 {
     TimeLog timeLog;
     bool collected = CollectWhite(aListener);
     timeLog.Checkpoint("CollectWhite()");
@@ -2837,22 +2815,25 @@ nsCycleCollector::FinishCollection(nsICy
     timeLog.Checkpoint("ClearGraph()");
 
     return collected;
 }
 
 uint32_t
 nsCycleCollector::SuspectedCount()
 {
+    CheckThreadSafety();
     return mPurpleBuf.Count();
 }
 
 void
 nsCycleCollector::Shutdown()
 {
+    CheckThreadSafety();
+
     // Always delete snow white objects.
     FreeSnowWhite(true);
 
 #ifndef DEBUG
     if (PR_GetEnv("XPCOM_CC_RUN_DURING_SHUTDOWN"))
 #endif
     {
         nsCOMPtr<nsCycleCollectorLogger> listener;
@@ -3209,17 +3190,16 @@ nsCycleCollector_collect(bool aManuallyT
 void
 nsCycleCollector_shutdown()
 {
     CollectorData *data = sCollectorData.get();
 
     if (data) {
         MOZ_ASSERT(data->mCollector);
         PROFILER_LABEL("CC", "nsCycleCollector_shutdown");
-        data->mCollector->CheckThreadSafety();
         data->mCollector->Shutdown();
         delete data->mCollector;
         data->mCollector = nullptr;
         if (!data->mRuntime) {
           delete data;
           sCollectorData.set(nullptr);
         }
     }