merge autoland to mozilla-central. r=merge a=merge
authorSebastian Hengst <archaeopteryx@coole-files.de>
Thu, 14 Sep 2017 11:04:14 +0200
changeset 430348 dd6b788f149763c4014c27f2fe1a1d13228bda82
parent 430334 6266decf217d4da5a18115cb5b1ff70feb76e7a5 (current diff)
parent 430347 1b5b6e3c41fc68b8f1efde169bd7962ba86b0a5b (diff)
child 430349 754d3df0517d5c374ac2b1515fab3621892c327d
child 430369 df71f64a2925339d0f431b07bdef74a61555c198
push id7761
push userjlund@mozilla.com
push dateFri, 15 Sep 2017 00:19:52 +0000
treeherdermozilla-beta@c38455951db4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge, merge
milestone57.0a1
first release with
nightly linux32
dd6b788f1497 / 57.0a1 / 20170914100122 / files
nightly linux64
dd6b788f1497 / 57.0a1 / 20170914100122 / files
nightly mac
dd6b788f1497 / 57.0a1 / 20170914100122 / files
nightly win32
dd6b788f1497 / 57.0a1 / 20170914100122 / files
nightly win64
dd6b788f1497 / 57.0a1 / 20170914100122 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
merge autoland to mozilla-central. r=merge a=merge MozReview-Commit-ID: 6nttXoSo3Fh
--- a/browser/extensions/formautofill/FormAutofillDoorhanger.jsm
+++ b/browser/extensions/formautofill/FormAutofillDoorhanger.jsm
@@ -107,17 +107,17 @@ const CONTENT = {
       accessKey: "S",
       callbackState: "save",
     },
     secondaryActions: [{
       label: GetStringFromName("cancelCreditCardLabel"),
       accessKey: "D",
       callbackState: "cancel",
     }, {
-      label: GetStringFromName("disableCreditCardLabel"),
+      label: GetStringFromName("neverSaveCreditCardLabel"),
       accessKey: "N",
       callbackState: "disable",
     }],
     options: {
       persistWhileVisible: true,
       popupIconURL: "chrome://formautofill/content/icon-credit-card.svg",
     },
   },
--- a/browser/extensions/formautofill/locales/en-US/formautofill.properties
+++ b/browser/extensions/formautofill/locales/en-US/formautofill.properties
@@ -17,17 +17,17 @@ autofillSecurityOptionsLinkOSX = Form Au
 changeAutofillOptionsOSX = Change Form Autofill Preferences
 addressesSyncCheckbox = Share addresses with synced devices
 updateAddressMessage = Would you like to update your address with this new information?
 createAddressLabel = Create New Address
 updateAddressLabel = Update Address
 saveCreditCardMessage = Would you like Firefox to save this credit card? (Security code will not be saved)
 saveCreditCardLabel = Save Credit Card
 cancelCreditCardLabel = Don’t Save
-disableCreditCardLabel = Never Save credit Cards
+neverSaveCreditCardLabel = Never Save Credit Cards
 openAutofillMessagePanel = Open Form Autofill message panel
 autocompleteFooterOption = Form Autofill Options
 autocompleteFooterOptionShort = More Options
 autocompleteFooterOptionOSX = Form Autofill Preferences
 autocompleteFooterOptionOSXShort = Preferences
 category.address = address
 category.name = name
 category.organization = company
--- a/browser/locales/searchplugins/chambers-en-GB.xml
+++ b/browser/locales/searchplugins/chambers-en-GB.xml
@@ -1,16 +1,15 @@
 <!-- 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/. -->
 
 <SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
 <ShortName>Chambers (UK)</ShortName>
 <Description>Chambers 21st Century Dictionary Search</Description>
 <InputEncoding>UTF-8</InputEncoding>
-<Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAARVBMVEV8grz///8cJoz8AgS8CiQ8QpxMUqQsMpRMDly8wtw8EmSMksS8RmT8iozsBgzM0uR8DkScosxscrSkLlzUGizs7vQsEmwP6BukAAAAYUlEQVR4XpXMNxLEIBBE0ekxgLzf+x9VmEKFlO3P+gVN/CmDI9pbWJCyBzqAHF2uggFR2XwFAph/IcTRh77CKhJBRQv4F3hgSGAVeAO6UeRUnQvwAEySy5ByR/ORW/+FthvNOwN3ZVtbCQAAAABJRU5ErkJggg==</Image>
-<Url type="text/html" method="GET" template="http://www.chambers.co.uk/search.php" resultdomain="chambers.co.uk">
+<Image width="16" height="16">data:image/x-icon;base64,AAABAAIAICAAAAEAIAAsAwAAJgAAABAQAAABACAAPwIAAFIDAACJUE5HDQoaCgAAAA1JSERSAAAAIAAAACAIBgAAAHN6evQAAALzSURBVFiF7ddNqBVlHMfxz5nqHpN8y7DyqjTYG2RwQWKCW5uiRRD2CkGbIl1IOxdBGFKgQRgkWC2iRUG1bBG0iUyCopgKJSyNskYjKiz0Kr1crzanxfMYc+fOOZ5z4tQi/6vhef7z/L4zz8v/9/B/j9agL+RJmuAiLMHF8fk3HMWvOJ6VxalKfgttzGRlUQ4NkCfpJbgFt+J6LMeCOPjJKD6Fb7APu7EHV2MLHs/K4ouBAfIknY97sRFrMYaf8DE+ww9YEaHWRrAEJ5Cjg5uxLiuLXfXxzz+L+DiexAOYH7/0ZezEl1lZnKzkjuHKmLsBl+K22N3BqiaNrgB5kq7E87gjftEMnsXTWVmcqOdnZTGD/XmSPoH38AwmYnerm1bSRXwxtlfE4U1sbxKvgfwZf/V6fF7purwvgLjKN+KeSv9RPJeVxVQv8RrIHjyGI7FpvC8ArIkAY5W2D/Bpv+KVeBuvoMSKPEnbPQHi1z9o9oLpYFdWFn8Mqp6VxWm8hINYink9AYQtdLvZ23Ma+wcVr8S3eEc4tBacDeAGrK61TeH7YdXj6fcCNuHnen99a9xo9twTtt/0sAAR4gAONPX9/Qfi/F/2T4SGieoUtLHyvwTodlq1ceG/AdDBqYacRUKxGTnANL5ryJmHa0YOkJVFB4caclq4KU/SC0YKEOMj/N6QN2nu+TASgL2a9+s47oz2aqQAv+AtoXjU8x425FrIk7SVJ+lknqRX9ASI6+B1fN0wzlXYHL3CoDEpOKm7egLEOIgd5q6FFu7HtjxJl/WjmifpWJ6k6/Ci4B3fqOc0zmk0ok/hEXNrw2m8i634JFqxpvcn8JBgaA9hQ1YWe/sCiIMsxOYIMaeMCk5nt2BWvoptqwQbPiE45CV4H5uaxHsCRIg27sOjglM6ryGtI7hlwrF9ZsxjeE3wkV3LeT/3gpZQpO4WfOJ1WNwFZgY/Cn/mVXxYte5DAdRgFgoH0rVCjViOZcKtqBAW2j4crl7PzkWv+AufXtBu3nNrKQAAAABJRU5ErkJggolQTkcNChoKAAAADUlIRFIAAAAQAAAAEAgGAAAAH/P/YQAAAgZJREFUOI2Nk7FrU1EUxn/n3PdSFYOCowX7koY4FAdbkUKFig5OIojF1UVwFbcKxsH/QF3sII4RRJwEhSpoadJYHSpYrEYDIlSDUCvSJu8eh7ynaQziN9zpnu9+3+/eC10ykDI4/k/ye0mHBQxgkWhfSzkpWM6QQLB1RJcs3nhohIUMwbuDrHwxEO0drmp0eVNZwuyEiCya2GMPP73ZNTSzrCr3Nmnn+6ao6NDNuhasqtH13rzPKGbnJXr0WvNWIToCUAanZVCAqsud24W7sEr7g3qZBqgxGhpojdFwguXvmDu9jm+YkwLAmdR9jsHtFY1evdVhq2h0O3XvTlBjNOykzF2s6NCVdE/QYRAeAkY2MAwa/ZCP8aIFYF5nMrR2AkyBDwBCZ7nA1FnnPtpb4nWpA3tlDVhL2FkngbEtJSmwG+BuHwMBsz/kDRKAJnyOMTwGJgeSBL5flV4pQBDryxhrtjvW48/JjwjYLJNBTwUnYMnpAqAGOsb7Bsj9AYQQ2RGqTQMc5Um7DM6SgwTiOQb3LrjoPGmFq6m7d6Uf+HoGQbGz8xrdeEMxOwWxJHWqQe6Yk+COh28AJVBJoqmAXyAqesfMgMlEFqVJ/BXjqSFqYvsFAi9cGo/rD0qgJfDdn0kFvDEZ1NzHU97kOGbDCHswVk1sVnzr1mE+NdO9fxFNu/5LvS/0F8COyR9a0q7OAAAAAElFTkSuQmCC</Image>
+<Url type="text/html" method="GET" template="http://www.chambers.co.uk/search/" resultdomain="chambers.co.uk" rel="searchform">
   <Param name="query" value="{searchTerms}"/>
   <Param name="title" value="21st"/>
   <Param name="sourceid" value="Mozilla-search"/>
 </Url>
-<SearchForm>http://www.chambers.co.uk/search.php</SearchForm>
 </SearchPlugin>
--- a/dom/media/AudioStream.cpp
+++ b/dom/media/AudioStream.cpp
@@ -14,16 +14,19 @@
 #include "mozilla/Mutex.h"
 #include "mozilla/Sprintf.h"
 #include <algorithm>
 #include "mozilla/Telemetry.h"
 #include "CubebUtils.h"
 #include "nsPrintfCString.h"
 #include "gfxPrefs.h"
 #include "AudioConverter.h"
