merge backout
authorMats Palmgren <matspal@gmail.com>
Thu, 17 Apr 2014 15:10:44 +0000
changeset 197642 3f6c842e8180f279d145d80d14270125c7fd785e
parent 197641 70862f5149c6aabc9a92739ec98bc99735754516 (current diff)
parent 197640 feded4c79308a7f972aacbec7e0c61d157482b7c (diff)
child 197643 7340e1b5c7e18016583e6c721edc2cc57bb37263
push idunknown
push userunknown
push dateunknown
milestone31.0a1
merge backout
layout/generic/nsFrame.cpp
layout/reftests/bugs/reftest.list
layout/reftests/reftest.list
--- a/CLOBBER
+++ b/CLOBBER
@@ -17,9 +17,9 @@
 #
 # Modifying this file will now automatically clobber the buildbot machines \o/
 #
 
 # Are you updating CLOBBER because you think it's needed for your WebIDL
 # changes to stick? As of bug 928195, this shouldn't be necessary! Please
 # don't change CLOBBER for WebIDL changes any more.
 
-Bug 916012 moves definition from one WEBIDL_FILE to another (Bug 979886)
+Bug 995411 moves some files around in gfx/layers and widget/xpwidget
--- a/content/media/gstreamer/GStreamerFormatHelper.cpp
+++ b/content/media/gstreamer/GStreamerFormatHelper.cpp
@@ -25,20 +25,18 @@ GStreamerFormatHelper* GStreamerFormatHe
 
     gInstance = new GStreamerFormatHelper();
   }
 
   return gInstance;
 }
 
 void GStreamerFormatHelper::Shutdown() {
-  if (gInstance) {
-    delete gInstance;
-    gInstance = nullptr;
-  }
+  delete gInstance;
+  gInstance = nullptr;
 }
 
 static char const *const sContainers[6][2] = {
   {"video/mp4", "video/quicktime"},
   {"video/quicktime", "video/quicktime"},
   {"audio/mp4", "audio/x-m4a"},
   {"audio/x-m4a", "audio/x-m4a"},
   {"audio/mpeg", "audio/mpeg, mpegversion=(int)1"},
--- a/content/media/omx/AudioOutput.cpp
+++ b/content/media/omx/AudioOutput.cpp
@@ -175,20 +175,18 @@ void AudioOutput::Pause()
   }
 }
 
 void AudioOutput::Close()
 {
   AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("%s", __PRETTY_FUNCTION__));
   mTrack.clear();
 
-  if (mCallbackData) {
-    delete mCallbackData;
-    mCallbackData = NULL;
-  }
+  delete mCallbackData;
+  mCallbackData = nullptr;
 }
 
 // static
 void AudioOutput::CallbackWrapper(int aEvent, void* aCookie, void* aInfo)
 {
   CallbackData* data = (CallbackData*) aCookie;
   data->Lock();
   AudioOutput* me = data->GetOutput();
--- a/content/media/plugins/MediaPluginHost.cpp
+++ b/content/media/plugins/MediaPluginHost.cpp
@@ -318,15 +318,13 @@ MediaPluginHost *GetMediaPluginHost()
   if (!sMediaPluginHost) {
     sMediaPluginHost = new MediaPluginHost();
   }
   return sMediaPluginHost;
 }
 
 void MediaPluginHost::Shutdown()
 {
-  if (sMediaPluginHost) {
-    delete sMediaPluginHost;
-    sMediaPluginHost = nullptr;
-  }
+  delete sMediaPluginHost;
+  sMediaPluginHost = nullptr;
 }
 
 } // namespace mozilla
--- a/content/media/webrtc/MediaEngineWebRTCAudio.cpp
+++ b/content/media/webrtc/MediaEngineWebRTCAudio.cpp
@@ -463,20 +463,17 @@ void
 MediaEngineWebRTCAudioSource::Shutdown()
 {
   if (!mInitDone) {
     // duplicate these here in case we failed during Init()
     if (mChannel != -1) {
       mVoENetwork->DeRegisterExternalTransport(mChannel);
     }
 
-    if (mNullTransport) {
-      delete mNullTransport;
-    }
-
+    delete mNullTransport;
     return;
   }
 
   if (mState == kStarted) {
     while (!mSources.IsEmpty()) {
       Stop(mSources[0], kAudioTrack); // XXX change to support multiple tracks
     }
     MOZ_ASSERT(mState == kStopped);
@@ -486,19 +483,17 @@ MediaEngineWebRTCAudioSource::Shutdown()
     Deallocate();
   }
 
   mVoEBase->Terminate();
   if (mChannel != -1) {
     mVoENetwork->DeRegisterExternalTransport(mChannel);
   }
 
-  if (mNullTransport) {
-    delete mNullTransport;
-  }
+  delete mNullTransport;
 
   mVoEProcessing = nullptr;
   mVoENetwork = nullptr;
   mVoERender = nullptr;
   mVoEBase = nullptr;
 
   mState = kReleased;
   mInitDone = false;
--- a/editor/reftests/xul/reftest.list
+++ b/editor/reftests/xul/reftest.list
@@ -1,29 +1,29 @@
-fails-if(Android||B2G) == empty-1.xul empty-ref.xul # bug 783658
-!= empty-2.xul empty-ref.xul
+fails-if(Android||B2G) skip-if(B2G&&browserIsRemote) == empty-1.xul empty-ref.xul # bug 783658
+skip-if(B2G&&browserIsRemote) != empty-2.xul empty-ref.xul
 # There is no way to simulate an autocomplete textbox in windows XP/Vista/7 default theme using CSS.
 # Therefore, the equlity tests below should be marked as failing.
-fails-if(Android||B2G) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012])/.test(http.oscpu)) == autocomplete-1.xul autocomplete-ref.xul # bug 783658
-fails-if(Android||B2G) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012])/.test(http.oscpu)) == emptyautocomplete-1.xul emptyautocomplete-ref.xul # bug 783658
-!= emptymultiline-1.xul emptymultiline-ref.xul
-fails-if(Android||B2G) == emptymultiline-2.xul emptymultiline-ref.xul # bug 783658
-fails-if(Android||B2G) == emptytextbox-1.xul emptytextbox-ref.xul # bug 783658
-fails-if(Android||B2G) == emptytextbox-2.xul emptytextbox-ref.xul # bug 783658
-!= emptytextbox-3.xul emptytextbox-ref.xul
-!= emptytextbox-4.xul emptytextbox-ref.xul
-fails-if(Android||B2G) == emptytextbox-5.xul emptytextbox-ref.xul # bug 783658
+fails-if(Android||B2G) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012])/.test(http.oscpu)) skip-if(B2G&&browserIsRemote) == autocomplete-1.xul autocomplete-ref.xul # bug 783658
+fails-if(Android||B2G) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012])/.test(http.oscpu)) skip-if(B2G&&browserIsRemote) == emptyautocomplete-1.xul emptyautocomplete-ref.xul # bug 783658
+skip-if(B2G&&browserIsRemote) != emptymultiline-1.xul emptymultiline-ref.xul
+fails-if(Android||B2G) skip-if(B2G&&browserIsRemote) == emptymultiline-2.xul emptymultiline-ref.xul # bug 783658
+fails-if(Android||B2G) skip-if(B2G&&browserIsRemote) == emptytextbox-1.xul emptytextbox-ref.xul # bug 783658
+fails-if(Android||B2G) skip-if(B2G&&browserIsRemote) == emptytextbox-2.xul emptytextbox-ref.xul # bug 783658
+skip-if(B2G&&browserIsRemote) != emptytextbox-3.xul emptytextbox-ref.xul
+skip-if(B2G&&browserIsRemote) != emptytextbox-4.xul emptytextbox-ref.xul
+fails-if(Android||B2G) skip-if(B2G&&browserIsRemote) == emptytextbox-5.xul emptytextbox-ref.xul # bug 783658
 # There is no way to simulate a number textbox in windows XP/Vista/7 default theme using CSS.
 # Therefore, the equlity tests below should be marked as failing.
-!= number-1.xul number-ref.xul
-!= number-2.xul number-ref.xul
-fails-if(Android||B2G) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012])/.test(http.oscpu)) == number-3.xul number-ref.xul # bug 783658
-!= number-4.xul number-ref.xul
-fails-if(Android||B2G) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012])/.test(http.oscpu)) == number-5.xul number-ref.xul # bug 783658
-fails-if(Android||B2G) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012])/.test(http.oscpu)) == numberwithvalue-1.xul numberwithvalue-ref.xul # bug 783658
-fails-if(Android||B2G) == passwd-1.xul passwd-ref.xul # bug 783658
-fails-if(Android||B2G) == passwd-2.xul passwd-ref.xul # bug 783658
-!= passwd-3.xul passwd-ref.xul
-fails-if(Android||B2G) == plain-1.xul plain-ref.xul # bug 783658
-fails-if(Android||B2G) == textbox-1.xul textbox-ref.xul
-!= textbox-disabled.xul textbox-ref.xul
+skip-if(B2G&&browserIsRemote) != number-1.xul number-ref.xul
+skip-if(B2G&&browserIsRemote) != number-2.xul number-ref.xul
+fails-if(Android||B2G) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012])/.test(http.oscpu)) skip-if(B2G&&browserIsRemote) == number-3.xul number-ref.xul # bug 783658
+skip-if(B2G&&browserIsRemote) != number-4.xul number-ref.xul
+fails-if(Android||B2G) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012])/.test(http.oscpu)) skip-if(B2G&&browserIsRemote) == number-5.xul number-ref.xul # bug 783658
+fails-if(Android||B2G) fails-if(windowsDefaultTheme&&/^Windows\x20NT\x20(5\.[12]|6\.[012])/.test(http.oscpu)) skip-if(B2G&&browserIsRemote) == numberwithvalue-1.xul numberwithvalue-ref.xul # bug 783658
+fails-if(Android||B2G) skip-if(B2G&&browserIsRemote) == passwd-1.xul passwd-ref.xul # bug 783658
+fails-if(Android||B2G) skip-if(B2G&&browserIsRemote) == passwd-2.xul passwd-ref.xul # bug 783658
+skip-if(B2G&&browserIsRemote) != passwd-3.xul passwd-ref.xul
+fails-if(Android||B2G) skip-if(B2G&&browserIsRemote) == plain-1.xul plain-ref.xul # bug 783658
+fails-if(Android||B2G) skip-if(B2G&&browserIsRemote) == textbox-1.xul textbox-ref.xul
+skip-if(B2G&&browserIsRemote) != textbox-disabled.xul textbox-ref.xul
 # Read-only textboxes look like normal textboxes in windows Vista/7 default theme
-fails-if(windowsDefaultTheme&&/^Windows\x20NT\x206\.[012]/.test(http.oscpu)) != textbox-readonly.xul textbox-ref.xul
+fails-if(windowsDefaultTheme&&/^Windows\x20NT\x206\.[012]/.test(http.oscpu)) skip-if(B2G&&browserIsRemote) != textbox-readonly.xul textbox-ref.xul
--- a/gfx/thebes/gfxMacPlatformFontList.mm
+++ b/gfx/thebes/gfxMacPlatformFontList.mm
@@ -825,23 +825,23 @@ gfxMacPlatformFontList::RegisteredFontsC
                                                                    CFStringRef name,
                                                                    const void *object,
                                                                    CFDictionaryRef userInfo)
 {
     if (!::CFEqual(name, kCTFontManagerRegisteredFontsChangedNotification)) {
         return;
     }
 
+    gfxMacPlatformFontList* fl = static_cast<gfxMacPlatformFontList*>(observer);
+
     // xxx - should be carefully pruning the list of fonts, not rebuilding it from scratch
-    static_cast<gfxMacPlatformFontList*>(observer)->UpdateFontList();
+    fl->UpdateFontList();
 
     // modify a preference that will trigger reflow everywhere
-    static const char kPrefName[] = "font.internaluseonly.changed";
-    bool fontInternalChange = Preferences::GetBool(kPrefName, false);
-    Preferences::SetBool(kPrefName, !fontInternalChange);
+    fl->ForceGlobalReflow();
 }
 
 gfxFontEntry*
 gfxMacPlatformFontList::GlobalFontFallback(const uint32_t aCh,
                                            int32_t aRunScript,
                                            const gfxFontStyle* aMatchStyle,
                                            uint32_t& aCmapCount,
                                            gfxFontFamily** aMatchedFamily)
--- a/gfx/thebes/gfxPlatformFontList.cpp
+++ b/gfx/thebes/gfxPlatformFontList.cpp
@@ -4,16 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifdef MOZ_LOGGING
 #define FORCE_PR_LOG /* Allow logging in the release build */
 #endif
 #include "prlog.h"
 
 #include "gfxPlatformFontList.h"
+#include "gfxUserFontSet.h"
 
 #include "nsUnicharUtils.h"
 #include "nsUnicodeRange.h"
 #include "nsUnicodeProperties.h"
 
 #include "mozilla/Attributes.h"
 #include "mozilla/Likely.h"
 #include "mozilla/MemoryReporting.h"
@@ -298,16 +299,31 @@ gfxPlatformFontList::ResolveFontName(con
     gfxFontFamily *family = FindFamily(aFontName);
     if (family) {
         aResolvedFontName = family->Name();
         return true;
     }
     return false;
 }
 