+#if defined(XP_WIN)
+#include "nsXULAppAPI.h"
+#endif
 
 namespace mozilla {
 
 #undef LOG
 #undef LOGW
 
 LazyLogModule gAudioStreamLog("AudioStream");
 // For simple logs
--- a/dom/media/MediaCache.cpp
+++ b/dom/media/MediaCache.cpp
@@ -1861,46 +1861,38 @@ MediaCacheStream::NotifyDataStarted(int6
   mChannelOffset = aOffset;
   if (mStreamLength >= 0) {
     // If we started reading at a certain offset, then for sure
     // the stream is at least that long.
     mStreamLength = std::max(mStreamLength, mChannelOffset);
   }
 }
 
-bool
+void
 MediaCacheStream::UpdatePrincipal(nsIPrincipal* aPrincipal)
 {
-  return nsContentUtils::CombineResourcePrincipals(&mPrincipal, aPrincipal);
+  MOZ_ASSERT(NS_IsMainThread());
+  MediaCache::ResourceStreamIterator iter(mMediaCache, mResourceID);
+  while (MediaCacheStream* stream = iter.Next()) {
+    if (nsContentUtils::CombineResourcePrincipals(&stream->mPrincipal,
+                                                  aPrincipal)) {
+      stream->mClient->CacheClientNotifyPrincipalChanged();
+    }
+  }
 }
 
 void
-MediaCacheStream::NotifyDataReceived(int64_t aSize, const char* aData,
-    nsIPrincipal* aPrincipal)
+MediaCacheStream::NotifyDataReceived(int64_t aSize, const char* aData)
 {
   // This might happen off the main thread.
 
   // It is safe to read mClosed without holding the monitor because this
   // function is guaranteed to happen before Close().
   MOZ_DIAGNOSTIC_ASSERT(!mClosed);
 
-  // Update principals before putting the data in the cache. This is important,
-  // we want to make sure all principals are updated before any consumer
-  // can see the new data.
-  // We do this without holding the cache monitor, in case the client wants
-  // to do something that takes a lock.
-  {
-    MediaCache::ResourceStreamIterator iter(mMediaCache, mResourceID);
-    while (MediaCacheStream* stream = iter.Next()) {
-      if (stream->UpdatePrincipal(aPrincipal)) {
-        stream->mClient->CacheClientNotifyPrincipalChanged();
-      }
-    }
-  }
-
   ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
   int64_t size = aSize;
   const char* data = aData;
 
   LOG("Stream %p DataReceived at %" PRId64 " count=%" PRId64,
       this, mChannelOffset, aSize);
 
   // We process the data one block (or part of a block) at a time
--- a/dom/media/MediaCache.h
+++ b/dom/media/MediaCache.h
@@ -257,19 +257,17 @@ public:
   // ChannelMediaResource::CacheClientSeek. This can be called at any
   // time by the client, not just after a CacheClientSeek.
   void NotifyDataStarted(int64_t aOffset);
   // Notifies the cache that data has been received. The stream already
   // knows the offset because data is received in sequence and
   // the starting offset is known via NotifyDataStarted or because
   // the cache requested the offset in
   // ChannelMediaResource::CacheClientSeek, or because it defaulted to 0.
-  // We pass in the principal that was used to load this data.
-  void NotifyDataReceived(int64_t aSize, const char* aData,
-                          nsIPrincipal* aPrincipal);
+  void NotifyDataReceived(int64_t aSize, const char* aData);
   // Notifies the cache that the current bytes should be written to disk.
   // Called on the main thread.
   void FlushPartialBlock();
   // Notifies the cache that the channel has closed with the given status.
   void NotifyDataEnded(nsresult aStatus);
 
   // Notifies the stream that the channel is reopened. The stream should
   // reset variables such as |mDidNotifyDataEnded|.
@@ -347,16 +345,20 @@ public:
   // 'Read' for argument and return details.
   nsresult ReadAt(int64_t aOffset, char* aBuffer,
                   uint32_t aCount, uint32_t* aBytes);
 
   void ThrottleReadahead(bool bThrottle);
 
   size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const;
 
+  // Update mPrincipal for all streams of the same resource given that data has
+  // been received from aPrincipal
+  void UpdatePrincipal(nsIPrincipal* aPrincipal);
+
 private:
   friend class MediaCache;
 
   /**
    * A doubly-linked list of blocks. Add/Remove/Get methods are all
    * constant time. We declare this here so that a stream can contain a
    * BlockList of its read-ahead blocks. Blocks are referred to by index
    * into the MediaCache::mIndex array.
@@ -424,18 +426,16 @@ private:
   // This method assumes that the cache monitor is held and can be called on
   // any thread.
   int64_t GetNextCachedDataInternal(int64_t aOffset);
   // Writes |mPartialBlock| to disk.
   // Used by |NotifyDataEnded| and |FlushPartialBlock|.
   // If |aNotifyAll| is true, this function will wake up readers who may be
   // waiting on the media cache monitor. Called on the main thread only.
   void FlushPartialBlockInternal(bool aNotify, ReentrantMonitorAutoEnter& aReentrantMonitor);
-  // Update mPrincipal given that data has been received from aPrincipal
-  bool UpdatePrincipal(nsIPrincipal* aPrincipal);
 
   // Instance of MediaCache to use with this MediaCacheStream.
   RefPtr<MediaCache> mMediaCache;
 
   // These fields are main-thread-only.
   ChannelMediaResource*  mClient;
   nsCOMPtr<nsIPrincipal> mPrincipal;
   // True if CacheClientNotifyDataEnded has been called for this stream.
--- a/dom/media/MediaResource.cpp
+++ b/dom/media/MediaResource.cpp
@@ -430,71 +430,61 @@ ChannelMediaResource::OnChannelRedirect(
                                         int64_t aOffset)
 {
   mChannel = aNew;
   mSuspendAgent.NotifyChannelOpened(mChannel);
   return SetupChannelHeaders(aOffset);
 }
 
 nsresult
-ChannelMediaResource::CopySegmentToCache(nsIPrincipal* aPrincipal,
-                                         const char* aFromSegment,
+ChannelMediaResource::CopySegmentToCache(const char* aFromSegment,
                                          uint32_t aCount,
                                          uint32_t* aWriteCount)
 {
-  mCacheStream.NotifyDataReceived(aCount, aFromSegment, aPrincipal);
+  mCacheStream.NotifyDataReceived(aCount, aFromSegment);
   *aWriteCount = aCount;
   return NS_OK;
 }
 
-
-struct CopySegmentClosure {
-  nsCOMPtr<nsIPrincipal> mPrincipal;
-  ChannelMediaResource*  mResource;
-};
-
 nsresult
 ChannelMediaResource::CopySegmentToCache(nsIInputStream* aInStream,
-                                         void* aClosure,
+                                         void* aResource,
                                          const char* aFromSegment,
                                          uint32_t aToOffset,
                                          uint32_t aCount,
                                          uint32_t* aWriteCount)
 {
-  CopySegmentClosure* closure = static_cast<CopySegmentClosure*>(aClosure);
-  return closure->mResource->CopySegmentToCache(
-    closure->mPrincipal, aFromSegment, aCount, aWriteCount);
+  ChannelMediaResource* res = static_cast<ChannelMediaResource*>(aResource);
+  return res->CopySegmentToCache(aFromSegment, aCount, aWriteCount);
 }
 
 nsresult
 ChannelMediaResource::OnDataAvailable(nsIRequest* aRequest,
                                       nsIInputStream* aStream,
                                       uint32_t aCount)
 {
   // This might happen off the main thread.
   NS_ASSERTION(mChannel.get() == aRequest, "Wrong channel!");
 
+  // Update principals before putting the data in the cache. This is important,
+  // we want to make sure all principals are updated before any consumer can see
+  // the new data.
+  // TODO: Handle the case where OnDataAvailable() runs off the main thread.
+  UpdatePrincipal();
+
   RefPtr<ChannelMediaResource> self = this;
   nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
     "ChannelMediaResource::OnDataAvailable",
     [self, aCount]() { self->mChannelStatistics.AddBytes(aCount); });
   mCallback->AbstractMainThread()->Dispatch(r.forget());
 
-  CopySegmentClosure closure;
-  nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
-  if (secMan && mChannel) {
-    secMan->GetChannelResultPrincipal(mChannel, getter_AddRefs(closure.mPrincipal));
-  }
-  closure.mResource = this;
-
   uint32_t count = aCount;
   while (count > 0) {
     uint32_t read;
-    nsresult rv = aStream->ReadSegments(CopySegmentToCache, &closure, count,
-                                        &read);
+    nsresult rv = aStream->ReadSegments(CopySegmentToCache, this, count, &read);
     if (NS_FAILED(rv))
       return rv;
     NS_ASSERTION(read > 0, "Read 0 bytes while data was available?");
     count -= read;
   }
 
   return NS_OK;
 }
@@ -586,17 +576,18 @@ nsresult ChannelMediaResource::Close()
 {
   NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
 
   CloseChannel();
   mCacheStream.Close();
   return NS_OK;
 }
 
-already_AddRefed<nsIPrincipal> ChannelMediaResource::GetCurrentPrincipal()
+already_AddRefed<nsIPrincipal>
+ChannelMediaResource::GetCurrentPrincipal()
 {
   NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
 
   nsCOMPtr<nsIPrincipal> principal = mCacheStream.GetCurrentPrincipal();
   return principal.forget();
 }
 
 bool ChannelMediaResource::CanClone()
@@ -834,16 +825,28 @@ void
 ChannelMediaResource::CacheClientNotifyPrincipalChanged()
 {
   NS_ASSERTION(NS_IsMainThread(), "Don't call on non-main thread");
 
   mCallback->NotifyPrincipalChanged();
 }
 
 void
+ChannelMediaResource::UpdatePrincipal()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  nsCOMPtr<nsIPrincipal> principal;
+  nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
+  if (secMan && mChannel) {
+    secMan->GetChannelResultPrincipal(mChannel, getter_AddRefs(principal));
+    mCacheStream.UpdatePrincipal(principal);
+  }
+}
+
+void
 ChannelMediaResource::CacheClientNotifySuspendedStatusChanged()
 {
   NS_ASSERTION(NS_IsMainThread(), "Don't call on non-main thread");
   mCallback->NotifySuspendedStatusChanged(IsSuspendedByCache());
 }
 
 nsresult
 ChannelMediaResource::CacheClientSeek(int64_t aOffset, bool aResume)
--- a/dom/media/MediaResource.h
+++ b/dom/media/MediaResource.h
@@ -546,36 +546,37 @@ protected:
   // Opens the channel, using an HTTP byte range request to start at aOffset
   // if possible. Main thread only.
   nsresult OpenChannel(int64_t aOffset);
   nsresult RecreateChannel();
   // Add headers to HTTP request. Main thread only.
   nsresult SetupChannelHeaders(int64_t aOffset);
   // Closes the channel. Main thread only.
   void CloseChannel();
+  // Update the principal for the resource. Main thread only.
+  void UpdatePrincipal();
 
   int64_t GetOffset() const;
 
   // Parses 'Content-Range' header and returns results via parameters.
   // Returns error if header is not available, values are not parse-able or
   // values are out of range.
   nsresult ParseContentRangeHeader(nsIHttpChannel * aHttpChan,
                                    int64_t& aRangeStart,
                                    int64_t& aRangeEnd,
                                    int64_t& aRangeTotal);
 
   static nsresult CopySegmentToCache(nsIInputStream* aInStream,
-                                     void* aClosure,
+                                     void* aResource,
                                      const char* aFromSegment,
                                      uint32_t aToOffset,
                                      uint32_t aCount,
                                      uint32_t* aWriteCount);
 
-  nsresult CopySegmentToCache(nsIPrincipal* aPrincipal,
-                              const char* aFromSegment,
+  nsresult CopySegmentToCache(const char* aFromSegment,
                               uint32_t aCount,
                               uint32_t* aWriteCount);
 
   // Main thread access only
   RefPtr<Listener> mListener;
   // When this flag is set, if we get a network error we should silently
   // reopen the stream.
   bool               mReopenOnError;
--- a/gfx/layers/AnimationHelper.cpp
+++ b/gfx/layers/AnimationHelper.cpp
@@ -510,33 +510,29 @@ AnimationHelper::SetAnimations(Animation
 
     if (animation.baseStyle().type() != Animatable::Tnull_t) {
       aBaseAnimationStyle = ToStyleAnimationValue(animation.baseStyle());
     }
 
     AnimData* data = aAnimData.AppendElement();
     InfallibleTArray<Maybe<ComputedTimingFunction>>& functions =
       data->mFunctions;
+    InfallibleTArray<StyleAnimationValue>& startValues = data->mStartValues;
+    InfallibleTArray<StyleAnimationValue>& endValues = data->mEndValues;
+
     const InfallibleTArray<AnimationSegment>& segments = animation.segments();
-    for (uint32_t j = 0; j < segments.Length(); j++) {
-      TimingFunction tf = segments.ElementAt(j).sampleFn();
+    for (const AnimationSegment& segment : segments) {
+      startValues.AppendElement(ToStyleAnimationValue(segment.startState()));
+      endValues.AppendElement(ToStyleAnimationValue(segment.endState()));
 
+      TimingFunction tf = segment.sampleFn();
       Maybe<ComputedTimingFunction> ctf =
         AnimationUtils::TimingFunctionToComputedTimingFunction(tf);
       functions.AppendElement(ctf);
     }
-
-    // Precompute the StyleAnimationValues that we need if this is a transform
-    // animation.
-    InfallibleTArray<StyleAnimationValue>& startValues = data->mStartValues;
-    InfallibleTArray<StyleAnimationValue>& endValues = data->mEndValues;
-    for (const AnimationSegment& segment : segments) {
-      startValues.AppendElement(ToStyleAnimationValue(segment.startState()));
-      endValues.AppendElement(ToStyleAnimationValue(segment.endState()));
-    }
   }
 }
 
 uint64_t
 AnimationHelper::GetNextCompositorAnimationsId()
 {
   static uint32_t sNextId = 0;
   ++sNextId;
--- a/media/libstagefright/binding/MP4Metadata.cpp
+++ b/media/libstagefright/binding/MP4Metadata.cpp
@@ -758,16 +758,18 @@ MP4MetadataRust::Init()
   mp4parse_io io = { read_source, &mRustSource };
   mRustParser.reset(mp4parse_new(&io));
   MOZ_ASSERT(mRustParser);
 
   if (MOZ_LOG_TEST(sLog, LogLevel::Debug)) {
     mp4parse_log(true);
   }
 
+  mp4parse_fallible_allocation(true);
+
   mp4parse_status rv = mp4parse_read(mRustParser.get());
   MOZ_LOG(sLog, LogLevel::Debug, ("rust parser returned %d\n", rv));
   Telemetry::Accumulate(Telemetry::MEDIA_RUST_MP4PARSE_SUCCESS,
                         rv == mp4parse_status_OK);
   if (rv != mp4parse_status_OK && rv != mp4parse_status_TABLE_TOO_LARGE) {
     MOZ_LOG(sLog, LogLevel::Info, ("Rust mp4 parser fails to parse this stream."));
     MOZ_ASSERT(rv > 0);
     Telemetry::Accumulate(Telemetry::MEDIA_RUST_MP4PARSE_ERROR_CODE, rv);
--- a/media/libstagefright/binding/include/mp4parse.h
+++ b/media/libstagefright/binding/include/mp4parse.h
@@ -19,16 +19,17 @@ extern "C" {
 typedef enum mp4parse_status {
 	mp4parse_status_OK = 0,
 	mp4parse_status_BAD_ARG = 1,
 	mp4parse_status_INVALID = 2,
 	mp4parse_status_UNSUPPORTED = 3,
 	mp4parse_status_EOF = 4,
 	mp4parse_status_IO = 5,
 	mp4parse_status_TABLE_TOO_LARGE = 6,
+	mp4parse_status_OOM = 7,
 } mp4parse_status;
 
 typedef enum mp4parse_track_type {
 	mp4parse_track_type_VIDEO = 0,
 	mp4parse_track_type_AUDIO = 1,
 } mp4parse_track_type;
 
 typedef enum mp4parse_codec {
@@ -113,16 +114,18 @@ typedef struct mp4parse_io {
 mp4parse_parser* mp4parse_new(mp4parse_io const* io);
 
 /// Free an `mp4parse_parser*` allocated by `mp4parse_new()`.
 void mp4parse_free(mp4parse_parser* parser);
 
 /// Enable `mp4_parser` log.
 void mp4parse_log(bool enable);
 
+void mp4parse_fallible_allocation(bool enable);
+
 /// Run the `mp4parse_parser*` allocated by `mp4parse_new()` until EOF or error.
 mp4parse_status mp4parse_read(mp4parse_parser* parser);
 
 /// Return the number of tracks parsed by previous `mp4parse_read()` call.
 mp4parse_status mp4parse_get_track_count(mp4parse_parser const* parser, uint32_t* count);
 
 /// Fill the supplied `mp4parse_track_info` with metadata for `track`.
 mp4parse_status mp4parse_get_track_info(mp4parse_parser* parser, uint32_t track_index, mp4parse_track_info* info);
--- a/media/libstagefright/binding/mp4parse-cargo.patch
+++ b/media/libstagefright/binding/mp4parse-cargo.patch
@@ -1,28 +1,30 @@
 diff --git a/media/libstagefright/binding/mp4parse/Cargo.toml b/media/libstagefright/binding/mp4parse/Cargo.toml
 index ff9422c..814c4c6 100644
 --- a/media/libstagefright/binding/mp4parse/Cargo.toml
 +++ b/media/libstagefright/binding/mp4parse/Cargo.toml
-@@ -20,19 +20,11 @@ exclude = [
+@@ -20,20 +20,12 @@ exclude = [
  ]
  
 -[badges]
 -travis-ci = { repository = "https://github.com/mozilla/mp4parse-rust" }
  
  [dependencies]
 -byteorder = "1.0.0"
 -afl = { version = "0.1.1", optional = true }
 -afl-plugin = { version = "0.1.1", optional = true }
 -abort_on_panic = { version = "1.0.0", optional = true }
 -bitreader = { version = "0.3.0" }
 -num-traits = "0.1.37"
+-mp4parse_fallible = { path = "../mp4parse_fallible" }
 +byteorder = "1.0.0"
 +bitreader = { version = "0.3.0" }
 +num-traits = "0.1.37"
++mp4parse_fallible = { path = "../mp4parse_fallible" }
  
  [dev-dependencies]
  test-assembler = "0.1.2"
  
 -[features]
 -fuzz = ["afl", "afl-plugin", "abort_on_panic"]
 -
  # Somewhat heavy-handed, but we want at least -Z force-overflow-checks=on.
--- a/media/libstagefright/binding/mp4parse/Cargo.toml
+++ b/media/libstagefright/binding/mp4parse/Cargo.toml
@@ -19,12 +19,13 @@ exclude = [
   "*.mp4",
 ]
 
 
 [dependencies]
 byteorder = "1.0.0"
 bitreader = { version = "0.3.0" }
 num-traits = "0.1.37"
+mp4parse_fallible = { path = "../mp4parse_fallible" }
 
 [dev-dependencies]
 test-assembler = "0.1.2"
 
--- a/media/libstagefright/binding/mp4parse/src/lib.rs
+++ b/media/libstagefright/binding/mp4parse/src/lib.rs
@@ -6,43 +6,50 @@
 #![cfg_attr(feature = "fuzz", feature(plugin))]
 #![cfg_attr(feature = "fuzz", plugin(afl_plugin))]
 #[cfg(feature = "fuzz")]
 extern crate afl;
 
 extern crate byteorder;
 extern crate bitreader;
 extern crate num_traits;
+extern crate mp4parse_fallible;
 use byteorder::{ReadBytesExt, WriteBytesExt};
 use bitreader::{BitReader, ReadInto};
 use std::io::{Read, Take};
 use std::io::Cursor;
 use std::cmp;
 use num_traits::Num;
+use mp4parse_fallible::FallibleVec;
 
 mod boxes;
 use boxes::{BoxType, FourCC};
 
 // Unit tests.
 #[cfg(test)]
 mod tests;
 
 // Arbitrary buffer size limit used for raw read_bufs on a box.
 const BUF_SIZE_LIMIT: usize = 1024 * 1024;
 
 // Max table length. Calculating in worth case for one week long video, one
 // frame per table entry in 30 fps.
-#[cfg(target_pointer_width = "64")]
 const TABLE_SIZE_LIMIT: u32 = 30 * 60 * 60 * 24 * 7;
 
-// Reduce max table length if it is in 32 arch for memory problem.
-#[cfg(target_pointer_width = "32")]
-const TABLE_SIZE_LIMIT: u32 = 30 * 60 * 60 * 24;
+static DEBUG_MODE: std::sync::atomic::AtomicBool = std::sync::atomic::ATOMIC_BOOL_INIT;
+
+static FALLIBLE_ALLOCATION: std::sync::atomic::AtomicBool = std::sync::atomic::ATOMIC_BOOL_INIT;
 
-static DEBUG_MODE: std::sync::atomic::AtomicBool = std::sync::atomic::ATOMIC_BOOL_INIT;
+pub fn set_fallible_allocation_mode(fallible: bool) {
+    FALLIBLE_ALLOCATION.store(fallible, std::sync::atomic::Ordering::SeqCst);
+}
+
+fn get_fallible_allocation_mode() -> bool {
+    FALLIBLE_ALLOCATION.load(std::sync::atomic::Ordering::Relaxed)
+}
 
 pub fn set_debug_mode(mode: bool) {
     DEBUG_MODE.store(mode, std::sync::atomic::Ordering::SeqCst);
 }
 
 #[inline(always)]
 fn get_debug_mode() -> bool {
     DEBUG_MODE.load(std::sync::atomic::Ordering::Relaxed)
@@ -51,16 +58,47 @@ fn get_debug_mode() -> bool {
 macro_rules! log {
     ($($args:tt)*) => (
         if get_debug_mode() {
             println!( $( $args )* );
         }
     )
 }
 
+// TODO: vec_push() and vec_reserve() needs to be replaced when Rust supports
+// fallible memory allocation in raw_vec.
+pub fn vec_push<T>(vec: &mut Vec<T>, val: T) -> std::result::Result<(), ()> {
+    if get_fallible_allocation_mode() {
+        return vec.try_push(val);
+    }
+
+    vec.push(val);
+    Ok(())
+}
+
+pub fn vec_reserve<T>(vec: &mut Vec<T>, size: usize) -> std::result::Result<(), ()> {
+    if get_fallible_allocation_mode() {
+        return vec.try_reserve(size);
+    }
+
+    vec.reserve(size);
+    Ok(())
+}
+
+fn reserve_read_buf(size: usize) -> std::result::Result<Vec<u8>, ()> {
+    if get_fallible_allocation_mode() {
+        let mut buf: Vec<u8> = Vec::new();
+        buf.try_reserve(size)?;
+        unsafe { buf.set_len(size); }
+        return Ok(buf);
+    }
+
+    Ok(vec![0; size])
+}
+
 /// Describes parser failures.
 ///
 /// This enum wraps the standard `io::Error` type, unified with
 /// our own parser error states and those of crates we use.
 #[derive(Debug)]
 pub enum Error {
     /// Parse error caused by corrupt or malformed data.
     InvalidData(&'static str),
@@ -69,16 +107,18 @@ pub enum Error {
     /// Reflect `std::io::ErrorKind::UnexpectedEof` for short data.
     UnexpectedEOF,
     /// Propagate underlying errors from `std::io`.
     Io(std::io::Error),
     /// read_mp4 terminated without detecting a moov box.
     NoMoov,
     /// Parse error caused by table size is over limitation.
     TableTooLarge,
+    /// Out of memory
+    OutOfMemory,
 }
 
 impl From<bitreader::BitReaderError> for Error {
     fn from(_: bitreader::BitReaderError) -> Error {
         Error::InvalidData("invalid data")
     }
 }
 
@@ -92,16 +132,22 @@ impl From<std::io::Error> for Error {
 }
 
 impl From<std::string::FromUtf8Error> for Error {
     fn from(_: std::string::FromUtf8Error) -> Error {
         Error::InvalidData("invalid utf8")
     }
 }
 
+impl From<()> for Error {
+    fn from(_: ()) -> Error {
+        Error::OutOfMemory
+    }
+}
+
 /// Result shorthand using our Error enum.
 pub type Result<T> = std::result::Result<T, Error>;
 
 /// Basic ISO box structure.
 ///
 /// mp4 files are a sequence of possibly-nested 'box' structures.  Each box
 /// begins with a header describing the length of the box's data and a
 /// four-byte box type which identifies the type of the box. Together these
@@ -684,27 +730,27 @@ fn read_moov<T: Read>(f: &mut BMFFBox<T>
             BoxType::MovieHeaderBox => {
                 let (mvhd, timescale) = parse_mvhd(&mut b)?;
                 context.timescale = timescale;
                 log!("{:?}", mvhd);
             }
             BoxType::TrackBox => {
                 let mut track = Track::new(context.tracks.len());
                 read_trak(&mut b, &mut track)?;
-                context.tracks.push(track);
+                vec_push(&mut context.tracks, track)?;
             }
             BoxType::MovieExtendsBox => {
                 let mvex = read_mvex(&mut b)?;
                 log!("{:?}", mvex);
                 context.mvex = Some(mvex);
             }
             BoxType::ProtectionSystemSpecificHeaderBox => {
                 let pssh = read_pssh(&mut b)?;
                 log!("{:?}", pssh);
-                context.psshs.push(pssh);
+                vec_push(&mut context.psshs, pssh)?;
             }
             _ => skip_box_content(&mut b)?,
         };
         check_parser_state!(b.content);
     }
     Ok(())
 }
 
@@ -718,29 +764,29 @@ fn read_pssh<T: Read>(src: &mut BMFFBox<
 
         let system_id = read_buf(pssh, 16)?;
 
         let mut kid: Vec<ByteData> = Vec::new();
         if version > 0 {
             let count = be_u32_with_limit(pssh)?;
             for _ in 0..count {
                 let item = read_buf(pssh, 16)?;
-                kid.push(item);
+                vec_push(&mut kid, item)?;
             }
         }
 
         let data_size = be_u32_with_limit(pssh)? as usize;
         let data = read_buf(pssh, data_size)?;
 
         (system_id, kid, data)
     };
 
     let mut pssh_box = Vec::new();
     write_be_u32(&mut pssh_box, src.head.size as u32)?;
-    pssh_box.append(&mut b"pssh".to_vec());
+    pssh_box.extend_from_slice(b"pssh");
     pssh_box.append(&mut box_content);
 
     Ok(ProtectionSystemSpecificHeaderBox {
         system_id: system_id,
         kid: kid,
         data: data,
         box_content: pssh_box,
     })
@@ -935,17 +981,17 @@ fn read_ftyp<T: Read>(src: &mut BMFFBox<
     let bytes_left = src.bytes_left();
     if bytes_left % 4 != 0 {
         return Err(Error::InvalidData("invalid ftyp size"));
     }
     // Is a brand_count of zero valid?
     let brand_count = bytes_left / 4;
     let mut brands = Vec::new();
     for _ in 0..brand_count {
-        brands.push(From::from(be_u32(src)?));
+        vec_push(&mut brands, From::from(be_u32(src)?))?;
     }
     Ok(FileTypeBox {
         major_brand: From::from(major),
         minor_version: minor,
         compatible_brands: brands,
     })
 }
 
@@ -1044,22 +1090,22 @@ fn read_elst<T: Read>(src: &mut BMFFBox<
             0 => {
                 // 32 bit segment duration and media times.
                 (be_u32(src)? as u64, be_i32(src)? as i64)
             }
             _ => return Err(Error::InvalidData("unhandled elst version")),
         };
         let media_rate_integer = be_i16(src)?;
         let media_rate_fraction = be_i16(src)?;
-        edits.push(Edit {
+        vec_push(&mut edits, Edit {
             segment_duration: segment_duration,
             media_time: media_time,
             media_rate_integer: media_rate_integer,
             media_rate_fraction: media_rate_fraction,
-        })
+        })?;
     }
 
     Ok(EditListBox {
         edits: edits,
     })
 }
 
 /// Parse a mdhd box.
@@ -1105,51 +1151,51 @@ fn read_mdhd<T: Read>(src: &mut BMFFBox<
 }
 
 /// Parse a stco box.
 fn read_stco<T: Read>(src: &mut BMFFBox<T>) -> Result<ChunkOffsetBox> {
     let (_, _) = read_fullbox_extra(src)?;
     let offset_count = be_u32_with_limit(src)?;
     let mut offsets = Vec::new();
     for _ in 0..offset_count {
-        offsets.push(be_u32(src)? as u64);
+        vec_push(&mut offsets, be_u32(src)? as u64)?;
     }
 
     // Padding could be added in some contents.
     skip_box_remain(src)?;
 
     Ok(ChunkOffsetBox {
         offsets: offsets,
     })
 }
 
 /// Parse a co64 box.
 fn read_co64<T: Read>(src: &mut BMFFBox<T>) -> Result<ChunkOffsetBox> {
     let (_, _) = read_fullbox_extra(src)?;
     let offset_count = be_u32_with_limit(src)?;
     let mut offsets = Vec::new();
     for _ in 0..offset_count {
-        offsets.push(be_u64(src)?);
+        vec_push(&mut offsets, be_u64(src)?)?;
     }
 
     // Padding could be added in some contents.
     skip_box_remain(src)?;
 
     Ok(ChunkOffsetBox {
         offsets: offsets,
     })
 }
 
 /// Parse a stss box.
 fn read_stss<T: Read>(src: &mut BMFFBox<T>) -> Result<SyncSampleBox> {
     let (_, _) = read_fullbox_extra(src)?;
     let sample_count = be_u32_with_limit(src)?;
     let mut samples = Vec::new();
     for _ in 0..sample_count {
-        samples.push(be_u32(src)?);
+        vec_push(&mut samples, be_u32(src)?)?;
     }
 
     // Padding could be added in some contents.
     skip_box_remain(src)?;
 
     Ok(SyncSampleBox {
         samples: samples,
     })
@@ -1159,21 +1205,21 @@ fn read_stss<T: Read>(src: &mut BMFFBox<
 fn read_stsc<T: Read>(src: &mut BMFFBox<T>) -> Result<SampleToChunkBox> {
     let (_, _) = read_fullbox_extra(src)?;
     let sample_count = be_u32_with_limit(src)?;
     let mut samples = Vec::new();
     for _ in 0..sample_count {
         let first_chunk = be_u32(src)?;
         let samples_per_chunk = be_u32_with_limit(src)?;
         let sample_description_index = be_u32(src)?;
-        samples.push(SampleToChunk {
+        vec_push(&mut samples, SampleToChunk {
             first_chunk: first_chunk,
             samples_per_chunk: samples_per_chunk,
             sample_description_index: sample_description_index,
-        });
+        })?;
     }
 
     // Padding could be added in some contents.
     skip_box_remain(src)?;
 
     Ok(SampleToChunkBox {
         samples: samples,
     })
@@ -1198,20 +1244,20 @@ fn read_ctts<T: Read>(src: &mut BMFFBox<
                 let count = be_u32_with_limit(src)?;
                 let offset = TimeOffsetVersion::Version1(be_i32(src)?);
                 (count, offset)
             },
             _ => {
                 return Err(Error::InvalidData("unsupported version in 'ctts' box"));
             }
         };
-        offsets.push(TimeOffset {
+        vec_push(&mut offsets, TimeOffset {
             sample_count: sample_count,
             time_offset: time_offset,
-        });
+        })?;
     }
 
     skip_box_remain(src)?;
 
     Ok(CompositionOffsetBox {
         samples: offsets,
     })
 }
@@ -1219,17 +1265,17 @@ fn read_ctts<T: Read>(src: &mut BMFFBox<
 /// Parse a stsz box.
 fn read_stsz<T: Read>(src: &mut BMFFBox<T>) -> Result<SampleSizeBox> {
     let (_, _) = read_fullbox_extra(src)?;
     let sample_size = be_u32(src)?;
     let sample_count = be_u32_with_limit(src)?;
     let mut sample_sizes = Vec::new();
     if sample_size == 0 {
         for _ in 0..sample_count {
-            sample_sizes.push(be_u32(src)?);
+            vec_push(&mut sample_sizes, be_u32(src)?)?;
         }
     }
 
     // Padding could be added in some contents.
     skip_box_remain(src)?;
 
     Ok(SampleSizeBox {
         sample_size: sample_size,
@@ -1240,20 +1286,20 @@ fn read_stsz<T: Read>(src: &mut BMFFBox<
 /// Parse a stts box.
 fn read_stts<T: Read>(src: &mut BMFFBox<T>) -> Result<TimeToSampleBox> {
     let (_, _) = read_fullbox_extra(src)?;
     let sample_count = be_u32_with_limit(src)?;
     let mut samples = Vec::new();
     for _ in 0..sample_count {
         let sample_count = be_u32_with_limit(src)?;
         let sample_delta = be_u32(src)?;
-        samples.push(Sample {
+        vec_push(&mut samples, Sample {
             sample_count: sample_count,
             sample_delta: sample_delta,
-        });
+        })?;
     }
 
     // Padding could be added in some contents.
     skip_box_remain(src)?;
 
     Ok(TimeToSampleBox {
         samples: samples,
     })
@@ -1450,17 +1496,17 @@ fn read_ds_descriptor(data: &[u8], esds:
         channel_counts += read_surround_channel_count(bit_reader, num_back_channel)?;
         channel_counts += read_surround_channel_count(bit_reader, num_lfe_channel)?;
     }
 
     esds.audio_object_type = Some(audio_object_type);
     esds.audio_sample_rate = sample_frequency;
     esds.audio_channel_count = Some(channel_counts);
     assert!(esds.decoder_specific_data.is_empty());
-    esds.decoder_specific_data.extend(data.iter());
+    esds.decoder_specific_data.extend_from_slice(data);
 
     Ok(())
 }
 
 fn read_surround_channel_count(bit_reader: &mut BitReader, channels: u8) -> Result<u16> {
     let mut count = 0;
     for _ in 0..channels {
         let is_cpe: bool = ReadInto::read(bit_reader, 1)?;
@@ -1538,17 +1584,17 @@ fn read_dfla<T: Read>(src: &mut BMFFBox<
         return Err(Error::Unsupported("unknown dfLa (FLAC) version"));
     }
     if flags != 0 {
         return Err(Error::InvalidData("no-zero dfLa (FLAC) flags"));
     }
     let mut blocks = Vec::new();
     while src.bytes_left() > 0 {
         let block = read_flac_metadata(src)?;
-        blocks.push(block);
+        vec_push(&mut blocks, block)?;
     }
     // The box must have at least one meta block, and the first block
     // must be the METADATA_BLOCK_STREAMINFO
     if blocks.is_empty() {
         return Err(Error::InvalidData("FLACSpecificBox missing metadata"));
     } else if blocks[0].block_type != 0 {
         return Err(Error::InvalidData(
                 "FLACSpecificBox must have STREAMINFO metadata first"));
@@ -1732,17 +1778,17 @@ fn read_video_sample_entry<T: Read>(src:
                 codec_specific = Some(VideoCodecSpecific::ESDSConfig(esds));
             }
             BoxType::ProtectionSchemeInformationBox => {
                 if name != BoxType::ProtectedVisualSampleEntry {
                     return Err(Error::InvalidData("malformed video sample entry"));
                 }
                 let sinf = read_sinf(&mut b)?;
                 log!("{:?} (sinf)", sinf);
-                protection_info.push(sinf);
+                vec_push(&mut protection_info, sinf)?;
             }
             _ => {
                 log!("Unsupported video codec, box {:?} found", b.head.name);
                 skip_box_content(&mut b)?;
             }
         }
         check_parser_state!(b.content);
     }
@@ -1857,17 +1903,17 @@ fn read_audio_sample_entry<T: Read>(src:
             }
             BoxType::ProtectionSchemeInformationBox => {
                 if name != BoxType::ProtectedAudioSampleEntry {
                     return Err(Error::InvalidData("malformed audio sample entry"));
                 }
                 let sinf = read_sinf(&mut b)?;
                 log!("{:?} (sinf)", sinf);
                 codec_type = CodecType::EncryptedAudio;
-                protection_info.push(sinf);
+                vec_push(&mut protection_info, sinf)?;
             }
             _ => {
                 log!("Unsupported audio codec, box {:?} found", b.head.name);
                 skip_box_content(&mut b)?;
             }
         }
         check_parser_state!(b.content);
     }
@@ -1915,17 +1961,17 @@ fn read_stsd<T: Read>(src: &mut BMFFBox<
                 }
                 Err(e) => return Err(e),
             };
             if track.data.is_none() {
                 track.data = Some(description.clone());
             } else {
                 log!("** don't know how to handle multiple descriptions **");
             }
-            descriptions.push(description);
+            vec_push(&mut descriptions, description)?;
             check_parser_state!(b.content);
             if descriptions.len() == description_count as usize {
                 break;
             }
         }
     }
 
     // Padding could be added in some contents.
@@ -2010,22 +2056,25 @@ fn skip<T: Read>(src: &mut T, mut bytes:
     Ok(())
 }
 
 /// Read size bytes into a Vector or return error.
 fn read_buf<T: ReadBytesExt>(src: &mut T, size: usize) -> Result<Vec<u8>> {
     if size > BUF_SIZE_LIMIT {
         return Err(Error::InvalidData("read_buf size exceeds BUF_SIZE_LIMIT"));
     }
-    let mut buf = vec![0; size];
-    let r = src.read(&mut buf)?;
-    if r != size {
-        return Err(Error::InvalidData("failed buffer read"));
+    if let Ok(mut buf) = reserve_read_buf(size) {
+        let r = src.read(&mut buf)?;
+        if r != size {
+          return Err(Error::InvalidData("failed buffer read"));
+        }
+        return Ok(buf);
     }
-    Ok(buf)
+
+    Err(Error::OutOfMemory)
 }
 
 fn be_i16<T: ReadBytesExt>(src: &mut T) -> Result<i16> {
     src.read_i16::<byteorder::BigEndian>().map_err(From::from)
 }
 
 fn be_i32<T: ReadBytesExt>(src: &mut T) -> Result<i32> {
     src.read_i32::<byteorder::BigEndian>().map_err(From::from)
--- a/media/libstagefright/binding/mp4parse_capi/src/lib.rs
+++ b/media/libstagefright/binding/mp4parse_capi/src/lib.rs
@@ -53,28 +53,30 @@ use mp4parse::AudioCodecSpecific;
 use mp4parse::VideoCodecSpecific;
 use mp4parse::MediaTimeScale;
 use mp4parse::MediaScaledTime;
 use mp4parse::TrackTimeScale;
 use mp4parse::TrackScaledTime;
 use mp4parse::serialize_opus_header;
 use mp4parse::CodecType;
 use mp4parse::Track;
+use mp4parse::vec_push;
 
 #[allow(non_camel_case_types)]
 #[repr(C)]
 #[derive(PartialEq, Debug)]
 pub enum mp4parse_status {
     OK = 0,
     BAD_ARG = 1,
     INVALID = 2,
     UNSUPPORTED = 3,
     EOF = 4,
     IO = 5,
     TABLE_TOO_LARGE = 6,
+    OOM = 7,
 }
 
 #[allow(non_camel_case_types)]
 #[repr(C)]
 #[derive(PartialEq, Debug)]
 pub enum mp4parse_track_type {
     VIDEO = 0,
     AUDIO = 1,
@@ -303,26 +305,31 @@ pub unsafe extern fn mp4parse_free(parse
 }
 
 /// Enable `mp4_parser` log.
 #[no_mangle]
 pub unsafe extern fn mp4parse_log(enable: bool) {
     mp4parse::set_debug_mode(enable);
 }
 
+#[no_mangle]
+pub unsafe extern fn mp4parse_fallible_allocation(enable: bool) {
+    mp4parse::set_fallible_allocation_mode(enable);
+}
+
 /// Run the `mp4parse_parser*` allocated by `mp4parse_new()` until EOF or error.
 #[no_mangle]
 pub unsafe extern fn mp4parse_read(parser: *mut mp4parse_parser) -> mp4parse_status {
     // Validate arguments from C.
     if parser.is_null() || (*parser).poisoned() {
         return mp4parse_status::BAD_ARG;
     }
 
-    let mut context = (*parser).context_mut();
-    let mut io = (*parser).io_mut();
+    let context = (*parser).context_mut();
+    let io = (*parser).io_mut();
 
     let r = read_mp4(io, context);
     match r {
         Ok(_) => mp4parse_status::OK,
         Err(Error::NoMoov) | Err(Error::InvalidData(_)) => {
             // Block further calls. We've probable lost sync.
             (*parser).set_poisoned(true);
             mp4parse_status::INVALID
@@ -333,16 +340,17 @@ pub unsafe extern fn mp4parse_read(parse
             // Block further calls after a read failure.
             // Getting std::io::ErrorKind::UnexpectedEof is normal
             // but our From trait implementation should have converted
             // those to our Error::UnexpectedEOF variant.
             (*parser).set_poisoned(true);
             mp4parse_status::IO
         },
         Err(Error::TableTooLarge) => mp4parse_status::TABLE_TOO_LARGE,
+        Err(Error::OutOfMemory) => mp4parse_status::OOM,
     }
 }
 
 /// Return the number of tracks parsed by previous `mp4parse_read()` call.
 #[no_mangle]
 pub unsafe extern fn mp4parse_get_track_count(parser: *const mp4parse_parser, count: *mut u32) -> mp4parse_status {
     // Validate arguments from C.
     if parser.is_null() || count.is_null() || (*parser).poisoned() {
@@ -895,26 +903,27 @@ fn create_sample_table(track: &Track, tr
                 (t, _) if t > 0 => start_offset + t as u64,
                 _ => 0,
             };
             if end_offset == 0 {
                 return None;
             }
             cur_position = end_offset;
 
-            sample_table.push(
-                mp4parse_indice {
-                    start_offset: start_offset,
-                    end_offset: end_offset,
-                    start_composition: 0,
-                    end_composition: 0,
-                    start_decode: 0,
-                    sync: !has_sync_table,
-                }
-            );
+            let res = vec_push(&mut sample_table, mp4parse_indice {
+                start_offset: start_offset,
+                end_offset: end_offset,
+                start_composition: 0,
+                end_composition: 0,
+                start_decode: 0,
+                sync: !has_sync_table,
+            });
+            if res.is_err() {
+                return None;
+            }
         }
     }
 
     // Mark the sync sample in sample_table according to 'stss'.
     if let Some(ref v) = track.stss {
         for iter in &v.samples {
             if let Some(elem) = sample_table.get_mut((iter - 1) as usize) {
                 elem.sync = true;
@@ -972,22 +981,23 @@ fn create_sample_table(track: &Track, tr
             _ => return None,
         }
     }
 
     // Correct composition end time due to 'ctts' causes composition time re-ordering.
     //
     // Composition end time is not in specification. However, gecko needs it, so we need to
     // calculate to correct the composition end time.
-    if track.ctts.is_some() {
+    if sample_table.len() > 0 {
         // Create an index table refers to sample_table and sorted by start_composisiton time.
         let mut sort_table = Vec::new();
-        sort_table.reserve(sample_table.len());
         for i in 0 .. sample_table.len() {
-            sort_table.push(i);
+            if vec_push(&mut sort_table, i).is_err() {
+                return None;
+            }
         }
 
         sort_table.sort_by_key(|i| {
             match sample_table.get(*i) {
                 Some(v) => {
                     v.start_composition
                 },
                 _ => 0,
@@ -1111,17 +1121,17 @@ extern fn panic_read(_: *mut u8, _: usiz
 
 #[cfg(test)]
 extern fn error_read(_: *mut u8, _: usize, _: *mut std::os::raw::c_void) -> isize {
     -1
 }
 
 #[cfg(test)]
 extern fn valid_read(buf: *mut u8, size: usize, userdata: *mut std::os::raw::c_void) -> isize {
-    let mut input: &mut std::fs::File = unsafe { &mut *(userdata as *mut _) };
+    let input: &mut std::fs::File = unsafe { &mut *(userdata as *mut _) };
 
     let mut buf = unsafe { std::slice::from_raw_parts_mut(buf, size) };
     match input.read(&mut buf) {
         Ok(n) => n as isize,
         Err(_) => -1,
     }
 }
 
@@ -1275,16 +1285,18 @@ fn get_track_count_poisoned_parser() {
         assert!(!parser.is_null());
 
         // Our mp4parse_io read should simply fail with an error.
         assert_eq!(mp4parse_status::IO, mp4parse_read(parser));
 
         let mut count: u32 = 0;
         let rv = mp4parse_get_track_count(parser, &mut count);
         assert_eq!(rv, mp4parse_status::BAD_ARG);
+
+        mp4parse_free(parser);
     }
 }
 
 #[test]
 fn arg_validation_with_data() {
     unsafe {
         let mut file = std::fs::File::open("../mp4parse/tests/minimal.mp4").unwrap();
         let io = mp4parse_io { read: Some(valid_read),
new file mode 100644
--- /dev/null
+++ b/media/libstagefright/binding/mp4parse_fallible/Cargo.toml
@@ -0,0 +1,10 @@
+[package]
+name = "mp4parse_fallible"
+version = "0.0.1"
+authors = ["The Servo Project Developers"]
+license = "MPL-2.0"
+publish = false
+
+[lib]
+name = "mp4parse_fallible"
+path = "lib.rs"
new file mode 100644
--- /dev/null
+++ b/media/libstagefright/binding/mp4parse_fallible/README
@@ -0,0 +1,2 @@
+This is from https://github.com/servo/servo/tree/master/components/fallible
+with modificaion for mp4 demuxer.
new file mode 100644
--- /dev/null
+++ b/media/libstagefright/binding/mp4parse_fallible/lib.rs
@@ -0,0 +1,92 @@
+/* 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/. */
+
+use std::mem;
+use std::vec::Vec;
+
+extern "C" {
+    fn realloc(ptr: *mut u8, bytes: usize) -> *mut u8;
+    fn malloc(bytes: usize) -> *mut u8;
+}
+
+pub trait FallibleVec<T> {
+    /// Append |val| to the end of |vec|.  Returns Ok(()) on success,
+    /// Err(()) if it fails, which can only be due to lack of memory.
+    fn try_push(&mut self, value: T) -> Result<(), ()>;
+
+    /// Expand the vector size. Return Ok(()) on success, Err(()) if it
+    /// fails.
+    fn try_reserve(&mut self, new_cap: usize) -> Result<(), ()>;
+}
+
+/////////////////////////////////////////////////////////////////
+// Vec
+
+impl<T> FallibleVec<T> for Vec<T> {
+    #[inline]
+    fn try_push(&mut self, val: T) -> Result<(), ()> {
+        if self.capacity() == self.len() {
+            let old_cap: usize = self.capacity();
+            let new_cap: usize
+                = if old_cap == 0 { 4 } else { old_cap.checked_mul(2).ok_or(()) ? };
+
+            try_extend_vec(self, new_cap)?;
+            debug_assert!(self.capacity() > self.len());
+        }
+        self.push(val);
+        Ok(())
+    }
+
+    #[inline]
+    fn try_reserve(&mut self, cap: usize) -> Result<(), ()> {
+        let new_cap = cap + self.capacity();
+        try_extend_vec(self, new_cap)?;
+        debug_assert!(self.capacity() == new_cap);
+        Ok(())
+    }
+}
+
+#[inline(never)]
+#[cold]
+fn try_extend_vec<T>(vec: &mut Vec<T>, new_cap: usize) -> Result<(), ()> {
+    let old_ptr = vec.as_mut_ptr();
+    let old_len = vec.len();
+
+    let old_cap: usize = vec.capacity();
+
+    if old_cap >= new_cap {
+        return Ok(());
+    }
+
+    let new_size_bytes
+        = new_cap.checked_mul(mem::size_of::<T>()).ok_or(()) ? ;
+
+    let new_ptr = unsafe {
+        if old_cap == 0 {
+            malloc(new_size_bytes)
+        } else {
+            realloc(old_ptr as *mut u8, new_size_bytes)
+        }
+    };
+
+    if new_ptr.is_null() {
+        return Err(());
+    }
+
+    let new_vec = unsafe {
+        Vec::from_raw_parts(new_ptr as *mut T, old_len, new_cap)
+    };
+
+    mem::forget(mem::replace(vec, new_vec));
+    Ok(())
+}
+
+#[test]
+fn oom_test() {
+    let mut vec: Vec<char> = Vec::new();
+    match vec.try_reserve(std::usize::MAX) {
+        Ok(_) => panic!("it should be OOM"),
+        _ => (),
+    }
+}
--- a/media/libstagefright/binding/update-rust.sh
+++ b/media/libstagefright/binding/update-rust.sh
@@ -1,13 +1,13 @@
 #!/bin/sh -e
 # Script to update mp4parse-rust sources to latest upstream
 
 # Default version.
-VER=81260ded506dce968716720e10544c510f37d222
+VER=295fd9fac60f1c0627750695a4218e32425b0f66
 
 # Accept version or commit from the command line.
 if test -n "$1"; then
   VER=$1
 fi
 
 echo "Fetching sources..."
 rm -rf _upstream
@@ -33,16 +33,19 @@ mkdir -p mp4parse/tests
 cp _upstream/mp4parse/mp4parse/tests/*.rs mp4parse/tests/
 cp _upstream/mp4parse/mp4parse/tests/*.mp4 mp4parse/tests/
 rm -rf mp4parse_capi
 mkdir -p mp4parse_capi/src
 cp _upstream/mp4parse/mp4parse_capi/Cargo.toml mp4parse_capi/
 cp _upstream/mp4parse/mp4parse_capi/build.rs mp4parse_capi/
 cp _upstream/mp4parse/mp4parse_capi/include/mp4parse.h include/
 cp _upstream/mp4parse/mp4parse_capi/src/*.rs mp4parse_capi/src/
+rm -rf mp4parse_fallible
+mkdir -p mp4parse_fallible
+cp _upstream/mp4parse/mp4parse_fallible/* mp4parse_fallible/
 
 echo "Applying patches..."
 patch -p4 < mp4parse-cargo.patch
 
 echo "Cleaning up..."
 rm -rf _upstream
 
 echo "Updating gecko Cargo.lock..."
--- a/mobile/android/app/src/photon/res/layout/toolbar_edit_layout.xml
+++ b/mobile/android/app/src/photon/res/layout/toolbar_edit_layout.xml
@@ -22,26 +22,24 @@
         android:background="@drawable/url_bar_title_bg"
         android:scaleType="center"
         android:src="@drawable/ic_search_icon"
         android:visibility="gone"
         tools:visibility="visible"/>
 
     <org.mozilla.gecko.toolbar.ToolbarEditText
         android:id="@+id/url_edit_text"
-        style="@style/UrlBar.Title"
+        style="@style/UrlBar.EditLayout.Title"
         android:layout_width="match_parent"
         android:layout_gravity="center_vertical"
         android:layout_weight="1.0"
         android:background="@drawable/url_bar_title_bg"
         android:contentDescription="@string/url_bar_default_text"
         android:imeOptions="actionGo|flagNoExtractUi|flagNoFullscreen"
         android:inputType="textUri"
-        android:paddingEnd="8dp"
-        android:paddingRight="8dp"
         android:selectAllOnFocus="true"/>
 
     <org.mozilla.gecko.toolbar.ToolbarRoundButton
         android:id="@+id/qrcode"
         style="@style/UrlBar.QRCode"
         android:background="@drawable/url_bar_action_button"
         android:src="@drawable/ic_qrcode"/>
 
--- a/mobile/android/app/src/photon/res/values-large-v17/styles.xml
+++ b/mobile/android/app/src/photon/res/values-large-v17/styles.xml
@@ -58,16 +58,21 @@
 
     <style name="UrlBar.EditLayout" parent="UrlBar.V17.EditLayout" />
 
     <style name="UrlBar.V17.EditLayout" parent="UrlBar.Base.EditLayout">
         <item name="android:layout_toStartOf">@id/menu_items</item>
         <item name="android:layout_toEndOf">@id/forward</item>
     </style>
 
+    <style name="UrlBar.EditLayout.Title" parent="UrlBar.V17.EditLayout.Title"/>
+    <style name="UrlBar.V17.EditLayout.Title" parent="UrlBar.Title">
+        <item name="android:paddingEnd">8dp</item>
+    </style>
+
     <style name="UrlBar.DisplayLayout" parent="UrlBar.V17.DisplayLayout" />
 
     <style name="UrlBar.V17.DisplayLayout" parent="UrlBar.Base.DisplayLayout">
         <item name="android:layout_toStartOf">@id/menu_items</item>
         <item name="android:layout_toEndOf">@id/forward</item>
     </style>
 
     <style name="UrlBar.EditCancel" parent="UrlBar.V17.EditCancel" />
--- a/mobile/android/app/src/photon/res/values-large/styles.xml
+++ b/mobile/android/app/src/photon/res/values-large/styles.xml
@@ -173,16 +173,21 @@
 
     <style name="UrlBar.Base.EditLayout" parent="UrlBar.Button" />
 
     <style name="UrlBar.V15.EditLayout" parent="UrlBar.Base.EditLayout">
         <item name="android:layout_toLeftOf">@id/menu_items</item>
         <item name="android:layout_toRightOf">@id/forward</item>
     </style>
 
+    <style name="UrlBar.EditLayout.Title" parent="UrlBar.V15.EditLayout.Title"/>
+    <style name="UrlBar.V15.EditLayout.Title" parent="UrlBar.Title">
+        <item name="android:paddingRight">8dp</item>
+    </style>
+
     <style name="UrlBar.DisplayLayout" parent="UrlBar.V15.DisplayLayout" />
 
     <style name="UrlBar.Base.DisplayLayout" parent="UrlBar.Button.Container" />
 
     <style name="UrlBar.V15.DisplayLayout" parent="UrlBar.Base.DisplayLayout">
         <item name="android:layout_toLeftOf">@id/menu_items</item>
         <item name="android:layout_toRightOf">@id/forward</item>
     </style>
--- a/mobile/android/app/src/photon/res/values-v17/styles.xml
+++ b/mobile/android/app/src/photon/res/values-v17/styles.xml
@@ -49,21 +49,27 @@
         <item name="android:layout_alignParentEnd">true</item>
     </style>
 
     <style name="UrlBar.EditLayout" parent="UrlBar.V17.EditLayout" />
 
     <style name="UrlBar.V17.EditLayout" parent="UrlBar.Base.EditLayout">
         <item name="android:layout_alignStart">@id/url_bar_entry</item>
         <item name="android:layout_toStartOf">@id/edit_cancel</item>
-        <item name="android:paddingStart">8dp</item>
+        <item name="android:paddingStart">5dp</item>
         <item name="android:paddingEnd">0dp</item>
         <item name="android:layout_marginEnd">-3dp</item>
     </style>
 
+    <style name="UrlBar.EditLayout.Title" parent="UrlBar.V17.EditLayout.Title"/>
+    <style name="UrlBar.V17.EditLayout.Title" parent="UrlBar.Title">
+        <item name="android:paddingStart">5dp</item>
+        <item name="android:paddingEnd">8dp</item>
+    </style>
+
     <style name="UrlBar.DisplayLayout" parent="UrlBar.V17.DisplayLayout" />
 
     <style name="UrlBar.V17.DisplayLayout" parent="UrlBar.Base.DisplayLayout">
         <item name="android:layout_alignStart">@id/url_bar_entry</item>
         <item name="android:layout_alignEnd">@id/url_bar_entry</item>
     </style>
 
     <style name="UrlBar.QRCode" parent="UrlBar.V17.QRCode"/>
--- a/mobile/android/app/src/photon/res/values/colors.xml
+++ b/mobile/android/app/src/photon/res/values/colors.xml
@@ -6,17 +6,17 @@
 
 <resources>
     <!-- color palette for Photon -->
     <color name="photon_text_main">#272727</color>
     <color name="photon_text_main_private">#FFFFFF</color>
     <color name="photon_text_secondary">#B2B2B2</color>
     <color name="photon_text_secondary_private">#737373</color>
     <color name="photon_text_placeholder">#737373</color>
-    <color name="photon_text_placeholder_private">#737373</color>
+    <color name="photon_text_placeholder_private">#B2B2B2</color>
     <color name="photon_text_selected_highlight">#4D0A84FF</color>
     <color name="photon_text_selected_highlight_private">#4DAC39FF</color>
 
     <color name="photon_search_suggestion_box">#E4E4E4</color>
 
     <!-- opacity: 20% -->
     <color name="photon_search_suggestion_box_pressed">#33E4E4E4</color>
 
@@ -97,16 +97,17 @@
     <color name="photon_tab_strip_item_lwt_light_pressed">@color/photon_tab_strip_item_lwt_pressed</color>
 
     <color name="tab_strip_title_lwt_checked">#272727</color>
     <color name="tab_strip_title_lwt">#272727</color>
 
     <!-- Status bar background color -->
     <color name="status_bar_bg_color">@color/photon_toolbar_bg</color>
     <color name="status_bar_bg_color_private">@color/photon_toolbar_bg_private</color>
+    <color name="status_bar_bg_color_tabs_tray">@color/photon_tabs_tray_bg</color>
     <color name="status_bar_bg_color_tablet">@color/photon_tabs_tray_bg</color>
 
     <!-- Toolbar menu item tint color -->
     <color name="menu_item_tint">@color/photon_icon</color>
     <color name="menu_item_tint_private">@color/photon_icon_private</color>
 
     <!-- Navigation button background color -->
     <color name="nav_button_bg_color">#F9F9FA</color>
--- a/mobile/android/app/src/photon/res/values/styles.xml
+++ b/mobile/android/app/src/photon/res/values/styles.xml
@@ -894,21 +894,27 @@
         <item name="android:layout_alignParentRight">true</item>
     </style>
 
     <style name="UrlBar.EditLayout" parent="UrlBar.V15.EditLayout"/>
     <style name="UrlBar.Base.EditLayout" parent="UrlBar.Button"/>
     <style name="UrlBar.V15.EditLayout" parent="UrlBar.Base.EditLayout">
         <item name="android:layout_alignLeft">@id/url_bar_entry</item>
         <item name="android:layout_toLeftOf">@id/edit_cancel</item>
-        <item name="android:paddingLeft">8dp</item>
+        <item name="android:paddingLeft">5dp</item>
         <item name="android:paddingRight">0dp</item>
         <item name="android:layout_marginRight">-3dp</item>
     </style>
 
+    <style name="UrlBar.EditLayout.Title" parent="UrlBar.V15.EditLayout.Title"/>
+    <style name="UrlBar.V15.EditLayout.Title" parent="UrlBar.Title">
+        <item name="android:paddingLeft">5dp</item>
+        <item name="android:paddingRight">8dp</item>
+    </style>
+
     <style name="UrlBar.DisplayLayout" parent="UrlBar.V15.DisplayLayout"/>
     <style name="UrlBar.Base.DisplayLayout" parent="UrlBar.Button"/>
 
     <style name="UrlBar.V15.DisplayLayout" parent="UrlBar.Base.DisplayLayout">
         <item name="android:layout_alignLeft">@id/url_bar_entry</item>
         <item name="android:layout_alignRight">@id/url_bar_entry</item>
     </style>
 
--- a/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
+++ b/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
@@ -2313,37 +2313,36 @@ public class BrowserApp extends GeckoApp
             // Hide potentially visible "find in page" bar (Bug 1177338)
             mFindInPageBar.hide();
 
             for (final BrowserAppDelegate delegate : delegates) {
                 delegate.onTabsTrayShown(this, mTabsPanel);
             }
         }
 
-        // Since tabs tray only has dark theme, always update the status bar with dark color.
-        WindowUtil.invalidateStatusBarColor(this, true);
+        // Set status bar color with tabs tray background color.
+        WindowUtil.setTabsTrayStatusBarColor(this);
     }
 
     @Override
     public void hideTabs() {
         mTabsPanel.hide();
         if (mTabStrip != null) {
             mTabStrip.tabStripIsCovered(false);
         }
         if (mDoorHangerPopup != null) {
             mDoorHangerPopup.enable();
         }
 
         for (final BrowserAppDelegate delegate : delegates) {
             delegate.onTabsTrayHidden(this, mTabsPanel);
         }
 
-        final Tab tab = Tabs.getInstance().getSelectedTab();
-        final boolean darkTheme = (tab != null && tab.isPrivate());
-        WindowUtil.invalidateStatusBarColor(this, darkTheme);
+        final boolean isPrivate = mBrowserToolbar.isPrivateMode();
+        WindowUtil.setStatusBarColor(this, isPrivate);
     }
 
     @Override
     public boolean autoHideTabs() {
         if (areTabsShown()) {
             hideTabs();
             return true;
         }
--- a/mobile/android/base/java/org/mozilla/gecko/toolbar/BrowserToolbar.java
+++ b/mobile/android/base/java/org/mozilla/gecko/toolbar/BrowserToolbar.java
@@ -353,19 +353,17 @@ public abstract class BrowserToolbar ext
             @Override
             public void onClick(View view) {
                 // Drop the soft keyboard.
                 urlEditLayout.clearFocus();
                 activity.openOptionsMenu();
             }
         });
 
-        final Tab tab = Tabs.getInstance().getSelectedTab();
-        final boolean darkTheme = (tab != null && tab.isPrivate());
-        WindowUtil.invalidateStatusBarColor(activity, darkTheme);
+        WindowUtil.setStatusBarColor(activity, isPrivateMode());
     }
 
     @Override
     public void onDetachedFromWindow() {
         super.onDetachedFromWindow();
 
         prefs.close();
     }
@@ -871,17 +869,17 @@ public abstract class BrowserToolbar ext
         urlEditLayout.setPrivateMode(isPrivate);
         urlDisplayLayout.setPrivateMode(isPrivate);
 
         ((ThemedImageButton) menuButton).setPrivateMode(isPrivate);
 
         shadowPaint.setColor(isPrivate ? shadowPrivateColor : shadowColor);
 
         if (modeChanged) {
-            WindowUtil.invalidateStatusBarColor(activity, isPrivate);
+            WindowUtil.setStatusBarColor(activity, isPrivate);
         }
     }
 
     public void show() {
         setVisibility(View.VISIBLE);
     }
 
     public void hide() {
--- a/mobile/android/base/java/org/mozilla/gecko/util/WindowUtil.java
+++ b/mobile/android/base/java/org/mozilla/gecko/util/WindowUtil.java
@@ -2,44 +2,62 @@
  * 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/. */
 
 package org.mozilla.gecko.util;
 
 import android.app.Activity;
 import android.os.Build;
+import android.support.annotation.ColorRes;
 import android.support.v4.content.ContextCompat;
 import android.view.View;
 import android.view.Window;
 
 import org.mozilla.gecko.R;
 
 public class WindowUtil {
 
-    public static void invalidateStatusBarColor(final Activity activity, boolean darkTheme) {
+    public static void setTabsTrayStatusBarColor(final Activity activity) {
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
+            return;
+        }
+        setStatusBarColor(activity, R.color.status_bar_bg_color_tabs_tray, true);
+    }
+
+    public static void setStatusBarColor(final Activity activity, final boolean isPrivate) {
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
             return;
         }
 
         final int colorResId;
+        final boolean isDarkTheme;
 
         if (HardwareUtils.isTablet()) {
             colorResId = R.color.status_bar_bg_color_tablet;
-            darkTheme = true;
+            isDarkTheme = true;
         } else {
-            colorResId = darkTheme ? R.color.status_bar_bg_color_private : R.color.status_bar_bg_color;
+            colorResId = isPrivate ? R.color.status_bar_bg_color_private : R.color.status_bar_bg_color;
+            isDarkTheme = isPrivate;
+        }
+        setStatusBarColor(activity, colorResId, isDarkTheme);
+    }
+
+    public static void setStatusBarColor(final Activity activity, @ColorRes final int colorResId,
+                                         final boolean isDarkTheme) {
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
+            return;
         }
 
         final Window window = activity.getWindow();
         final int backgroundColor = ContextCompat.getColor(activity, colorResId);
         window.setStatusBarColor(backgroundColor);
 
         final View view = window.getDecorView();
         int flags = view.getSystemUiVisibility();
-        if (darkTheme) {
+        if (isDarkTheme) {
             flags &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
         } else {
             flags |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
         }
         view.setSystemUiVisibility(flags);
     }
 }
--- a/servo/Cargo.lock
+++ b/servo/Cargo.lock
@@ -3592,17 +3592,17 @@ dependencies = [
  "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "uuid 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "webdriver 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "webrender"
 version = "0.50.0"
-source = "git+https://github.com/servo/webrender#08e5d6f3f391c0bb9bd17de69fdf89c068098d62"
+source = "git+https://github.com/servo/webrender#7d9444a24fb98bcc41afdca2a5bf145d514500f1"
 dependencies = [
  "app_units 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "bincode 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-graphics 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-text 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3620,17 +3620,17 @@ dependencies = [
  "thread_profiler 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
  "webrender_api 0.50.0 (git+https://github.com/servo/webrender)",
 ]
 
 [[package]]
 name = "webrender_api"
 version = "0.50.0"
-source = "git+https://github.com/servo/webrender#08e5d6f3f391c0bb9bd17de69fdf89c068098d62"
+source = "git+https://github.com/servo/webrender#7d9444a24fb98bcc41afdca2a5bf145d514500f1"
 dependencies = [
  "app_units 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "bincode 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-foundation 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-graphics 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "dwrote 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)",
--- a/testing/geckodriver/CHANGES.md
+++ b/testing/geckodriver/CHANGES.md
@@ -12,16 +12,18 @@ Unreleased
 - Added crashreporter environment variables to better control the browser
   in case of crashes
 
 - Added preference `dom.file.createInChild` set to true to allow file
   object creation in content processes
 
 ### Changed
 
+- Log all used application arguments and not only `-marionette`
+
 - Early abort connection attempts to Marionette if the Firefox process
   closed unexpectetly
 
 - Removed deprecated `socksProxyVersion` in favor of `socksVersion`
 
 - Removed `ftpProxyPort`, `httpProxyPort`, `sslProxyPort`, and
   `socksProxyPort` because _ports_ have to be set for `ftpProxy`,
   `httpProxy`, `sslProxy`, and `socksProxy` using ":<PORT>"
@@ -36,17 +38,17 @@ Unreleased
   `path`, containing an addon as a Base64 string
 
 - The [`WindowRectParameters`] have been updated to return signed 32-bit
   integers in accordance with the CSS and WebDriver specifications, and
   to be more liberal with the input types
 
 - [webdriver crate] upgraded to version 0.30.0
 
-- [mozrunner crate] upgraded to version 0.4.2
+- [mozrunner crate] upgraded to version 0.5.0
 
 
 0.18.0 (2017-07-10)
 -------------------
 
 ### Changed
 
 - [`RectResponse`] permits returning floats for `width` and `height`
--- a/testing/geckodriver/Cargo.toml
+++ b/testing/geckodriver/Cargo.toml
@@ -1,14 +1,15 @@
 [package]
 name = "geckodriver"
 version = "0.18.0"
 authors = [
   "James Graham <james@hoppipolla.co.uk>",
   "Andreas Tolfsen <ato@sny.no>",
+  "Henrik Skupin <mail@hskupin.info"
 ]
 description = "Proxy for using WebDriver clients to interact with Gecko-based browsers."
 keywords = ["webdriver", "w3c", "httpd", "mozilla", "firefox"]
 repository = "https://hg.mozilla.org/mozilla-central/file/tip/testing/geckodriver"
 readme = "README.md"
 license = "MPL-2.0"
 
 [dependencies]
--- a/testing/geckodriver/src/logging.rs
+++ b/testing/geckodriver/src/logging.rs
@@ -125,17 +125,18 @@ fn filtered_gecko_log(level: &LogLevel) 
 
 struct GeckoFormat;
 
 impl Format for GeckoFormat {
     fn format(&self, io: &mut io::Write, record: &Record, _: &OwnedKeyValueList) -> io::Result<()> {
         // TODO(ato): Quite sure this is the wrong way to filter records with slog,
         // but I do not comprehend how slog works.
         let module = record.module();
-        if module.starts_with("geckodriver") || module.starts_with("webdriver") {
+        if module.starts_with("geckodriver") || module.starts_with("webdriver") ||
+           module.starts_with("mozrunner") {
             let ts = format_ts(Local::now());
             let level = record.level().to_gecko();
             let _ = try!(write!(io, "{}\t{}\t{}\t{}\n", ts, module, level, record.msg()));
         }
         Ok(())
     }
 }
 
--- a/testing/geckodriver/src/marionette.rs
+++ b/testing/geckodriver/src/marionette.rs
@@ -461,17 +461,16 @@ impl MarionetteHandler {
         };
 
         try!(self.set_prefs(port, &mut runner.profile, custom_profile, options.prefs)
             .map_err(|e| {
                 WebDriverError::new(ErrorStatus::SessionNotCreated,
                                     format!("Failed to set preferences: {}", e))
             }));
 
-        info!("Starting browser {} with args {:?}", binary.display(), runner.args());
         try!(runner.start()
             .map_err(|e| {
                 WebDriverError::new(ErrorStatus::SessionNotCreated,
                                     format!("Failed to start browser {}: {}",
                                             binary.display(), e))
             }));
         self.browser = Some(runner);
 
--- a/testing/marionette/client/marionette_driver/marionette.py
+++ b/testing/marionette/client/marionette_driver/marionette.py
@@ -614,26 +614,39 @@ class Marionette(object):
 
         if self.bin:
             if not Marionette.is_port_available(self.port, host=self.host):
                 ex_msg = "{0}:{1} is unavailable.".format(self.host, self.port)
                 raise errors.MarionetteException(message=ex_msg)
 
             self.instance = GeckoInstance.create(
                 app, host=self.host, port=self.port, bin=self.bin, **instance_args)
-            self.instance.start()
-            self.raise_for_port(timeout=self.startup_timeout)
+            self.start_binary(self.startup_timeout)
 
         self.timeout = Timeouts(self)
 
     @property
     def profile_path(self):
         if self.instance and self.instance.profile:
             return self.instance.profile.profile
 
+    def start_binary(self, timeout):
+        try:
+            self.instance.start()
+            self.raise_for_port(timeout=timeout)
+        except socket.timeout:
+            # Something went wrong with starting up Marionette server. Given
+            # that the process will not quit itself, force a shutdown immediately.
+            self.cleanup()
+
+            msg = "Process killed after {}s because no connection to Marionette "\
+                  "server could be established. Check gecko.log for errors"
+            _, _, tb = sys.exc_info()
+            raise IOError, msg.format(timeout), tb
+
     def cleanup(self):
         if self.session is not None:
             try:
                 self.delete_session()
             except (errors.MarionetteException, IOError):
                 # These exceptions get thrown if the Marionette server
                 # hit an exception/died or the connection died. We can
                 # do no further server-side cleanup in this case.
@@ -692,17 +705,16 @@ class Marionette(object):
             finally:
                 if sock is not None:
                     sock.close()
 
             time.sleep(poll_interval)
 
         return False
 
-    @do_process_check
     def raise_for_port(self, timeout=None):
         """Raise socket.timeout if no connection can be established.
 
         :param timeout: Timeout in seconds for the server to be ready.
 
         """
         if not self.wait_for_port(timeout):
             raise socket.timeout("Timed out waiting for connection on {0}:{1}!".format(
@@ -1173,47 +1185,52 @@ class Marionette(object):
         '''
         Returns an absolute url for files served from Marionette's www directory.
 
         :param relative_url: The url of a static file, relative to Marionette's www directory.
         '''
         return "{0}{1}".format(self.baseurl, relative_url)
 
     @do_process_check
-    def start_session(self, capabilities=None, timeout=60):
+    def start_session(self, capabilities=None, timeout=None):
         """Create a new WebDriver session.
         This method must be called before performing any other action.
 
         :param capabilities: An optional dictionary of
             Marionette-recognised capabilities.  It does not
             accept a WebDriver conforming capabilities dictionary
             (including alwaysMatch, firstMatch, desiredCapabilities,
             or requriedCapabilities), and only recognises extension
             capabilities that are specific to Marionette.
-        :param timeout: Timeout in seconds for the server to be ready.
+        :param timeout: Optional timeout in seconds for the server to be ready.
         :returns: A dictionary of the capabilities offered.
         """
+        if timeout is None:
+            timeout = self.startup_timeout
+
         self.crashed = 0
 
         if self.instance:
             returncode = self.instance.runner.returncode
+            # We're managing a binary which has terminated. Start it again
+            # and implicitely wait for the Marionette server to be ready.
             if returncode is not None:
-                # We're managing a binary which has terminated, so start it again.
-                self.instance.start()
+                self.start_binary(timeout)
+
+        else:
+            # In the case when Marionette doesn't manage the binary wait until
+            # its server component has been started.
+            self.wait_for_port(timeout=timeout)
 
         self.client = transport.TcpTransport(
             self.host,
             self.port,
             self.socket_timeout)
+        self.protocol, _ = self.client.connect()
 
-        # Call wait_for_port() before attempting to connect in
-        # the event gecko hasn't started yet.
-        timeout = timeout or self.startup_timeout
-        self.wait_for_port(timeout=timeout)
-        self.protocol, _ = self.client.connect()
         body = capabilities
         if body is None:
             body = {}
 
         # Duplicate capabilities object so the body we end up
         # sending looks like this:
         #
         #     {acceptInsecureCerts: true, {capabilities: {acceptInsecureCerts: true}}}
--- a/testing/marionette/harness/marionette_harness/tests/unit/test_cli_arguments.py
+++ b/testing/marionette/harness/marionette_harness/tests/unit/test_cli_arguments.py
@@ -29,8 +29,23 @@ class TestCommandLineArguments(Marionett
         with self.marionette.using_context("chrome"):
             safe_mode = self.marionette.execute_script("""
               Cu.import("resource://gre/modules/Services.jsm");
 
               return Services.appinfo.inSafeMode;
             """)
 
             self.assertTrue(safe_mode, "Safe Mode has not been enabled")
+
+    def test_startup_timeout(self):
+        startup_timeout = self.marionette.startup_timeout
+
+        # Use a timeout which always cause an IOError
+        self.marionette.startup_timeout = 1
+        msg = "Process killed after {}s".format(self.marionette.startup_timeout)
+
+        try:
+            self.marionette.quit()
+            with self.assertRaisesRegexp(IOError, msg):
+                self.marionette.start_session()
+        finally:
+            self.marionette.startup_timeout = startup_timeout
+            self.marionette.start_session()
--- a/toolkit/library/gtest/rust/Cargo.lock
+++ b/toolkit/library/gtest/rust/Cargo.lock
@@ -797,16 +797,17 @@ dependencies = [
 ]
 
 [[package]]
 name = "mp4parse"
 version = "0.8.0"
 dependencies = [
  "bitreader 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mp4parse_fallible 0.0.1",
  "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "mp4parse-gtest"
 version = "0.1.0"
 
 [[package]]
@@ -814,16 +815,20 @@ name = "mp4parse_capi"
 version = "0.8.0"
 dependencies = [
  "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "mp4parse 0.8.0",
  "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
+name = "mp4parse_fallible"
+version = "0.0.1"
+
+[[package]]
 name = "net2"
 version = "0.2.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
--- a/toolkit/library/rust/Cargo.lock
+++ b/toolkit/library/rust/Cargo.lock
@@ -795,29 +795,34 @@ dependencies = [
 ]
 
 [[package]]
 name = "mp4parse"
 version = "0.8.0"
 dependencies = [
  "bitreader 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mp4parse_fallible 0.0.1",
  "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "mp4parse_capi"
 version = "0.8.0"
 dependencies = [
  "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "mp4parse 0.8.0",
  "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
+name = "mp4parse_fallible"
+version = "0.0.1"
+
+[[package]]
 name = "net2"
 version = "0.2.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",