+static PLDHashOperator
+RebuildLocalFonts(nsPtrHashKey<gfxUserFontSet>* aKey,
+                  void* aClosure)
+{
+    aKey->GetKey()->RebuildLocalRules();
+    return PL_DHASH_NEXT;
+}
+
+void
+gfxPlatformFontList::UpdateFontList()
+{
+    InitFontList();
+    mUserFontSetList.EnumerateEntries(RebuildLocalFonts, nullptr);
+}
+
 struct FontListData {
     FontListData(nsIAtom *aLangGroup,
                  const nsACString& aGenericFamily,
                  nsTArray<nsString>& aListOfFonts) :
         mLangGroup(aLangGroup), mGenericFamily(aGenericFamily),
         mListOfFonts(aListOfFonts) {}
     nsIAtom *mLangGroup;
     const nsACString& mGenericFamily;
@@ -792,16 +808,21 @@ gfxPlatformFontList::LoadFontInfo()
 #ifdef PR_LOGGING
     if (LOG_FONTINIT_ENABLED()) {
         TimeDuration elapsed = TimeStamp::Now() - start;
         LOG_FONTINIT(("(fontinit) fontloader load pass %8.2f ms done %s\n",
                       elapsed.ToMilliseconds(), (done ? "true" : "false")));
     }
 #endif
 
+    if (done) {
+        mOtherFamilyNamesInitialized = true;
+        mFaceNamesInitialized = true;
+    }
+
     return done;
 }
 
 void 
 gfxPlatformFontList::CleanupLoader()
 {
     mFontFamiliesToLoad.Clear();
     mNumFamilies = 0;
@@ -815,18 +836,16 @@ gfxPlatformFontList::CleanupLoader()
                       mFontInfo->mLoadStats.families,
                       mFontInfo->mLoadStats.fonts,
                       mFontInfo->mLoadStats.cmaps,
                       mFontInfo->mLoadStats.facenames,
                       mFontInfo->mLoadStats.othernames));
     }
 #endif
 
-    mOtherFamilyNamesInitialized = true;
-    mFaceNamesInitialized = true;
     gfxFontInfoLoader::CleanupLoader();
 }
 
 void
 gfxPlatformFontList::GetPrefsAndStartLoader()
 {
     mIncrement =
         std::max(1u, Preferences::GetUint(FONT_LOADER_FAMILIES_PER_SLICE_PREF));
@@ -834,16 +853,25 @@ gfxPlatformFontList::GetPrefsAndStartLoa
     uint32_t delay =
         std::max(1u, Preferences::GetUint(FONT_LOADER_DELAY_PREF));
     uint32_t interval =
         std::max(1u, Preferences::GetUint(FONT_LOADER_INTERVAL_PREF));
 
     StartLoader(delay, interval);
 }
 
+void
+gfxPlatformFontList::ForceGlobalReflow()
+{
+    // modify a preference that will trigger reflow everywhere
+    static const char kPrefName[] = "font.internaluseonly.changed";
+    bool fontInternalChange = Preferences::GetBool(kPrefName, false);
+    Preferences::SetBool(kPrefName, !fontInternalChange);
+}
+
 // Support for memory reporting
 
 static size_t
 SizeOfFamilyEntryExcludingThis(const nsAString&               aKey,
                                const nsRefPtr<gfxFontFamily>& aFamily,
                                MallocSizeOf                   aMallocSizeOf,
                                void*                          aUserArg)
 {
--- a/gfx/thebes/gfxPlatformFontList.h
+++ b/gfx/thebes/gfxPlatformFontList.h
@@ -77,16 +77,18 @@ protected:
 struct FontListSizes {
     uint32_t mFontListSize; // size of the font list and dependent objects
                             // (font family and face names, etc), but NOT
                             // including the font table cache and the cmaps
     uint32_t mFontTableCacheSize; // memory used for the gfxFontEntry table caches
     uint32_t mCharMapsSize; // memory used for cmap coverage info
 };
 
+class gfxUserFontSet;
+
 class gfxPlatformFontList : public gfxFontInfoLoader
 {
 public:
     static gfxPlatformFontList* PlatformFontList() {
         return sPlatformFontList;
     }
 
     static nsresult Init() {
@@ -110,17 +112,17 @@ public:
 
     void GetFontList (nsIAtom *aLangGroup,
                       const nsACString& aGenericFamily,
                       nsTArray<nsString>& aListOfFonts);
 
     virtual bool ResolveFontName(const nsAString& aFontName,
                                    nsAString& aResolvedFontName);
 
-    void UpdateFontList() { InitFontList(); }
+    void UpdateFontList();
 
     void ClearPrefFonts() { mPrefFonts.Clear(); }
 
     virtual void GetFontFamilyList(nsTArray<nsRefPtr<gfxFontFamily> >& aFamilyArray);
 
     virtual gfxFontEntry*
     SystemFindFontForChar(const uint32_t aCh,
                           int32_t aRunScript,
@@ -173,16 +175,25 @@ public:
     gfxCharacterMap* FindCharMap(gfxCharacterMap *aCmap);
 
     // add a cmap to the shared cmap set
     gfxCharacterMap* AddCmap(const gfxCharacterMap *aCharMap);
 
     // remove the cmap from the shared cmap set
     void RemoveCmap(const gfxCharacterMap *aCharMap);
 
+    // keep track of userfont sets to notify when global fontlist changes occur
+    void AddUserFontSet(gfxUserFontSet *aUserFontSet) {
+        mUserFontSetList.PutEntry(aUserFontSet);
+    }
+
+    void RemoveUserFontSet(gfxUserFontSet *aUserFontSet) {
+        mUserFontSetList.RemoveEntry(aUserFontSet);
+    }
+
 protected:
     class MemoryReporter MOZ_FINAL : public nsIMemoryReporter
     {
     public:
         NS_DECL_ISUPPORTS
         NS_DECL_NSIMEMORYREPORTER
     };
 
@@ -249,16 +260,19 @@ protected:
     // gfxFontInfoLoader overrides, used to load in font cmaps
     virtual void InitLoader();
     virtual bool LoadFontInfo();
     virtual void CleanupLoader();
 
     // read the loader initialization prefs, and start it
     void GetPrefsAndStartLoader();
 
+    // for font list changes that affect all documents
+    void ForceGlobalReflow();
+
     // used by memory reporter to accumulate sizes of family names in the hash
     static size_t
     SizeOfFamilyNameEntryExcludingThis(const nsAString&               aKey,
                                        const nsRefPtr<gfxFontFamily>& aFamily,
                                        mozilla::MallocSizeOf          aMallocSizeOf,
                                        void*                          aUserArg);
 
     // canonical family name ==> family entry (unique, one name per family entry)
@@ -300,11 +314,13 @@ protected:
     // contains weak ptrs to cmaps shared by font entry objects
     nsTHashtable<CharMapHashKey> mSharedCmaps;
 
     // data used as part of the font cmap loading process
     nsTArray<nsRefPtr<gfxFontFamily> > mFontFamiliesToLoad;
     uint32_t mStartIndex;
     uint32_t mIncrement;
     uint32_t mNumFamilies;
+
+    nsTHashtable<nsPtrHashKey<gfxUserFontSet> > mUserFontSetList;
 };
 
 #endif /* GFXPLATFORMFONTLIST_H_ */
--- a/gfx/thebes/gfxUserFontSet.cpp
+++ b/gfx/thebes/gfxUserFontSet.cpp
@@ -13,16 +13,17 @@
 #include "nsUnicharUtils.h"
 #include "nsNetUtil.h"
 #include "nsICacheService.h"
 #include "nsIProtocolHandler.h"
 #include "nsIPrincipal.h"
 #include "gfxFontConstants.h"
 #include "mozilla/Services.h"
 #include "mozilla/gfx/2D.h"
+#include "gfxPlatformFontList.h"
 
 #include "opentype-sanitiser.h"
 #include "ots-memory-stream.h"
 
 using namespace mozilla;
 
 #ifdef PR_LOGGING
 PRLogModuleInfo *
@@ -97,23 +98,31 @@ gfxProxyFontEntry::Matches(const nsTArra
 gfxFont*
 gfxProxyFontEntry::CreateFontInstance(const gfxFontStyle *aFontStyle, bool aNeedsBold)
 {
     // cannot create an actual font for a proxy entry
     return nullptr;
 }
 
 gfxUserFontSet::gfxUserFontSet()
-    : mFontFamilies(5)
+    : mFontFamilies(5), mLocalRulesUsed(false)
 {
     IncrementGeneration();
+    gfxPlatformFontList *fp = gfxPlatformFontList::PlatformFontList();
+    if (fp) {
+        fp->AddUserFontSet(this);
+    }
 }
 
 gfxUserFontSet::~gfxUserFontSet()
 {
+    gfxPlatformFontList *fp = gfxPlatformFontList::PlatformFontList();
+    if (fp) {
+        fp->RemoveUserFontSet(this);
+    }
 }
 
 gfxFontEntry*
 gfxUserFontSet::AddFontFace(const nsAString& aFamilyName,
                             const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
                             uint32_t aWeight,
                             int32_t aStretch,
                             uint32_t aItalicStyle,
@@ -534,16 +543,17 @@ gfxUserFontSet::LoadNext(gfxMixedFontFam
         const gfxFontFaceSrc& currSrc = aProxyEntry->mSrcList[aProxyEntry->mSrcIndex];
 
         // src local ==> lookup and load immediately
 
         if (currSrc.mIsLocal) {
             gfxFontEntry *fe =
                 gfxPlatform::GetPlatform()->LookupLocalFont(aProxyEntry,
                                                             currSrc.mLocalName);
+            mLocalRulesUsed = true;
             if (fe) {
                 LOG(("userfonts (%p) [src %d] loaded local: (%s) for (%s) gen: %8.8x\n",
                      this, aProxyEntry->mSrcIndex,
                      NS_ConvertUTF16toUTF8(currSrc.mLocalName).get(),
                      NS_ConvertUTF16toUTF8(aFamily->Name()).get(),
                      uint32_t(mGeneration)));
                 fe->mFeatureSettings.AppendElements(aProxyEntry->mFeatureSettings);
                 fe->mLanguageOverride = aProxyEntry->mLanguageOverride;
@@ -659,16 +669,23 @@ gfxUserFontSet::IncrementGeneration()
 {
     // add one, increment again if zero
     ++sFontSetGeneration;
     if (sFontSetGeneration == 0)
        ++sFontSetGeneration;
     mGeneration = sFontSetGeneration;
 }
 
+void
+gfxUserFontSet::RebuildLocalRules()
+{
+    if (mLocalRulesUsed) {
+        DoRebuildUserFontSet();
+    }
+}
 
 gfxFontEntry*
 gfxUserFontSet::LoadFont(gfxMixedFontFamily *aFamily,
                          gfxProxyFontEntry *aProxy,
                          const uint8_t *aFontData, uint32_t &aLength)
 {
     gfxFontEntry *fe = nullptr;
 
--- a/gfx/thebes/gfxUserFontSet.h
+++ b/gfx/thebes/gfxUserFontSet.h
@@ -237,16 +237,19 @@ public:
 
     // generation - each time a face is loaded, generation is
     // incremented so that the change can be recognized 
     uint64_t GetGeneration() { return mGeneration; }
 
     // increment the generation on font load
     void IncrementGeneration();
 
+    // rebuild if local rules have been used
+    void RebuildLocalRules();
+
     class UserFontCache {
     public:
         // Record a loaded user-font in the cache. This requires that the
         // font-entry's userFontData has been set up already, as it relies
         // on the URI and Principal recorded there.
         static void CacheFont(gfxFontEntry *aFontEntry);
 
         // The given gfxFontEntry is being destroyed, so remove any record that
@@ -413,21 +416,27 @@ protected:
                                         gfxProxyFontEntry *aProxy,
                                         const uint8_t* aData,
                                         uint32_t aLength,
                                         uint32_t& aSaneLength,
                                         bool aIsCompressed);
 
     static bool OTSMessage(void *aUserData, const char *format, ...);
 
+    // helper method for performing the actual userfont set rebuild
+    virtual void DoRebuildUserFontSet() = 0;
+
     // font families defined by @font-face rules
     nsRefPtrHashtable<nsStringHashKey, gfxMixedFontFamily> mFontFamilies;
 
     uint64_t        mGeneration;
 
+    // true when local names have been looked up, false otherwise
+    bool mLocalRulesUsed;
+
     static PRLogModuleInfo* GetUserFontsLog();
 
 private:
     static void CopyWOFFMetadata(const uint8_t* aFontData,
                                  uint32_t aLength,
                                  FallibleTArray<uint8_t>* aMetadata,
                                  uint32_t* aMetaOrigLen);
 };
--- a/image/test/reftest/bmp/bmp-corrupted/reftest.list
+++ b/image/test/reftest/bmp/bmp-corrupted/reftest.list
@@ -3,10 +3,10 @@
 == wrapper.html?invalid-signature.bmp about:blank
 == wrapper.html?invalid-bpp.bmp about:blank
 == wrapper.html?os2-invalid-bpp.bmp about:blank
 # Tests for an unsupported compression value
 == wrapper.html?invalid-compression.bmp about:blank
 # Tests for RLE4 with an invalid BPP
 == wrapper.html?invalid-compression-RLE4.bmp about:blank
 # Tests for RLE8 with an invalid BPP
-== wrapper.html?invalid-compression-RLE8.bmp about:blank
+random-if(B2G) == wrapper.html?invalid-compression-RLE8.bmp about:blank # Bug 921207
 
--- a/js/src/jit-test/tests/asm.js/testSource.js
+++ b/js/src/jit-test/tests/asm.js/testSource.js
@@ -232,16 +232,43 @@ if (isAsmJSCompilationAvailable() && isC
     var m = new Function('glob', 'ffi', 'heap', bodyOnly);
     assertEq(isAsmJSModuleLoadedFromCache(m), true);
     assertEq(m.toString(), "function anonymous(glob, ffi, heap) {\n" + bodyOnly + "\n}");
     assertEq(m.toSource(), "(function anonymous(glob, ffi, heap) {\n" + bodyOnly + "\n})");
 }
 
 })();
 
+/* Implicit "use strict" context */
+(function() {
+
+var funcHeader =  'function (glob, ffi, heap) {',
+    funcBody = '\n"use asm";\n\
+    function g() {}\n\
+    return g;\n\n'
+    funcFooter = '}',
+    funcSource = funcHeader + funcBody + funcFooter
+    useStrict = '\n"use strict";\n';
+
+var f4 = eval("\"use strict\";\n(" + funcSource + ")");
+
+var expectedToString = funcHeader + useStrict + funcBody + funcFooter
+var expectedToSource = '(' + expectedToString + ')'
+
+assertEq(f4.toString(), expectedToString);
+assertEq(f4.toSource(), expectedToSource);
+
+if (isAsmJSCompilationAvailable() && isCachingEnabled()) {
+    var f5 = eval("\"use strict\";\n(" + funcSource + ")");
+    assertEq(isAsmJSModuleLoadedFromCache(f5), true);
+    assertEq(f5.toString(), expectedToString);
+    assertEq(f5.toSource(), expectedToSource);
+}
+})();
+
 /* Functions */
 (function() {
 
 var noSrc = "function noArgument() {\n\
     return 42;\n\
 }"
 var oneSrc = "function oneArgument(x) {\n\
     x = x | 0;\n\
--- a/js/src/jit/AsmJS.cpp
+++ b/js/src/jit/AsmJS.cpp
@@ -1138,17 +1138,23 @@ class MOZ_STACK_CLASS ModuleCompiler
             !addStandardLibraryMathName("SQRT1_2", M_SQRT1_2) ||
             !addStandardLibraryMathName("SQRT2", M_SQRT2))
         {
             return false;
         }
 
         uint32_t funcStart = parser_.pc->maybeFunction->pn_body->pn_pos.begin;
         uint32_t offsetToEndOfUseAsm = parser_.tokenStream.currentToken().pos.end;
-        module_ = cx_->new_<AsmJSModule>(parser_.ss, funcStart, offsetToEndOfUseAsm);
+
+        // "use strict" should be added to the source if we are in an implicit
+        // strict context, see also comment above addUseStrict in
+        // js::FunctionToString.
+        bool strict = parser_.pc->sc->strict && !parser_.pc->sc->hasExplicitUseStrict();
+
+        module_ = cx_->new_<AsmJSModule>(parser_.ss, funcStart, offsetToEndOfUseAsm, strict);
         if (!module_)
             return false;
 
         return true;
     }
 
     bool failOffset(uint32_t offset, const char *str) {
         JS_ASSERT(!errorString_);
@@ -1509,17 +1515,16 @@ class MOZ_STACK_CLASS ModuleCompiler
                                slowFuns ? slowFuns.get() : ""));
 #endif
     }
 
     bool finish(ScopedJSDeletePtr<AsmJSModule> *module)
     {
         module_->initFuncEnd(parser_.tokenStream.currentToken().pos.end,
                              parser_.tokenStream.peekTokenPos().end);
-
         masm_.finish();
         if (masm_.oom())
             return false;
 
 #if defined(JS_CODEGEN_ARM)
         // Now that compilation has finished, we need to update offsets to
         // reflect actual offsets (an ARM distinction).
         for (unsigned i = 0; i < module_->numHeapAccesses(); i++) {
--- a/js/src/jit/AsmJSLink.cpp
+++ b/js/src/jit/AsmJSLink.cpp
@@ -795,18 +795,41 @@ js::AsmJSModuleToString(JSContext *cx, H
         if (!out.append(") {\n"))
             return nullptr;
     }
 
     Rooted<JSFlatString*> src(cx, source->substring(cx, begin, end));
     if (!src)
         return nullptr;
 
-    if (!out.append(src->chars(), src->length()))
-        return nullptr;
+    if (module.strict()) {
+        // We need to add "use strict" in the body right after the opening
+        // brace.
+        size_t bodyStart = 0, bodyEnd;
+
+        // No need to test for functions created with the Function ctor as
+        // these doesn't implicitly inherit the "use strict" context. Strict mode is
+        // enabled for functions created with the Function ctor only if they begin with
+        // the "use strict" directive, but these functions won't validate as asm.js
+        // modules.
+
+        ConstTwoByteChars chars(src->chars(), src->length());
+        if (!FindBody(cx, fun, chars, src->length(), &bodyStart, &bodyEnd))
+            return nullptr;
+
+        if (!out.append(chars, bodyStart) ||
+            !out.append("\n\"use strict\";\n") ||
+            !out.append(chars + bodyStart, src->length() - bodyStart))
+        {
+            return nullptr;
+        }
+    } else {
+        if (!out.append(src->chars(), src->length()))
+            return nullptr;
+    }
 
     if (funCtor && !out.append("\n}"))
         return nullptr;
 
     if (addParenToLambda && fun->isLambda() && !out.append(")"))
         return nullptr;
 
     return out.finishString();
--- a/js/src/jit/AsmJSModule.cpp
+++ b/js/src/jit/AsmJSModule.cpp
@@ -323,32 +323,34 @@ AsmJSModule::staticallyLink(ExclusiveCon
     // Initialize global data segment
 
     for (size_t i = 0; i < exits_.length(); i++) {
         exitIndexToGlobalDatum(i).exit = interpExitTrampoline(exits_[i]);
         exitIndexToGlobalDatum(i).fun = nullptr;
     }
 }
 
-AsmJSModule::AsmJSModule(ScriptSource *scriptSource, uint32_t funcStart, uint32_t offsetToEndOfUseAsm)
+AsmJSModule::AsmJSModule(ScriptSource *scriptSource, uint32_t funcStart,
+                         uint32_t offsetToEndOfUseAsm, bool strict)
   : globalArgumentName_(nullptr),
     importArgumentName_(nullptr),
     bufferArgumentName_(nullptr),
     code_(nullptr),
     interruptExit_(nullptr),
     dynamicallyLinked_(false),
     loadedFromCache_(false),
     funcStart_(funcStart),
     offsetToEndOfUseAsm_(offsetToEndOfUseAsm),
     scriptSource_(scriptSource),
     codeIsProtected_(false)
 {
     mozilla::PodZero(&pod);
     scriptSource_->incref();
     pod.minHeapLength_ = AsmJSAllocationGranularity;
+    pod.strict_ = strict;
 }
 
 AsmJSModule::~AsmJSModule()
 {
     scriptSource_->decref();
 
     if (code_) {
         for (unsigned i = 0; i < numExits(); i++) {
@@ -871,17 +873,17 @@ class AutoUnprotectCodeForClone
     }
 };
 
 bool
 AsmJSModule::clone(JSContext *cx, ScopedJSDeletePtr<AsmJSModule> *moduleOut) const
 {
     AutoUnprotectCodeForClone cloneGuard(cx, *this);
 
-    *moduleOut = cx->new_<AsmJSModule>(scriptSource_, funcStart_, offsetToEndOfUseAsm_);
+    *moduleOut = cx->new_<AsmJSModule>(scriptSource_, funcStart_, offsetToEndOfUseAsm_, pod.strict_);
     if (!*moduleOut)
         return false;
 
     AsmJSModule &out = **moduleOut;
 
     // Mirror the order of serialize/deserialize in cloning:
 
     out.pod = pod;
@@ -1308,18 +1310,19 @@ js::LookupAsmJSModuleInCache(ExclusiveCo
 
     ModuleCharsForLookup moduleChars;
     cursor = moduleChars.deserialize(cx, cursor);
     if (!moduleChars.match(parser))
         return true;
 
     uint32_t funcStart = parser.pc->maybeFunction->pn_body->pn_pos.begin;
     uint32_t offsetToEndOfUseAsm = parser.tokenStream.currentToken().pos.end;
+    bool strict = parser.pc->sc->strict && !parser.pc->sc->hasExplicitUseStrict();
     ScopedJSDeletePtr<AsmJSModule> module(
-        cx->new_<AsmJSModule>(parser.ss, funcStart, offsetToEndOfUseAsm));
+        cx->new_<AsmJSModule>(parser.ss, funcStart, offsetToEndOfUseAsm, strict));
     if (!module)
         return false;
     cursor = module->deserialize(cx, cursor);
     if (!cursor)
         return false;
 
     bool atEnd = cursor == entry.memory + entry.serializedSize;
     MOZ_ASSERT(atEnd, "Corrupt cache file");
--- a/js/src/jit/AsmJSModule.h
+++ b/js/src/jit/AsmJSModule.h
@@ -426,16 +426,17 @@ class AsmJSModule
 #endif
 #if defined(JS_ION_PERF)
     ProfiledBlocksFunctionVector          perfProfiledBlocksFunctions_;
 #endif
 
     struct Pod {
         uint32_t                          funcLength_;
         uint32_t                          funcLengthWithRightBrace_;
+        bool                              strict_;
         uint32_t                          numGlobalVars_;
         uint32_t                          numFFIs_;
         size_t                            funcPtrTableAndExitBytes_;
         bool                              hasArrayView_;
         size_t                            functionBytes_; // just the function bodies, no stubs
         size_t                            codeBytes_;     // function bodies and stubs
         size_t                            totalBytes_;    // function bodies, stubs, and global data
         uint32_t                          minHeapLength_;
@@ -459,17 +460,18 @@ class AsmJSModule
 
     FunctionCountsVector                  functionCounts_;
 
     // This field is accessed concurrently when requesting an interrupt.
     // Access must be synchronized via the runtime's interrupt lock.
     mutable bool                          codeIsProtected_;
 
   public:
-    explicit AsmJSModule(ScriptSource *scriptSource, uint32_t functStart, uint32_t offsetToEndOfUseAsm);
+    explicit AsmJSModule(ScriptSource *scriptSource, uint32_t functStart,
+                         uint32_t offsetToEndOfUseAsm, bool strict);
     ~AsmJSModule();
 
     void trace(JSTracer *trc) {
         for (unsigned i = 0; i < globals_.length(); i++)
             globals_[i].trace(trc);
         for (unsigned i = 0; i < exports_.length(); i++)
             exports_[i].trace(trc);
         for (unsigned i = 0; i < exits_.length(); i++) {
@@ -519,16 +521,19 @@ class AsmJSModule
         pod.funcLengthWithRightBrace_ = endAfterCurly - funcStart_;
     }
     uint32_t funcEndBeforeCurly() const {
         return funcStart_ + pod.funcLength_;
     }
     uint32_t funcEndAfterCurly() const {
         return funcStart_ + pod.funcLengthWithRightBrace_;
     }
+    bool strict() const {
+        return pod.strict_;
+    }
 
     bool addGlobalVarInit(const Value &v, AsmJSCoercion coercion, uint32_t *globalIndex) {
         JS_ASSERT(pod.funcPtrTableAndExitBytes_ == 0);
         if (pod.numGlobalVars_ == UINT32_MAX)
             return false;
         Global g(Global::Variable, nullptr);
         g.pod.u.var.initKind_ = Global::InitConstant;
         g.pod.u.var.init.constant_ = v;
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -621,24 +621,28 @@ const Class JSFunction::class_ = {
     fun_hasInstance,
     nullptr,                 /* construct   */
     fun_trace
 };
 
 const Class* const js::FunctionClassPtr = &JSFunction::class_;
 
 /* Find the body of a function (not including braces). */
-static bool
-FindBody(JSContext *cx, HandleFunction fun, ConstTwoByteChars chars, size_t length,
+bool
+js::FindBody(JSContext *cx, HandleFunction fun, ConstTwoByteChars chars, size_t length,
          size_t *bodyStart, size_t *bodyEnd)
 {
     // We don't need principals, since those are only used for error reporting.
     CompileOptions options(cx);
-    options.setFileAndLine("internal-findBody", 0)
-           .setVersion(fun->nonLazyScript()->getVersion());
+    options.setFileAndLine("internal-findBody", 0);
+
+    // For asm.js modules, there's no script.
+    if (fun->hasScript())
+        options.setVersion(fun->nonLazyScript()->getVersion());
+
     AutoKeepAtoms keepAtoms(cx->perThreadData);
     TokenStream ts(cx, options, chars.get(), length, nullptr);
     int nest = 0;
     bool onward = true;
     // Skip arguments list.
     do {
         switch (ts.getToken()) {
           case TOK_NAME:
--- a/js/src/jsfun.h
+++ b/js/src/jsfun.h
@@ -549,16 +549,21 @@ class FunctionExtended : public JSFuncti
     HeapValue extendedSlots[NUM_EXTENDED_SLOTS];
 };
 
 extern JSFunction *
 CloneFunctionObject(JSContext *cx, HandleFunction fun, HandleObject parent,
                     gc::AllocKind kind = JSFunction::FinalizeKind,
                     NewObjectKind newKindArg = GenericObject);
 
+
+extern bool
+FindBody(JSContext *cx, HandleFunction fun, ConstTwoByteChars chars, size_t length,
+         size_t *bodyStart, size_t *bodyEnd);
+
 } // namespace js
 
 inline js::FunctionExtended *
 JSFunction::toExtended()
 {
     JS_ASSERT(isExtended());
     return static_cast<js::FunctionExtended *>(this);
 }
--- a/layout/base/nsDisplayListInvalidation.cpp
+++ b/layout/base/nsDisplayListInvalidation.cpp
@@ -1,15 +1,16 @@
 /*-*- 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 "nsDisplayListInvalidation.h"
 #include "nsDisplayList.h"
+#include "nsIFrame.h"
 
 nsDisplayItemGeometry::nsDisplayItemGeometry(nsDisplayItem* aItem, nsDisplayListBuilder* aBuilder)
 {
   MOZ_COUNT_CTOR(nsDisplayItemGeometry);
   bool snap;
   mBounds = aItem->GetBounds(aBuilder, &snap);
 }
 
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -6685,18 +6685,18 @@ nsFrame::BreakWordBetweenPunctuation(con
   NS_ASSERTION(aPunctAfter != aState->mLastCharWasPunctuation,
                "Call this only at punctuation boundaries");
   if (aState->mLastCharWasWhitespace) {
     // We always stop between whitespace and punctuation
     return true;
   }
   if (!Preferences::GetBool("layout.word_select.stop_at_punctuation")) {
     // When this pref is false, we never stop at a punctuation boundary unless
-    // it's after whitespace
-    return false;
+    // it's followed by whitespace (in the relevant direction).
+    return aWhitespaceAfter;
   }
   if (!aIsKeyboardSelect) {
     // mouse caret movement (e.g. word selection) always stops at every punctuation boundary
     return true;
   }
   bool afterPunct = aForward ? aState->mLastCharWasPunctuation : aPunctAfter;
   if (!afterPunct) {
     // keyboard caret movement only stops after punctuation (in content order)
--- a/layout/generic/test/test_movement_by_words.html
+++ b/layout/generic/test/test_movement_by_words.html
@@ -9,41 +9,44 @@
 <body>
 <p id="display"></p>
 <div id="content" style="display: block">
 <div contentEditable id="editor"></div>
 </div>
 <p id="catch">Catch-all
 <pre id="test"><script class="testbody" type="text/javascript;version=1.7">
 
-/** Test for Bug 384147 **/
+/** Tests for bugs 384147 and 981281 **/
 
 SimpleTest.waitForExplicitFinish();
 
 SimpleTest.waitForFocus(function(){setTimeout(focusing, 0)});
 
 function focusing() {
   document.getElementById("editor").focus();
   // This seems to be necessary because the selection is not set up properly otherwise
   setTimeout(test, 0);
 }
 
 var eatSpace;
+var stopAtPunctuation;
 var wordModifiers =
     (navigator.platform.indexOf("Mac") >= 0) ? {altKey:true} : {ctrlKey:true};
 var sel = window.getSelection();
 var editor = document.getElementById("editor");
 
 function setPrefs(eat_space, stop_at_punctuation, callback) {
   eatSpace = eat_space;
+  stopAtPunctuation = stop_at_punctuation;
   SpecialPowers.pushPrefEnv({"set": [["layout.word_select.eat_space_to_next_word", eat_space], ["layout.word_select.stop_at_punctuation", stop_at_punctuation]]}, callback);
 }
 
 function errString(dir) {
-  return dir + " movement broken with eatSpace=" + eatSpace + " in \"" + editor.innerHTML +
+  return dir + " movement broken with eatSpace=" + eatSpace +
+    ", stopAtPunctuation=" + stopAtPunctuation + " in \"" + editor.innerHTML +
     "\"; sel.anchorNode.parentNode=" + sel.anchorNode.parentNode;
 }
 
 function testRight(node, offset) {
   synthesizeKey("VK_RIGHT", wordModifiers);
   is(sel.anchorNode, node, errString("Right"));
   is(sel.anchorOffset, offset, errString("Right"));
 }
@@ -277,15 +280,201 @@ function test2() {
   sel.collapse(editor.firstChild, 0);
   testRight(editor.firstChild, 3);
   testRight(editor.firstChild, 6);
   testRight(editor.firstChild, 8);
   testLeft(editor.firstChild, 6);
   testLeft(editor.firstChild, 3);
   testLeft(editor.firstChild, 0);
 
+  // Test basic word movement with stop_at_punctuation false (bug 981281).
+  setPrefs(false, false, test3);
+}
+
+function test3() {
+  editor.innerHTML = "Hello Kitty";
+  sel.collapse(editor.firstChild, 0);
+  testRight(editor.firstChild, 5);
+  testRight(editor.firstChild, 11);
+  testLeft(editor.firstChild, 6);
+  testLeft(editor.firstChild, 0);
+
+  editor.innerHTML = "<b>Hello</b> Kitty";
+  sel.collapse(editor.firstChild.firstChild, 0);
+  testRight(editor.firstChild.nextSibling, 0);
+  testRight(editor.firstChild.nextSibling, 6);
+  testLeft(editor.firstChild.nextSibling, 1);
+  testLeft(editor.firstChild.firstChild, 0);
+
+  editor.innerHTML = "<b>Hello </b>Kitty";
+  sel.collapse(editor.firstChild.firstChild, 0);
+  testRight(editor.firstChild.firstChild, 5);
+  testRight(editor.firstChild.nextSibling, 5);
+  testLeft(editor.firstChild.firstChild, 6);
+  testLeft(editor.firstChild.firstChild, 0);
+
+  editor.innerHTML = "<b>Log out</b>  roc";
+  sel.collapse(editor.firstChild.firstChild, 0);
+  testRight(editor.firstChild.firstChild, 3);
+  testRight(editor.firstChild.nextSibling, 0);
+  testRight(editor.firstChild.nextSibling, 5);
+  testLeft(editor.firstChild.nextSibling, 1);
+  testLeft(editor.firstChild.firstChild, 4);
+  testLeft(editor.firstChild.firstChild, 0);
+
+  editor.innerHTML = "http://www.mozilla.org";
+  sel.collapse(editor.firstChild, 0);
+  testRight(editor.firstChild, 22);
+  testLeft(editor.firstChild, 0);
+
+  editor.innerHTML = "Set .rc to <b>'</b>quiz'";
+  sel.collapse(editor.firstChild, 0);
+  testRight(editor.firstChild, 3);
+  testRight(editor.firstChild, 7);
+  testRight(editor.firstChild, 10);
+  testRight(editor.firstChild.nextSibling.nextSibling, 5);
+  testLeft(editor.firstChild, 11);
+  testLeft(editor.firstChild, 8);
+  testLeft(editor.firstChild, 4);
+  testLeft(editor.firstChild, 0);
+
+  editor.innerHTML = ChineseChars + HiraganaChars + ChineseChars;
+  sel.collapse(editor.firstChild, 0);
+  testRight(editor.firstChild, 2);
+  testRight(editor.firstChild, 6);
+  testRight(editor.firstChild, 8);
+  testLeft(editor.firstChild, 6);
+  testLeft(editor.firstChild, 2);
+  testLeft(editor.firstChild, 0);
+
+  editor.innerHTML = ChineseChars + KatakanaChars + ChineseChars;
+  sel.collapse(editor.firstChild, 0);
+  testRight(editor.firstChild, 2);
+  testRight(editor.firstChild, 6);
+  testRight(editor.firstChild, 8);
+  testLeft(editor.firstChild, 6);
+  testLeft(editor.firstChild, 2);
+  testLeft(editor.firstChild, 0);
+
+  editor.innerHTML = KatakanaChars + HiraganaChars + KatakanaChars;
+  sel.collapse(editor.firstChild, 0);
+  testRight(editor.firstChild, 4);
+  testRight(editor.firstChild, 8);
+  testRight(editor.firstChild, 12);
+  testLeft(editor.firstChild, 8);
+  testLeft(editor.firstChild, 4);
+  testLeft(editor.firstChild, 0);
+
+  editor.innerHTML = HiraganaChars + JapaneseComma + HiraganaChars + JapaneseFullStop + HiraganaChars;
+  sel.collapse(editor.firstChild, 0);
+  testRight(editor.firstChild, 14);
+  testLeft(editor.firstChild, 0);
+
+  editor.innerHTML = KatakanaChars + JapaneseComma + KatakanaChars + JapaneseFullStop + KatakanaChars;
+  sel.collapse(editor.firstChild, 0);
+  testRight(editor.firstChild, 14);
+  testLeft(editor.firstChild, 0);
+
+  editor.innerHTML = ChineseChars + JapaneseComma + ChineseChars + JapaneseFullStop + ChineseChars;
+  sel.collapse(editor.firstChild, 0);
+  testRight(editor.firstChild, 8);
+  testLeft(editor.firstChild, 0);
+
+  // And again with eat_space_next_to_word true.
+  setPrefs(true, false, test4);
+}
+
+function test4() {
+  editor.innerHTML = "Hello Kitty";
+  sel.collapse(editor.firstChild, 0);
+  testRight(editor.firstChild, 6);
+  testRight(editor.firstChild, 11);
+  testLeft(editor.firstChild, 6);
+  testLeft(editor.firstChild, 0);
+
+  editor.innerHTML = "<b>Hello</b> Kitty";
+  sel.collapse(editor.firstChild.firstChild, 0);
+  testRight(editor.firstChild.nextSibling, 1);
+  testRight(editor.firstChild.nextSibling, 6);
+  testLeft(editor.firstChild.nextSibling, 1);
+  testLeft(editor.firstChild.firstChild, 0);
+
+  editor.innerHTML = "<b>Hello </b>Kitty";
+  sel.collapse(editor.firstChild.firstChild, 0);
+  testRight(editor.firstChild.nextSibling, 0);
+  testRight(editor.firstChild.nextSibling, 5);
+  testLeft(editor.firstChild.firstChild, 6);
+  testLeft(editor.firstChild.firstChild, 0);
+
+  editor.innerHTML = "<b>Log out</b>  roc";
+  sel.collapse(editor.firstChild.firstChild, 0);
+  testRight(editor.firstChild.firstChild, 4);
+  testRight(editor.firstChild.nextSibling, 2);
+  testRight(editor.firstChild.nextSibling, 5);
+  testLeft(editor.firstChild.nextSibling, 1);
+  testLeft(editor.firstChild.firstChild, 4);
+  testLeft(editor.firstChild.firstChild, 0);
+
+  editor.innerHTML = "http://www.mozilla.org";
+  sel.collapse(editor.firstChild, 0);
+  testRight(editor.firstChild, 22);
+  testLeft(editor.firstChild, 0);
+
+  editor.innerHTML = "Set .rc to <b>'</b>quiz'";
+  sel.collapse(editor.firstChild, 0);
+  testRight(editor.firstChild, 4);
+  testRight(editor.firstChild, 8);
+  testRight(editor.firstChild.nextSibling.firstChild, 0);
+  testRight(editor.firstChild.nextSibling.nextSibling, 5);
+  testLeft(editor.firstChild, 11);
+  testLeft(editor.firstChild, 8);
+  testLeft(editor.firstChild, 4);
+  testLeft(editor.firstChild, 0);
+
+  editor.innerHTML = ChineseChars + HiraganaChars + ChineseChars;
+  sel.collapse(editor.firstChild, 0);
+  testRight(editor.firstChild, 2);
+  testRight(editor.firstChild, 6);
+  testRight(editor.firstChild, 8);
+  testLeft(editor.firstChild, 6);
+  testLeft(editor.firstChild, 2);
+  testLeft(editor.firstChild, 0);
+
+  editor.innerHTML = ChineseChars + KatakanaChars + ChineseChars;
+  sel.collapse(editor.firstChild, 0);
+  testRight(editor.firstChild, 2);
+  testRight(editor.firstChild, 6);
+  testRight(editor.firstChild, 8);
+  testLeft(editor.firstChild, 6);
+  testLeft(editor.firstChild, 2);
+  testLeft(editor.firstChild, 0);
+
+  editor.innerHTML = KatakanaChars + HiraganaChars + KatakanaChars;
+  sel.collapse(editor.firstChild, 0);
+  testRight(editor.firstChild, 4);
+  testRight(editor.firstChild, 8);
+  testRight(editor.firstChild, 12);
+  testLeft(editor.firstChild, 8);
+  testLeft(editor.firstChild, 4);
+  testLeft(editor.firstChild, 0);
+
+  editor.innerHTML = HiraganaChars + JapaneseComma + HiraganaChars + JapaneseFullStop + HiraganaChars;
+  sel.collapse(editor.firstChild, 0);
+  testRight(editor.firstChild, 14);
+  testLeft(editor.firstChild, 0);
+
+  editor.innerHTML = KatakanaChars + JapaneseComma + KatakanaChars + JapaneseFullStop + KatakanaChars;
+  sel.collapse(editor.firstChild, 0);
+  testRight(editor.firstChild, 14);
+  testLeft(editor.firstChild, 0);
+
+  editor.innerHTML = ChineseChars + JapaneseComma + ChineseChars + JapaneseFullStop + ChineseChars;
+  sel.collapse(editor.firstChild, 0);
+  testRight(editor.firstChild, 8);
+  testLeft(editor.firstChild, 0);
+
   SimpleTest.finish();
 }
 
 
 </script></pre>
 </body>
 </html>
--- a/layout/reftests/bidi/reftest.list
+++ b/layout/reftests/bidi/reftest.list
@@ -81,18 +81,18 @@ random-if(winWidget) == 267459-1.html 26
 random-if(winWidget) == 305643-1.html 305643-1-ref.html # depends on windows version, see bug 590101
 == 332655-1.html 332655-1-ref.html
 == 332655-2.html 332655-2-ref.html
 == 381279-1.html 381279-1-ref.html
 == 386339.html 386339-ref.html
 == 409375.html 409375-ref.html
 == 413542-1.html 413542-1-ref.html
 == 413542-2.html 413542-2-ref.html
-== 413928-1.html 413928-1-ref.html
-== 413928-2.html 413928-2-ref.html
+random-if(B2G) == 413928-1.html 413928-1-ref.html
+random-if(B2G) == 413928-2.html 413928-2-ref.html
 == 425338-1a.html 425338-1-ref.html
 == 425338-1b.html 425338-1-ref.html
 == 489517-1.html 489517-1-ref.html
 == 489887-1.html 489887-1-ref.html
 == 492231-1.html 492231-1-ref.html
 == 496006-1.html 496006-1-ref.html
 == 503269-1.html 503269-1-ref.html
 == 503957-1.html 503957-1-ref.html
@@ -134,11 +134,11 @@ skip-if(B2G) == 726420-1.html 726420-1-r
 == 730562-1.html 730562-1-ref.html
 == 746987-1.html 746987-1-ref.html
 == 746987-2.html 746987-2-ref.html
 == 746987-3.html 746987-3-ref.html
 == 746987-4.html 746987-4-ref.html
 == 779003-1.html 779003-1-ref.html
 == 779003-1-dynamic.html 779003-1-ref.html
 == 847242-1.html 847242-1-ref.html
-== 869833-1.xul 869833-1-ref.xul
+skip-if(B2G&&browserIsRemote) == 869833-1.xul 869833-1-ref.xul
 fails-if(B2G) == 922530-1.html 922530-1-ref.html # B2G kerning
 == 922550-1.html 922550-1-ref.html
--- a/layout/reftests/box-ordinal/reftest.list
+++ b/layout/reftests/box-ordinal/reftest.list
@@ -1,7 +1,7 @@
-== box-ordinal-with-out-of-flow-1.html box-ordinal-with-out-of-flow-1-ref.html
-== dynamic-1-remove-to-none-grouped.xul dynamic-1-ref.xul
-== dynamic-1-add-to-one-grouped.xul dynamic-1-ref.xul
-== dynamic-1-remove-to-one-grouped-1.xul dynamic-1-ref.xul
-fails == dynamic-1-remove-to-one-grouped-2.xul dynamic-1-ref.xul # bug 575500
-== dynamic-1-add-to-two-grouped-1.xul dynamic-1-ref.xul
-== dynamic-1-add-to-two-grouped-2.xul dynamic-1-ref.xul
+skip-if(B2G&&browserIsRemote) == box-ordinal-with-out-of-flow-1.html box-ordinal-with-out-of-flow-1-ref.html
+skip-if(B2G&&browserIsRemote) == dynamic-1-remove-to-none-grouped.xul dynamic-1-ref.xul
+skip-if(B2G&&browserIsRemote) == dynamic-1-add-to-one-grouped.xul dynamic-1-ref.xul
+skip-if(B2G&&browserIsRemote) == dynamic-1-remove-to-one-grouped-1.xul dynamic-1-ref.xul
+fails skip-if(B2G&&browserIsRemote) == dynamic-1-remove-to-one-grouped-2.xul dynamic-1-ref.xul # bug 575500
+skip-if(B2G&&browserIsRemote) == dynamic-1-add-to-two-grouped-1.xul dynamic-1-ref.xul
+skip-if(B2G&&browserIsRemote) == dynamic-1-add-to-two-grouped-2.xul dynamic-1-ref.xul
--- a/layout/reftests/box-properties/reftest.list
+++ b/layout/reftests/box-properties/reftest.list
@@ -1,9 +1,9 @@
-== outline-radius-percent-1.html outline-radius-percent-1-ref.html
+random-if(B2G) == outline-radius-percent-1.html outline-radius-percent-1-ref.html
 == min-width-1.html min-width-1-ref.html
 == min-height-1.html min-height-1-ref.html
 == max-width-1.html max-width-1-ref.html
 == max-height-1.html max-height-1-ref.html
 == width-special-values-block.html width-special-values-block-ref.html
 == width-special-values-float.html width-special-values-block-ref.html
 == width-special-values-image-block.html width-special-values-image-block-ref.html
 == width-special-values-image.html width-special-values-image-ref.html
--- a/layout/reftests/box-shadow/reftest.list
+++ b/layout/reftests/box-shadow/reftest.list
@@ -9,17 +9,17 @@ random != boxshadow-blur-2.html boxshado
 == tableboxshadow-trshadow.html tableboxshadow-trshadow-ref.html
 == tableboxshadow-tdshadow.html tableboxshadow-tdshadow-ref.html
 == boxshadow-rounding.html boxshadow-rounding-ref.html
 fails-if(Android||B2G) == boxshadow-button.html boxshadow-button-ref.html
 fails-if(Android||B2G) == boxshadow-fileupload.html boxshadow-fileupload-ref.html
 == boxshadow-inner-basic.html boxshadow-inner-basic-ref.svg
 random-if(layersGPUAccelerated) == boxshadow-mixed.html boxshadow-mixed-ref.html
 random-if(d2d) == boxshadow-rounded-spread.html boxshadow-rounded-spread-ref.html
-HTTP(..) == boxshadow-dynamic.xul boxshadow-dynamic-ref.xul
+skip-if(B2G&&browserIsRemote) HTTP(..) == boxshadow-dynamic.xul boxshadow-dynamic-ref.xul
 random-if(d2d) == boxshadow-onecorner.html boxshadow-onecorner-ref.html
 random-if(d2d) == boxshadow-twocorners.html boxshadow-twocorners-ref.html
 random-if(d2d) == boxshadow-threecorners.html boxshadow-threecorners-ref.html
 == boxshadow-skiprect.html boxshadow-skiprect-ref.html
 == boxshadow-opacity.html boxshadow-opacity-ref.html
 == boxshadow-color-rounding.html boxshadow-color-rounding-ref.html
 
 == overflow-not-scrollable-1.html overflow-not-scrollable-1-ref.html
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -1379,17 +1379,17 @@ pref(dom.use_xbl_scopes_for_remote_xul,t
 == 495385-5.html 495385-5-ref.html
 asserts(1) == 496032-1.html 496032-1-ref.html # bug 399262
 == 496840-1.html 496840-1-ref.html
 skip-if(B2G&&browserIsRemote) == 498228-1.xul 498228-1-ref.xul # bug 974780
 == 501037.html 501037-ref.html
 == 501257-1a.html 501257-1-ref.html
 == 501257-1b.html 501257-1-ref.html
 == 501257-1.xhtml 501257-1-ref.xhtml
-== 501627-1.html 501627-1-ref.html
+skip-if(B2G) == 501627-1.html 501627-1-ref.html # Bug 989165
 == 502288-1.html 502288-1-ref.html
 skip-if(B2G) == 502447-1.html 502447-1-ref.html
 == 502795-1.html 502795-1-ref.html
 == 502942-1.html 502942-1-ref.html
 == 503364-1a.html 503364-1-ref.html
 == 503364-1b.html 503364-1-ref.html
 == 503399.html 503399-ref.html
 # Reftest for bug 503531 marked as failing; should be re-enabled when
@@ -1604,17 +1604,17 @@ skip-if(B2G) == 600803-1.html 600803-1-r
 == 600974-2.html 600974-1-ref.html
 == 600974-3.html 600974-1-ref.html
 == 602200-1.html 602200-1-ref.html
 == 602200-2.html 602200-2-ref.html
 fuzzy-if(Android&&AndroidVersion>=15,8,20) == 602200-3.html 602200-3-ref.html
 == 602200-4.html 602200-4-ref.html
 == 603423-1.html 603423-1-ref.html
 == 604737.html 604737-ref.html
-== 605138-1.html 605138-1-ref.html
+random-if(B2G) == 605138-1.html 605138-1-ref.html # Bug 988758
 == 605157-1.xhtml 605157-1-ref.xhtml
 == 607267-1.html 607267-1-ref.html
 == 608636-1.html 608636-1-ref.html
 == 608756-1a.html 608756-1-ref.html
 == 608756-1b.html 608756-1-ref.html
 == 608756-2.html 608756-2-ref.html
 == 609272-1.html 609272-1-ref.html
 needs-focus == 613433-1.html 613433-1-ref.html
--- a/layout/reftests/columns/reftest.list
+++ b/layout/reftests/columns/reftest.list
@@ -14,18 +14,18 @@
 == column-balancing-000.html column-balancing-000.ref.html
 == column-balancing-001.html column-balancing-000.ref.html
 == column-balancing-002.html column-balancing-002.ref.html
 == column-balancing-003.html column-balancing-000.ref.html
 == column-balancing-004.html column-balancing-004.ref.html
 == column-box-alignment-rtl.html column-box-alignment-rtl-ref.html
 HTTP(..) == columnfill-balance.html columnfill-balance-ref.html
 HTTP(..) == columnfill-auto.html columnfill-auto-ref.html
-HTTP(..) == columnfill-auto-2.html columnfill-auto-2-ref.html
-HTTP(..) == columnfill-auto-3.html columnfill-auto-2-ref.html
+random-if(B2G) HTTP(..) == columnfill-auto-2.html columnfill-auto-2-ref.html
+random-if(B2G) HTTP(..) == columnfill-auto-3.html columnfill-auto-2-ref.html
 skip-if(B2G) == columnrule-basic.html columnrule-basic-ref.html # bug 773482
 skip-if(B2G) == columnrule-complex.html columnrule-complex-ref.html # bug 773482
 != columnrule-linestyles.html columnrule-linestyles-notref.html
 == columnrule-padding.html columnrule-padding-ref.html
 skip-if(B2G) == columnfill-overflow.html columnfill-overflow-ref.html # bug 773482
 == margin-collapsing-bug616722-1.html margin-collapsing-bug616722-1-ref.html
 == margin-collapsing-bug616722-2.html margin-collapsing-bug616722-2-ref.html
 == column-balancing-nested-000.html column-balancing-nested-000-ref.html
--- a/layout/reftests/dom/reftest.list
+++ b/layout/reftests/dom/reftest.list
@@ -26,30 +26,30 @@
 # multiple range inserts
 == insertmultiplemultiple-1.html insertmultiplemultiple-ref.html
 # a range insert and an append
 == insertmultiplemultiple-2.html insertmultiplemultiple-ref.html
 # multiple range inserts and an append
 == insertmultiplemultiple-2.html insertmultiplemultiple-ref.html
 
 # testing bindings that have multiple insertion points
-== multipleinsertionpoints-ref2.xhtml multipleinsertionpoints-ref.xhtml
+fails-if(B2G) == multipleinsertionpoints-ref2.xhtml multipleinsertionpoints-ref.xhtml #Bug 988759
 # append a single element
 skip-if(B2G) == multipleinsertionpoints-appendsingle-1.xhtml multipleinsertionpoints-ref.xhtml # bug 773482
 skip-if(B2G) == multipleinsertionpoints-appendsingle-2.xhtml multipleinsertionpoints-ref.xhtml # bug 773482
 # append several elements
 skip-if(B2G) == multipleinsertionpoints-appendmultiple.xhtml multipleinsertionpoints-ref.xhtml # bug 773482
 # insert a single element
 skip-if(B2G) == multipleinsertionpoints-insertsingle-1.xhtml multipleinsertionpoints-ref.xhtml # bug 773482
 skip-if(B2G) == multipleinsertionpoints-insertsingle-2.xhtml multipleinsertionpoints-ref.xhtml # bug 773482
 # insert several elements
 skip-if(B2G) == multipleinsertionpoints-insertmultiple.xhtml multipleinsertionpoints-ref.xhtml # bug 773482
 
 # test appending some nodes whose frame construction should be done lazily
 # followed by appending a node that might not be done lazily
-== multipleappendwithxul.xhtml multipleappendwithxul-ref.xhtml
+skip-if(B2G&&browserIsRemote) == multipleappendwithxul.xhtml multipleappendwithxul-ref.xhtml # Bug 974780
 == multipleappendwithinput.xhtml multipleappendwithinput-ref.xhtml
 == multipleappendwitheditable.xhtml multipleappendwitheditable-ref.xhtml
 
 skip-if(B2G) == xbl-children-1.xhtml xbl-children-1-ref.xhtml
 skip-if(B2G) == xbl-children-2.xhtml about:blank
 skip-if(B2G) == xbl-children-3.xhtml xbl-children-3-ref.html
 skip-if(B2G) == xbl-children-4.xhtml xbl-children-4-ref.html
--- a/layout/reftests/first-line/reftest.list
+++ b/layout/reftests/first-line/reftest.list
@@ -21,17 +21,17 @@ load stress-5.html # assertion/crash tes
 load stress-6.html # assertion/crash test
 load stress-7.html # assertion/crash test
 == stress-8.html stress-8-ref.html # assertion/crash test
 == stress-9.html stress-9-ref.html # assertion/crash test
 load stress-10.html # crash test
 == stress-11.xhtml stress-11-ref.xhtml
 
 == border-not-apply.html border-not-apply-ref.html
-== 287088-1.html 287088-1-ref.html
+skip-if(B2G) == 287088-1.html 287088-1-ref.html # Bug 975254
 == 287088-2.html 287088-2-ref.html
 == 403177-1.html 403177-1-ref.html
 == 469227-2.html 469227-2-ref.html
 == 469227-3.html 469227-3-ref.html
 
 == restyle-inside-first-line.html restyle-inside-first-line-ref.html
 == font-styles.html font-styles-ref.html
 == font-styles-nooverflow.html font-styles-ref.html
--- a/layout/reftests/forms/input/number/reftest.list
+++ b/layout/reftests/forms/input/number/reftest.list
@@ -16,17 +16,17 @@ fuzzy-if(/^Windows\x20NT\x205\.1/.test(h
 
 # dynamic value changes:
 == show-value.html show-value-ref.html
 
 # disabled
 == number-disabled.html number-disabled-ref.html
 
 # auto width:
-== number-auto-width-1.html number-auto-width-1-ref.html
+random-if(B2G) == number-auto-width-1.html number-auto-width-1-ref.html
 
 # min-height/max-height tests:
 skip-if(B2G||Android) == number-min-height-1.html number-min-height-1-ref.html
 skip-if(B2G||Android) == number-min-height-2.html number-min-height-2-ref.html
 skip-if(B2G||Android) == number-max-height-1.html number-max-height-1-ref.html
 skip-if(B2G||Android) == number-max-height-2.html number-max-height-2-ref.html
 
 # focus
--- a/layout/reftests/forms/input/range/reftest.list
+++ b/layout/reftests/forms/input/range/reftest.list
@@ -12,20 +12,20 @@
 != different-fraction-of-range-unthemed-1.html different-fraction-of-range-unthemed-1-notref.html
 == same-fraction-of-range-unthemed-1.html same-fraction-of-range-unthemed-1-ref.html
 
 # dynamic value changes:
 == value-prop-unthemed.html 75pct-unthemed-common-ref.html
 == value-prop.html 75pct-common-ref.html
 == valueAsNumber-prop-unthemed.html 75pct-unthemed-common-ref.html
 == valueAsNumber-prop.html 75pct-common-ref.html
-== stepDown-unthemed.html 75pct-unthemed-common-ref.html
-== stepDown.html 75pct-common-ref.html
-== stepUp-unthemed.html 75pct-unthemed-common-ref.html
-== stepUp.html 75pct-common-ref.html
+random-if(B2G) == stepDown-unthemed.html 75pct-unthemed-common-ref.html # Bug 878916
+random-if(B2G) == stepDown.html 75pct-common-ref.html # Bug 878916
+random-if(B2G) == stepUp-unthemed.html 75pct-unthemed-common-ref.html # Bug 969256
+random-if(B2G) == stepUp.html 75pct-common-ref.html # Bug 969256
 fuzzy-if(B2G,1,1) == max-prop.html 100pct-common-ref.html
 
 # 'direction' property:
 == direction-unthemed-1.html direction-unthemed-1-ref.html
 
 # ::-moz-range-progress pseudo-element:
 fails-if(B2G||Android) == moz-range-progress-1.html moz-range-progress-1-ref.html
 == moz-range-progress-2.html moz-range-progress-2-ref.html
--- a/layout/reftests/ib-split/reftest.list
+++ b/layout/reftests/ib-split/reftest.list
@@ -59,17 +59,17 @@
 == insert-into-split-inline-13-ref.html insert-into-split-inline-13-noib-ref.html
 == insert-into-split-inline-14.html insert-into-split-inline-14-ref.html
 == insert-into-split-inline-14-ref.html insert-into-split-inline-14-noib-ref.html
 == insert-into-split-inline-15.html insert-into-split-inline-15-ref.html
 == insert-into-split-inline-15-ref.html insert-into-split-inline-15-noib-ref.html
 == insert-into-split-inline-16a.html insert-into-split-inline-16-ref.html
 == insert-into-split-inline-16b.html insert-into-split-inline-16-ref.html
 == insert-into-split-inline-16-ref.html insert-into-split-inline-16-noib-ref.html
-== float-inside-inline-between-blocks-1.html float-inside-inline-between-blocks-1-ref.html
+random-if(B2G) == float-inside-inline-between-blocks-1.html float-inside-inline-between-blocks-1-ref.html
 == table-pseudo-in-part3-1.html table-pseudo-in-part3-1-ref.html
 == emptyspan-1.html emptyspan-1-ref.html
 == emptyspan-2.html emptyspan-2-ref.html
 == emptyspan-3.html emptyspan-3-ref.html
 == emptyspan-4.html emptyspan-4-ref.html
 == split-inner-inline-1.html split-inner-inline-1-ref.html
 == split-inner-inline-2.html split-inner-inline-2-ref.html
 == whitespace-present-1a.html whitespace-present-1-ref.html
--- a/layout/reftests/image-element/reftest.list
+++ b/layout/reftests/image-element/reftest.list
@@ -39,9 +39,9 @@ fuzzy(1,9674) random-if(!cocoaWidget) ==
 fuzzy(1,9674) random-if(!cocoaWidget) == gradient-html-06b.html gradient-html-06c.html
 == gradient-html-06c.html gradient-html-06d.html
 == gradient-html-06d.html gradient-html-06e.html
 random-if(!cocoaWidget) fuzzy-if(azureQuartz,1,11367) == gradient-html-07a.html gradient-html-07b.html
 fuzzy(1,16900) == gradient-html-07c.html gradient-html-07d.html
 HTTP == invalidate-1.html invalidate-1-ref.html
 == pattern-html-01.html pattern-html-01-ref.svg
 == pattern-html-02.html pattern-html-02-ref.svg
-== referenced-from-binding-01.html referenced-from-binding-01-ref.html
+fails-if(B2G) == referenced-from-binding-01.html referenced-from-binding-01-ref.html # Bug 988763
--- a/layout/reftests/image-region/reftest.list
+++ b/layout/reftests/image-region/reftest.list
@@ -1,1 +1,1 @@
-== image-region.xul image-region-ref.xul
+skip-if(B2G&&browserIsRemote) == image-region.xul image-region-ref.xul
--- a/layout/reftests/marquee/reftest.list
+++ b/layout/reftests/marquee/reftest.list
@@ -1,9 +1,9 @@
-== 166591-dynamic-1.html 166591-dynamic-1-ref.html
+fails-if(B2G) == 166591-dynamic-1.html 166591-dynamic-1-ref.html
 fuzzy-if(Android&&AndroidVersion>=15,8,50) == 336736-1a.html 336736-1-ref.html
 fuzzy-if(Android&&AndroidVersion>=15,8,50) == 336736-1b.html 336736-1-ref.html
 == 406073-1.html 406073-1-ref.html
 == 407016-2.html 407016-2-ref.html
 fuzzy-if(Android&&AndroidVersion>=15,8,220) == 413027-4.html 413027-4-ref.html
 fuzzy-if(Android&&AndroidVersion>=15,8,30) == 425247-1.html 425247-1-ref.html
 fuzzy-if(Android&&AndroidVersion>=15,8,30) == 425247-2.html 425247-2-ref.html
 random == 429849-1.html 429849-1-ref.html # bug 432288
--- a/layout/reftests/object/reftest.list
+++ b/layout/reftests/object/reftest.list
@@ -49,9 +49,9 @@ fails == svg-with-type.html svg-with-typ
 #
 # XXX missing test 033 from http://biesi.damowmow.com/object/ here; not sure
 #     how nullplugin testing should work
 #
 #
 # XXX missing test 034 from http://biesi.damowmow.com/object/ here; would
 #     need to require Flash on the test machine to run them
 #
-== malformed-uri.html malformed-uri-ref.html
+fails-if(B2G) == malformed-uri.html malformed-uri-ref.html
--- a/layout/reftests/printing/reftest.list
+++ b/layout/reftests/printing/reftest.list
@@ -15,20 +15,20 @@ fails-if(B2G) == 609227-2b.html 609227-2
 == 577450-1.html 577450-1-ref.html
 == 626395-1a.html 626395-1-ref.html
 == 626395-1b.html 626395-1-ref.html
 == 626395-2a.html 626395-2-ref.html
 == 626395-2b.html 626395-2-ref.html
 == 626395-2c.html 626395-2-ref.html
 == 626395-2d.html 626395-2-ref.html
 == 652178-1.html 652178-1-ref.html
-fails-if(B2G) == 115199-1.html 115199-1-ref.html # reftest-print doesn't work on B2G
-== 115199-2a.html 115199-2-ref.html
-== 115199-2b.html 115199-2-ref.html
+random-if(B2G) == 115199-1.html 115199-1-ref.html # reftest-print doesn't work on B2G
+random-if(B2G) == 115199-2a.html 115199-2-ref.html
+random-if(B2G)  == 115199-2b.html 115199-2-ref.html
 == 652178-1.html 652178-1-ref2.html
 skip-if(B2G) fuzzy-if(cocoaWidget,1,5000) == 745025-1.html 745025-1-ref.html # reftest-print doesn't work on B2G
 == 820496-1.html 820496-1-ref.html
 
 # NOTE: These tests don't yet rigorously test what they're
 # trying to test (shrink-to-fit behavior), due to bug 967311.
-fails-if(B2G) == 960822.html 960822-ref.html # reftest-print doesn't work on B2G (scrollbar difference only)
+random-if(B2G) == 960822.html 960822-ref.html # reftest-print doesn't work on B2G (scrollbar difference only)
 == 966419-1.html 966419-1-ref.html
 == 966419-2.html 966419-2-ref.html
--- a/layout/reftests/reftest.list
+++ b/layout/reftests/reftest.list
@@ -160,17 +160,17 @@ include floats/reftest.list
 
 # font-face
 include font-face/reftest.list
 
 # font features (opentype)
 include font-features/reftest.list
 
 # mobile font size inflation
-include font-inflation/reftest.list
+skip-if(B2G) include font-inflation/reftest.list # Bug 972697
 
 # font matching
 include font-matching/reftest.list
 
 # forms
 include forms/reftest.list
 
 # gfx
--- a/layout/reftests/svg/reftest.list
+++ b/layout/reftests/svg/reftest.list
@@ -221,17 +221,17 @@ random-if(gtk2Widget) == objectBoundingB
 == objectBoundingBox-and-pattern-01b.svg objectBoundingBox-and-pattern-01-ref.svg
 == objectBoundingBox-and-pattern-01c.svg objectBoundingBox-and-pattern-01-ref.svg
 == objectBoundingBox-and-pattern-02.svg pass.svg
 == objectBoundingBox-and-pattern-03.svg objectBoundingBox-and-pattern-03-ref.svg
 == opacity-and-gradient-01.svg pass.svg
 skip-if(d2d) fuzzy-if(azureQuartz,1,99974) == opacity-and-gradient-02.svg opacity-and-gradient-02-ref.svg
 == opacity-and-pattern-01.svg pass.svg
 == opacity-and-transform-01.svg opacity-and-transform-01-ref.svg
-fuzzy-if(Android&&AndroidVersion>=15,8,200) == outer-svg-border-and-padding-01.svg outer-svg-border-and-padding-01-ref.svg
+fuzzy-if(Android&&AndroidVersion>=15,8,200) random-if(B2G) == outer-svg-border-and-padding-01.svg outer-svg-border-and-padding-01-ref.svg
 == overflow-on-outer-svg-01.svg overflow-on-outer-svg-01-ref.svg
 == overflow-on-outer-svg-02a.xhtml overflow-on-outer-svg-02-ref.xhtml
 == overflow-on-outer-svg-02b.xhtml overflow-on-outer-svg-02-ref.xhtml
 == overflow-on-outer-svg-02c.xhtml overflow-on-outer-svg-02-ref.xhtml
 == overflow-on-outer-svg-02d.xhtml overflow-on-outer-svg-02-ref.xhtml
 == overflow-on-outer-svg-03a.xhtml overflow-on-outer-svg-03-ref.xhtml
 == overflow-on-outer-svg-03b.xhtml overflow-on-outer-svg-03-ref.xhtml
 pref(svg.paint-order.enabled,true) == paint-order-01.svg paint-order-01-ref.svg
--- a/layout/reftests/svg/sizing/reftest.list
+++ b/layout/reftests/svg/sizing/reftest.list
@@ -279,26 +279,26 @@ HTTP(../..) == inline--position-relative
 # in the future.
 #
 # Since we have given the replaced element algorithm a reasonable workout in
 # the standalone tests, for the embedded by reference tests we will simply
 # check that the embedded SVG's intrinsic dimensions are used. The following
 # tests do not have any width or height on the <object> element so they should
 # be sized purely by the embedded SVG's intrinsic size.
 
-random-if(Android) == object--auto-auto--0-0.html          pass-empty.svg # XXX add border
-random-if(Android) == object--auto-auto--0-pct.html        object--auto-auto--0-pct--ref.html
-random-if(Android) == object--auto-auto--0-px.html         object--auto-auto--0-px--ref.html
-random-if(Android) == object--auto-auto--pct-0.html        object--auto-auto--pct-0--ref.html
+random-if(Android||B2G) == object--auto-auto--0-0.html          pass-empty.svg # XXX add border
+random-if(Android||B2G) == object--auto-auto--0-pct.html        object--auto-auto--0-pct--ref.html
+random-if(Android||B2G) == object--auto-auto--0-px.html         object--auto-auto--0-px--ref.html
+random-if(Android||B2G) == object--auto-auto--pct-0.html        object--auto-auto--pct-0--ref.html
 # The following four commented out tests fail post bug 428023:
 #== object--auto-auto--pct-pct.html      object--auto-auto--pct-pct--ref.html
 #== object--auto-auto--pct-px.html       object--auto-auto--pct-px--ref.html
-random-if(Android) == object--auto-auto--px-0.html         object--auto-auto--px-0--ref.html
+random-if(Android||B2G) == object--auto-auto--px-0.html         object--auto-auto--px-0--ref.html
 #== object--auto-auto--px-pct.html       object--auto-auto--px-pct--ref.html
-random-if(Android) == object--auto-auto--px-px.html        object--auto-auto--px-px--ref.html
+random-if(Android||B2G) == object--auto-auto--px-px.html        object--auto-auto--px-px--ref.html
 #== object--pct-pct--0-0.html            pass.svg
 
 
 # Assorted tests to check that dynamic changes work correctly
 #
 # Here we have an assortment of different tests to check that updates occur
 # correctly when changes are made that should result in a change in the size
 # or position of the SVG.
--- a/layout/reftests/text-shadow/reftest.list
+++ b/layout/reftests/text-shadow/reftest.list
@@ -1,13 +1,13 @@
-== basic.xul basic-ref.xul
-random-if(Android) == basic-negcoord.xul basic-negcoord-ref.xul
-!= blur.xul blur-notref.xul
-== color-inherit.xul color-inherit-ref.xul
-== multiple-noblur.xul multiple-noblur-ref.xul
+skip-if(B2G&&browserIsRemote) == basic.xul basic-ref.xul
+random-if(Android) skip-if(B2G&&browserIsRemote) == basic-negcoord.xul basic-negcoord-ref.xul
+skip-if(B2G&&browserIsRemote) != blur.xul blur-notref.xul
+skip-if(B2G&&browserIsRemote) == color-inherit.xul color-inherit-ref.xul
+skip-if(B2G&&browserIsRemote) == multiple-noblur.xul multiple-noblur-ref.xul
 HTTP(..) == blur-opacity.html blur-opacity-ref.html
 
 == basic.html basic-ref.html
 == basic-negcoord.html basic-negcoord-ref.html
 == basic-opacity.html basic-opacity-ref.html
 != blur.html blur-notref.html
 == color-inherit.html color-inherit-ref.html
 == color-parserorder.html color-parserorder-ref.html
--- a/layout/reftests/transform-3d/reftest.list
+++ b/layout/reftests/transform-3d/reftest.list
@@ -6,26 +6,26 @@
 # Check that the perspectve() transform function results in some visual changes
 != rotatex-perspective-1a.html rotatex-1-ref.html
 # Check that -moz-perspective results in visual changes to child transformed elements
 != rotatex-perspective-1b.html rotatex-1-ref.html
 # -moz-perspective should only apply to child elements
 == rotatex-perspective-1c.html rotatex-1-ref.html
 == rotatex-perspective-3a.html rotatex-perspective-3-ref.html
 == scalez-1a.html scalez-1-ref.html
-== preserve3d-1a.html preserve3d-1-ref.html
+fails-if(B2G) == preserve3d-1a.html preserve3d-1-ref.html # Bug 988766
 == preserve3d-1b.html about:blank
 == preserve3d-clipped.html about:blank 
 == preserve3d-2a.html preserve3d-2-ref.html
 == preserve3d-2b.html preserve3d-2-ref.html
 == preserve3d-2c.html preserve3d-2-ref.html
 == preserve3d-2d.html preserve3d-2-ref.html
 == preserve3d-3a.html preserve3d-3-ref.html
 skip-if(B2G) == preserve3d-4a.html green-rect.html
-fuzzy-if(Android&&AndroidVersion>=15,4,300) == preserve3d-5a.html preserve3d-5-ref.html
+fuzzy-if(Android&&AndroidVersion>=15,4,300) fails-if(B2G) == preserve3d-5a.html preserve3d-5-ref.html # Bug 988767
 == scale3d-z.html scalez-1-ref.html
 fuzzy-if(winWidget,102,580) fuzzy-if(d2d,143,681) fuzzy-if(OSX==10.8,224,924) fuzzy-if(OSX==10.9,224,924) == scale3d-all.html scale3d-1-ref.html # subpixel AA
 fuzzy-if(winWidget,102,580) fuzzy-if(d2d,143,681) fuzzy-if(OSX==10.8,224,924) fuzzy-if(OSX==10.9,224,924) == scale3d-all-separate.html scale3d-1-ref.html # subpixel AA
 == scale3d-xz.html scale3d-1-ref.html
 == translatez-1a.html translatez-1-ref.html
 != translatez-1b.html translatez-1-ref.html
 == translate3d-1a.html translate3d-1-ref.html
 == matrix3d-1a.html matrix3d-1-ref.html
--- a/layout/reftests/w3c-css/submitted/ui3/reftest.list
+++ b/layout/reftests/w3c-css/submitted/ui3/reftest.list
@@ -3,11 +3,11 @@
 == box-sizing-border-box-003.xht box-sizing-border-box-003-ref.xht
 == box-sizing-border-box-004.xht box-sizing-border-box-004-ref.xht
 == box-sizing-content-box-001.xht box-sizing-content-box-001-ref.xht
 == box-sizing-content-box-002.xht box-sizing-content-box-002-ref.xht
 == box-sizing-content-box-003.xht box-sizing-content-box-003-ref.xht
 == box-sizing-padding-box-001.xht box-sizing-padding-box-001-ref.xht
 == box-sizing-padding-box-002.xht box-sizing-padding-box-002-ref.xht
 == box-sizing-padding-box-003.xht box-sizing-padding-box-003-ref.xht
-fails-if(B2G) random-if(Android) == box-sizing-replaced-001.xht box-sizing-replaced-001-ref.xht
-== box-sizing-replaced-002.xht box-sizing-replaced-002-ref.xht
-== box-sizing-replaced-003.xht box-sizing-replaced-003-ref.xht
+random-if(Android) skip-if(B2G) == box-sizing-replaced-001.xht box-sizing-replaced-001-ref.xht # Bug 982547
+random-if(B2G) == box-sizing-replaced-002.xht box-sizing-replaced-002-ref.xht
+random-if(B2G) == box-sizing-replaced-003.xht box-sizing-replaced-003-ref.xht
--- a/layout/reftests/xul-document-load/reftest.list
+++ b/layout/reftests/xul-document-load/reftest.list
@@ -1,23 +1,23 @@
-== test001.xul reference-green-window.xul
-== test002.xul reference-green-window.xul
-== test003.xul reference-green-window.xul
-== test004.xul reference-green-window.xul
-== test005.xul reference-green-window.xul
-== test006.xul reference-green-window.xul
-== test007.xul reference-green-window.xul
-== test008.xul reference-green-window.xul
-== test009.xul reference-green-window.xul
-== test010.xul reference-green-window.xul
-== test011.xul reference-green-window.xul
-== test012.xul reference-green-window.xul
-== test013.xul reference-green-window.xul
-== test014.xul reference-green-window.xul
+skip-if(B2G&&browserIsRemote) == test001.xul reference-green-window.xul
+skip-if(B2G&&browserIsRemote) == test002.xul reference-green-window.xul
+skip-if(B2G&&browserIsRemote) == test003.xul reference-green-window.xul
+skip-if(B2G&&browserIsRemote) == test004.xul reference-green-window.xul
+skip-if(B2G&&browserIsRemote) == test005.xul reference-green-window.xul
+skip-if(B2G&&browserIsRemote) == test006.xul reference-green-window.xul
+skip-if(B2G&&browserIsRemote) == test007.xul reference-green-window.xul
+skip-if(B2G&&browserIsRemote) == test008.xul reference-green-window.xul
+skip-if(B2G&&browserIsRemote) == test009.xul reference-green-window.xul
+skip-if(B2G&&browserIsRemote) == test010.xul reference-green-window.xul
+skip-if(B2G&&browserIsRemote) == test011.xul reference-green-window.xul
+skip-if(B2G&&browserIsRemote) == test012.xul reference-green-window.xul
+skip-if(B2G&&browserIsRemote) == test013.xul reference-green-window.xul
+skip-if(B2G&&browserIsRemote) == test014.xul reference-green-window.xul
 # Disabled due to compartments for now.
-#== test015.xul reference-green-window.xul
-== test016.xul reference-green-window.xul
-== test017.xul reference-green-window.xul
-== test018.xul reference-green-window.xul
-== test019.xul reference-green-window.xul
-== test020.xul reference-green-window.xul
-== test021.xul reference-green-window.xul
-== test022.xul reference-green-window.xul
+#skip-if(B2G&&browserIsRemote) == test015.xul reference-green-window.xul
+skip-if(B2G&&browserIsRemote) == test016.xul reference-green-window.xul
+skip-if(B2G&&browserIsRemote) == test017.xul reference-green-window.xul
+skip-if(B2G&&browserIsRemote) == test018.xul reference-green-window.xul
+skip-if(B2G&&browserIsRemote) == test019.xul reference-green-window.xul
+skip-if(B2G&&browserIsRemote) == test020.xul reference-green-window.xul
+skip-if(B2G&&browserIsRemote) == test021.xul reference-green-window.xul
+skip-if(B2G&&browserIsRemote) == test022.xul reference-green-window.xul
--- a/layout/reftests/xul/reftest.list
+++ b/layout/reftests/xul/reftest.list
@@ -1,9 +1,9 @@
-== menuitem-key.xul menuitem-key-ref.xul
+skip-if(B2G&&browserIsRemote) == menuitem-key.xul menuitem-key-ref.xul
 # these random-if(Android) are due to differences between Android Native & Xul, see bug 732569
-random-if(Android||B2G) == menulist-shrinkwrap-1.xul menulist-shrinkwrap-1-ref.xul
-random-if(Android||B2G) fails-if(winWidget) == menulist-shrinkwrap-2.xul menulist-shrinkwrap-2-ref.xul
-== textbox-overflow-1.xul textbox-overflow-1-ref.xul # for bug 749658
+random-if(Android||B2G) skip-if(B2G&&browserIsRemote) == menulist-shrinkwrap-1.xul menulist-shrinkwrap-1-ref.xul
+random-if(Android||B2G) fails-if(winWidget) skip-if(B2G&&browserIsRemote) == menulist-shrinkwrap-2.xul menulist-shrinkwrap-2-ref.xul
+skip-if(B2G&&browserIsRemote) == textbox-overflow-1.xul textbox-overflow-1-ref.xul # for bug 749658
 # accesskeys are not normally displayed on Mac, so skip this test
-skip-if(cocoaWidget) == accesskey.xul accesskey-ref.xul
-fails-if(cocoaWidget) fails-if(B2G) == tree-row-outline-1.xul tree-row-outline-1-ref.xul
-!= tree-row-outline-1.xul tree-row-outline-1-notref.xul
+skip-if(cocoaWidget) skip-if(B2G&&browserIsRemote) == accesskey.xul accesskey-ref.xul
+fails-if(cocoaWidget) fails-if(B2G) skip-if(B2G&&browserIsRemote) == tree-row-outline-1.xul tree-row-outline-1-ref.xul
+skip-if(B2G&&browserIsRemote) != tree-row-outline-1.xul tree-row-outline-1-notref.xul
--- a/layout/style/nsFontFaceLoader.cpp
+++ b/layout/style/nsFontFaceLoader.cpp
@@ -485,19 +485,34 @@ nsUserFontSet::UpdateRules(const nsTArra
       }
     }
   }
 
   if (modified) {
     IncrementGeneration();
   }
 
+  // local rules have been rebuilt, so clear the flag
+  mLocalRulesUsed = false;
+
   return modified;
 }
 
+static bool
+HasLocalSrc(const nsCSSValue::Array *aSrcArr)
+{
+  size_t numSrc = aSrcArr->Count();
+  for (size_t i = 0; i < numSrc; i++) {
+    if (aSrcArr->Item(i).GetUnit() == eCSSUnit_Local_Font) {
+      return true;
+    }
+  }
+  return false;
+}
+
 void
 nsUserFontSet::InsertRule(nsCSSFontFaceRule* aRule, uint8_t aSheetType,
                           nsTArray<FontFaceRuleRecord>& aOldRules,
                           bool& aFontSetModified)
 {
   NS_ABORT_IF_FALSE(aRule->GetType() == mozilla::css::Rule::FONT_FACE_RULE,
                     "InsertRule passed a non-fontface CSS rule");
 
@@ -519,18 +534,30 @@ nsUserFontSet::InsertRule(nsCSSFontFaceR
     // usable font, so there is no point in processing it further.
     return;
   }
 
   // first, we check in oldRules; if the rule exists there, just move it
   // to the new rule list, and put the entry into the appropriate family
   for (uint32_t i = 0; i < aOldRules.Length(); ++i) {
     const FontFaceRuleRecord& ruleRec = aOldRules[i];
+
     if (ruleRec.mContainer.mRule == aRule &&
         ruleRec.mContainer.mSheetType == aSheetType) {
+
+      // if local rules were used, don't use the old font entry
+      // for rules containing src local usage
+      if (mLocalRulesUsed) {
+        aRule->GetDesc(eCSSFontDesc_Src, val);
+        unit = val.GetUnit();
+        if (unit == eCSSUnit_Array && HasLocalSrc(val.GetArrayValue())) {
+          break;
+        }
+      }
+
       AddFontFace(fontfamily, ruleRec.mFontEntry);
       mRules.AppendElement(ruleRec);
       aOldRules.RemoveElementAt(i);
       // note the set has been modified if an old rule was skipped to find
       // this one - something has been dropped, or ordering changed
       if (i > 0) {
         aFontSetModified = true;
       }
@@ -978,8 +1005,14 @@ nsUserFontSet::GetPrivateBrowsing()
   nsIPresShell* ps = mPresContext->PresShell();
   if (!ps) {
     return false;
   }
 
   nsCOMPtr<nsILoadContext> loadContext = ps->GetDocument()->GetLoadContext();
   return loadContext && loadContext->UsePrivateBrowsing();
 }
+
+void
+nsUserFontSet::DoRebuildUserFontSet()
+{
+  mPresContext->RebuildUserFontSet();
+}
--- a/layout/style/nsFontFaceLoader.h
+++ b/layout/style/nsFontFaceLoader.h
@@ -82,16 +82,18 @@ protected:
 
   virtual nsresult SyncLoadFontData(gfxProxyFontEntry* aFontToLoad,
                                     const gfxFontFaceSrc* aFontFaceSrc,
                                     uint8_t*& aBuffer,
                                     uint32_t& aBufferLength) MOZ_OVERRIDE;
 
   virtual bool GetPrivateBrowsing() MOZ_OVERRIDE;
 
+  virtual void DoRebuildUserFontSet() MOZ_OVERRIDE;
+
   nsPresContext* mPresContext;  // weak reference
 
   // Set of all loaders pointing to us. These are not strong pointers,
   // but that's OK because nsFontFaceLoader always calls RemoveLoader on
   // us before it dies (unless we die first).
   nsTHashtable< nsPtrHashKey<nsFontFaceLoader> > mLoaders;
 
   nsTArray<FontFaceRuleRecord>   mRules;
--- a/layout/xul/grid/reftests/reftest.list
+++ b/layout/xul/grid/reftests/reftest.list
@@ -1,18 +1,18 @@
-== row-sizing-1.xul row-sizing-1-ref.xul
-== column-sizing-1.xul column-sizing-1-ref.xul
-== row-or-column-sizing-1.xul row-or-column-sizing-2.xul
-== row-or-column-sizing-1.xul row-or-column-sizing-3.xul
-== row-or-column-sizing-1.xul row-or-column-sizing-4.xul
-== z-order-1.xul z-order-1-ref.xul
-== z-order-2.xul z-order-2-ref.xul
-== not-full-basic.xul not-full-basic-ref.xhtml
-== not-full-grid-pack-align.xul not-full-basic-ref.xhtml
-== not-full-row-group-align.xul not-full-row-group-align-ref.xhtml # does anyone want/need this behavior?
-== not-full-row-group-pack.xul not-full-row-group-pack-ref.xhtml
-== not-full-row-group-direction.xul not-full-row-group-direction-ref.xhtml
-== not-full-row-leaf-align.xul not-full-basic-ref.xhtml
-== not-full-row-leaf-pack.xul not-full-row-leaf-pack-ref.xhtml
-== not-full-row-leaf-direction.xul not-full-row-leaf-pack-ref.xhtml
+skip-if(B2G&&browserIsRemote) == row-sizing-1.xul row-sizing-1-ref.xul
+skip-if(B2G&&browserIsRemote) == column-sizing-1.xul column-sizing-1-ref.xul
+skip-if(B2G&&browserIsRemote) == row-or-column-sizing-1.xul row-or-column-sizing-2.xul
+skip-if(B2G&&browserIsRemote) == row-or-column-sizing-1.xul row-or-column-sizing-3.xul
+skip-if(B2G&&browserIsRemote) == row-or-column-sizing-1.xul row-or-column-sizing-4.xul
+skip-if(B2G&&browserIsRemote) == z-order-1.xul z-order-1-ref.xul
+skip-if(B2G&&browserIsRemote) == z-order-2.xul z-order-2-ref.xul
+skip-if(B2G&&browserIsRemote) == not-full-basic.xul not-full-basic-ref.xhtml
+skip-if(B2G&&browserIsRemote) == not-full-grid-pack-align.xul not-full-basic-ref.xhtml
+skip-if(B2G&&browserIsRemote) == not-full-row-group-align.xul not-full-row-group-align-ref.xhtml # does anyone want/need this behavior?
+skip-if(B2G&&browserIsRemote) == not-full-row-group-pack.xul not-full-row-group-pack-ref.xhtml
+skip-if(B2G&&browserIsRemote) == not-full-row-group-direction.xul not-full-row-group-direction-ref.xhtml
+skip-if(B2G&&browserIsRemote) == not-full-row-leaf-align.xul not-full-basic-ref.xhtml
+skip-if(B2G&&browserIsRemote) == not-full-row-leaf-pack.xul not-full-row-leaf-pack-ref.xhtml
+skip-if(B2G&&browserIsRemote) == not-full-row-leaf-direction.xul not-full-row-leaf-pack-ref.xhtml
 skip-if(B2G) fails-if(Android&&browserIsRemote) == scrollable-columns.xul scrollable-columns-ref.xhtml # bug 650597, 732569
-fails == scrollable-rows.xul scrollable-rows-ref.xhtml
-== sizing-2d.xul sizing-2d-ref.xul
+fails skip-if(B2G&&browserIsRemote) == scrollable-rows.xul scrollable-rows-ref.xhtml
+skip-if(B2G&&browserIsRemote) == sizing-2d.xul sizing-2d-ref.xul
--- a/layout/xul/reftest/reftest.list
+++ b/layout/xul/reftest/reftest.list
@@ -1,5 +1,5 @@
-fails-if(Android||B2G) == textbox-multiline-noresize.xul textbox-multiline-ref.xul # reference is blank on Android (due to no native theme support?)
-!= textbox-multiline-resize.xul textbox-multiline-ref.xul 
-== popup-explicit-size.xul popup-explicit-size-ref.xul
-random-if(Android) == image-size.xul image-size-ref.xul
-== image-scaling-min-height-1.xul image-scaling-min-height-1-ref.xul
+fails-if(Android||B2G) skip-if(B2G&&browserIsRemote) == textbox-multiline-noresize.xul textbox-multiline-ref.xul # reference is blank on Android (due to no native theme support?)
+skip-if(B2G&&browserIsRemote) != textbox-multiline-resize.xul textbox-multiline-ref.xul 
+skip-if(B2G&&browserIsRemote) == popup-explicit-size.xul popup-explicit-size-ref.xul
+random-if(Android) skip-if(B2G&&browserIsRemote) == image-size.xul image-size-ref.xul
+skip-if(B2G&&browserIsRemote) == image-scaling-min-height-1.xul image-scaling-min-height-1-ref.xul
--- a/netwerk/base/public/nsIStreamLoader.idl
+++ b/netwerk/base/public/nsIStreamLoader.idl
@@ -22,19 +22,19 @@ interface nsIStreamLoaderObserver : nsIS
      *
      * This method will always be called asynchronously by the
      * nsIStreamLoader involved, on the thread that called the
      * loader's init() method.
      *
      * If the observer wants to take over responsibility for the
      * data buffer (result), it returns NS_SUCCESS_ADOPTED_DATA
      * in place of NS_OK as its success code. The loader will then
-     * "forget" about the data, and not NS_Free() it in its own
-     * destructor; observer must call NS_Free() when the data is
-     * no longer required.
+     * "forget" about the data and not NS_Free() it after
+     * onStreamComplete() returns; observer must call NS_Free()
+     * when the data is no longer required.
      */
     void onStreamComplete(in nsIStreamLoader loader,
                           in nsISupports ctxt,
                           in nsresult status,
                           in unsigned long resultLength,
                           [const,array,size_is(resultLength)] in octet result);
 };
 
--- a/netwerk/base/src/nsStreamLoader.cpp
+++ b/netwerk/base/src/nsStreamLoader.cpp
@@ -13,19 +13,17 @@ nsStreamLoader::nsStreamLoader()
   : mData(nullptr),
     mAllocated(0),
     mLength(0)
 {
 }
 
 nsStreamLoader::~nsStreamLoader()
 {
-  if (mData) {
-    NS_Free(mData);
-  }
+  ReleaseData();
 }
 
 NS_IMETHODIMP
 nsStreamLoader::Init(nsIStreamLoaderObserver* observer)
 {
   NS_ENSURE_ARG_POINTER(observer);
   mObserver = observer;
   return NS_OK;
@@ -98,20 +96,19 @@ nsStreamLoader::OnStopRequest(nsIRequest
     // provide nsIStreamLoader::request during call to OnStreamComplete
     mRequest = request;
     nsresult rv = mObserver->OnStreamComplete(this, mContext, aStatus,
                                               mLength, mData);
     if (rv == NS_SUCCESS_ADOPTED_DATA) {
       // the observer now owns the data buffer, and the loader must
       // not deallocate it
       mData = nullptr;
-      mLength = 0;
-      mAllocated = 0;
     }
     // done.. cleanup
+    ReleaseData();
     mRequest = 0;
     mObserver = 0;
     mContext = 0;
   }
   return NS_OK;
 }
 
 NS_METHOD
@@ -127,18 +124,17 @@ nsStreamLoader::WriteSegmentFun(nsIInput
   if (count > UINT32_MAX - self->mLength) {
     return NS_ERROR_ILLEGAL_VALUE; // is there a better error to use here?
   }
 
   if (self->mLength + count > self->mAllocated) {
     self->mData = static_cast<uint8_t*>(NS_Realloc(self->mData,
                                                    self->mLength + count));
     if (!self->mData) {
-      self->mLength = 0;
-      self->mAllocated = 0;
+      self->ReleaseData();
       return NS_ERROR_OUT_OF_MEMORY;
     }
     self->mAllocated = self->mLength + count;
   }
 
   ::memcpy(self->mData + self->mLength, fromSegment, count);
   self->mLength += count;
 
@@ -150,8 +146,19 @@ nsStreamLoader::WriteSegmentFun(nsIInput
 NS_IMETHODIMP 
 nsStreamLoader::OnDataAvailable(nsIRequest* request, nsISupports *ctxt, 
                                 nsIInputStream *inStr, 
                                 uint64_t sourceOffset, uint32_t count)
 {
   uint32_t countRead;
   return inStr->ReadSegments(WriteSegmentFun, this, count, &countRead);
 }
+
+void
+nsStreamLoader::ReleaseData()
+{
+  if (mData) {
+    NS_Free(mData);
+    mData = nullptr;
+  }
+  mLength = 0;
+  mAllocated = 0;
+}
--- a/netwerk/base/src/nsStreamLoader.h
+++ b/netwerk/base/src/nsStreamLoader.h
@@ -25,16 +25,20 @@ public:
 
   static nsresult
   Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
 
 protected:
   static NS_METHOD WriteSegmentFun(nsIInputStream *, void *, const char *,
                                    uint32_t, uint32_t, uint32_t *);
 
+  // Utility method to free mData, if present, and update other state to
+  // reflect that no data has been allocated.
+  void ReleaseData();
+
   nsCOMPtr<nsIStreamLoaderObserver> mObserver;
   nsCOMPtr<nsISupports>             mContext;  // the observer's context
   nsCOMPtr<nsIRequest>              mRequest;
 
   uint8_t  *mData;      // buffer to accumulate incoming data
   uint32_t  mAllocated; // allocated size of data buffer (we preallocate if
                         //   contentSize is available)
   uint32_t  mLength;    // actual length of data in buffer
--- a/security/manager/ssl/src/nsNSSCallbacks.cpp
+++ b/security/manager/ssl/src/nsNSSCallbacks.cpp
@@ -605,16 +605,20 @@ nsHTTPListener::nsHTTPListener()
 {
 }
 
 nsHTTPListener::~nsHTTPListener()
 {
   if (mResponsibleForDoneSignal)
     send_done_signal();
 
+  if (mResultData) {
+    NS_Free(const_cast<uint8_t *>(mResultData));
+  }
+
   if (mLoader) {
     nsCOMPtr<nsIThread> mainThread(do_GetMainThread());
     NS_ProxyRelease(mainThread, mLoader);
   }
 }
 
 NS_IMPL_ISUPPORTS1(nsHTTPListener, nsIStreamLoaderObserver)
 
@@ -673,17 +677,18 @@ nsHTTPListener::OnStreamComplete(nsIStre
 
   if (NS_SUCCEEDED(rv))
   {
     rv = hchan->GetRequestSucceeded(&mHttpRequestSucceeded);
     if (NS_FAILED(rv))
       mHttpRequestSucceeded = false;
 
     mResultLen = stringLen;
-    mResultData = string; // reference. Make sure loader lives as long as this
+    mResultData = string; // take ownership of allocation
+    aStatus = NS_SUCCESS_ADOPTED_DATA;
 
     unsigned int rcode;
     rv = hchan->GetResponseStatus(&rcode);
     if (NS_FAILED(rv))
       mHttpResponseCode = 500;
     else
       mHttpResponseCode = rcode;
 
--- a/security/manager/ssl/src/nsNSSCallbacks.h
+++ b/security/manager/ssl/src/nsNSSCallbacks.h
@@ -44,17 +44,17 @@ public:
   nsCOMPtr<nsIStreamLoader> mLoader;
 
   nsresult mResultCode;
 
   bool mHttpRequestSucceeded;
   uint16_t mHttpResponseCode;
   nsCString mHttpResponseContentType;
 
-  const uint8_t* mResultData; // not owned, refers to mLoader
+  const uint8_t* mResultData; // allocated in loader, but owned by listener
   uint32_t mResultLen;
   
   mozilla::Mutex mLock;
   mozilla::CondVar mCondition;
   volatile bool mWaitFlag;
   
   bool mResponsibleForDoneSignal;
   void send_done_signal();
--- a/testing/marionette/client/MANIFEST.in
+++ b/testing/marionette/client/MANIFEST.in
@@ -1,4 +1,6 @@
 recursive-include marionette/touch *.js
+recursive-include marionette/www *
+recursive-include marionette/chrome *
 recursive-include marionette/runner/mixins/resources *
 exclude MANIFEST.in
 include requirements.txt
--- a/testing/marionette/client/marionette/runner/base.py
+++ b/testing/marionette/client/marionette/runner/base.py
@@ -470,16 +470,20 @@ class BaseMarionetteOptions(OptionParser
         self.add_option('--this-chunk',
                         dest='this_chunk',
                         type=int,
                         help='which chunk to run')
         self.add_option('--sources',
                         dest='sources',
                         action='store',
                         help='path to sources.xml (Firefox OS only)')
+        self.add_option('--server-root',
+                        dest='server_root',
+                        action='store',
+                        help='sets the web server\'s root directory to the given path')
 
     def parse_args(self, args=None, values=None):
         options, tests = OptionParser.parse_args(self, args, values)
         for handler in self.parse_args_handlers:
             handler(options, tests, args, values)
 
         return (options, tests)
 
@@ -540,17 +544,18 @@ class BaseMarionetteTestRunner(object):
 
     def __init__(self, address=None, emulator=None, emulatorBinary=None,
                  emulatorImg=None, emulator_res='480x800', homedir=None,
                  app=None, app_args=None, bin=None, profile=None, autolog=False,
                  revision=None, logger=None, testgroup="marionette", noWindow=False,
                  logcat_dir=None, xml_output=None, repeat=0, gecko_path=None,
                  testvars=None, tree=None, type=None, device_serial=None,
                  symbols_path=None, timeout=None, es_servers=None, shuffle=False,
-                 sdcard=None, this_chunk=1, total_chunks=1, sources=None, **kwargs):
+                 sdcard=None, this_chunk=1, total_chunks=1, sources=None, server_root=None,
+                 **kwargs):
         self.address = address
         self.emulator = emulator
         self.emulatorBinary = emulatorBinary
         self.emulatorImg = emulatorImg
         self.emulator_res = emulator_res
         self.homedir = homedir
         self.app = app
         self.app_args = app_args or []
@@ -576,16 +581,17 @@ class BaseMarionetteTestRunner(object):
         self.timeout = timeout
         self._device = None
         self._capabilities = None
         self._appName = None
         self.es_servers = es_servers
         self.shuffle = shuffle
         self.sdcard = sdcard
         self.sources = sources
+        self.server_root = server_root
         self.this_chunk = this_chunk
         self.total_chunks = total_chunks
         self.mixin_run_tests = []
         self.manifest_skipped_tests = []
         self.tests = []
 
         if testvars:
             if not os.path.exists(testvars):
@@ -649,19 +655,22 @@ class BaseMarionetteTestRunner(object):
         self.failed = 0
         self.todo = 0
         self.failures = []
 
     def start_httpd(self, need_external_ip):
         host = "127.0.0.1"
         if need_external_ip:
             host = moznetwork.get_ip()
+        docroot = self.server_root or os.path.join(os.path.dirname(os.path.dirname(__file__)), 'www')
+        if not os.path.isdir(docroot):
+            raise Exception("Server root %s is not a valid path" % docroot)
         self.httpd = MozHttpd(host=host,
                               port=0,
-                              docroot=os.path.join(os.path.dirname(os.path.dirname(__file__)), 'www'))
+                              docroot=docroot)
         self.httpd.start()
         self.marionette.baseurl = 'http://%s:%d/' % (host, self.httpd.httpd.server_port)
         self.logger.info('running webserver on %s' % self.marionette.baseurl)
 
 
     def _build_kwargs(self):
         kwargs = {
             'device_serial': self.device_serial,
--- a/toolkit/content/tests/reftests/reftest.list
+++ b/toolkit/content/tests/reftests/reftest.list
@@ -1,2 +1,2 @@
-random-if(cocoaWidget) == bug-442419-progressmeter-max.xul bug-442419-progressmeter-max-ref.xul # fails most of the time on Mac because progress meter animates
-!= textbox-multiline-default-value.xul textbox-multiline-empty.xul
+skip-if(B2G&&browserIsRemote) random-if(cocoaWidget) == bug-442419-progressmeter-max.xul bug-442419-progressmeter-max-ref.xul # fails most of the time on Mac because progress meter animates # Bug 974780
+skip-if(B2G&&browserIsRemote) != textbox-multiline-default-value.xul textbox-multiline-empty.xul # Bug 974780