Merge inbound to mozilla-central. a=merge
authorMargareta Eliza Balazs <ebalazs@mozilla.com>
Tue, 16 Jan 2018 23:43:19 +0200
changeset 453823 b2cb61e83ac50115a28f04aaa8a32d4db90aad23
parent 453822 a97be0f1da510a103f3f536e4a380a44042bde74 (current diff)
parent 453763 dccbf55508540c0459f36c286e3aff6975af722e (diff)
child 453824 b5495d7f42a69017bf88aa697a451faafa4bc39d
push id1648
push usermtabara@mozilla.com
push dateThu, 01 Mar 2018 12:45:47 +0000
treeherdermozilla-release@cbb9688c2eeb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone59.0a1
first release with
nightly linux32
b2cb61e83ac5 / 59.0a1 / 20180116220110 / files
nightly linux64
b2cb61e83ac5 / 59.0a1 / 20180116220110 / files
nightly mac
b2cb61e83ac5 / 59.0a1 / 20180116220110 / files
nightly win32
b2cb61e83ac5 / 59.0a1 / 20180116220110 / files
nightly win64
b2cb61e83ac5 / 59.0a1 / 20180116220110 / 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 inbound to mozilla-central. a=merge
--- a/dom/base/FragmentOrElement.cpp
+++ b/dom/base/FragmentOrElement.cpp
@@ -1175,16 +1175,18 @@ FragmentOrElement::RemoveChildAt_Depreca
   if (oldKid) {
     doRemoveChildAt(aIndex, aNotify, oldKid, mAttrsAndChildren);
   }
 }
 
 void
 FragmentOrElement::RemoveChildNode(nsIContent* aKid, bool aNotify)
 {
+  // Let's keep the node alive.
+  nsCOMPtr<nsIContent> kungFuDeathGrip = aKid;
   doRemoveChildAt(IndexOf(aKid), aNotify, aKid, mAttrsAndChildren);
 }
 
 void
 FragmentOrElement::GetTextContentInternal(nsAString& aTextContent,
                                           OOMReporter& aError)
 {
   if (!nsContentUtils::GetNodeTextContent(this, true, aTextContent, fallible)) {
@@ -2302,20 +2304,19 @@ FragmentOrElement::SetInnerHTMLInternal(
   mozAutoSubtreeModified subtree(doc, nullptr);
 
   target->FireNodeRemovedForChildren();
 
   // Needed when innerHTML is used in combination with contenteditable
   mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, true);
 
   // Remove childnodes.
-  uint32_t childCount = target->GetChildCount();
   nsAutoMutationBatch mb(target, true, false);
-  for (uint32_t i = 0; i < childCount; ++i) {
-    target->RemoveChildAt_Deprecated(0, true);
+  while (target->HasChildren()) {
+    target->RemoveChildNode(target->GetFirstChild(), true);
   }
   mb.RemovalDone();
 
   nsAutoScriptLoaderDisabler sld(doc);
 
   nsAtom* contextLocalName = NodeInfo()->NameAtom();
   int32_t contextNameSpaceID = GetNameSpaceID();
 
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -7449,20 +7449,20 @@ nsDOMAttributeMap::BlastSubtreeToPieces(
                              false);
 
         // XXX Should we abort here?
         NS_ASSERTION(NS_SUCCEEDED(rv), "Uh-oh, UnsetAttr shouldn't fail!");
       }
     }
   }
 
-  uint32_t count = aNode->GetChildCount();
-  for (uint32_t i = 0; i < count; ++i) {
-    BlastSubtreeToPieces(aNode->GetFirstChild());
-    aNode->RemoveChildAt_Deprecated(0, false);
+  while (aNode->HasChildren()) {
+    nsIContent* node = aNode->GetFirstChild();
+    BlastSubtreeToPieces(node);
+    aNode->RemoveChildNode(node, false);
   }
 }
 
 enum class StyleDataType
 {
   InlineStyle,
   SMILOverride,
   RestyleBits,
@@ -7650,19 +7650,17 @@ nsIDocument::AdoptNode(nsINode& aAdopted
             return nullptr;
           }
         }
       } while ((doc = doc->GetParentDocument()));
 
       // Remove from parent.
       nsCOMPtr<nsINode> parent = adoptedNode->GetParentNode();
       if (parent) {
-        int32_t idx = parent->IndexOf(adoptedNode);
-        MOZ_ASSERT(idx >= 0);
-        parent->RemoveChildAt_Deprecated(idx, true);
+        parent->RemoveChildNode(adoptedNode->AsContent(), true);
       } else {
         MOZ_ASSERT(!adoptedNode->IsInUncomposedDoc());
 
         // If we're adopting a node that's not in a document, it might still
         // have a binding applied. Remove the binding from the element now
         // that it's getting adopted into a new document.
         // TODO Fully tear down the binding.
         if (adoptedNode->IsElement()) {
--- a/dom/base/nsGenericDOMDataNode.cpp
+++ b/dom/base/nsGenericDOMDataNode.cpp
@@ -771,69 +771,84 @@ nsGenericDOMDataNode::SplitText(uint32_t
   nsCOMPtr<nsIContent> newChild;
   nsresult rv = SplitData(aOffset, getter_AddRefs(newChild));
   if (NS_SUCCEEDED(rv)) {
     rv = CallQueryInterface(newChild, aReturn);
   }
   return rv;
 }
 
-/* static */ int32_t
-nsGenericDOMDataNode::FirstLogicallyAdjacentTextNode(nsIContent* aParent,
-                                                     int32_t aIndex)
+static nsIContent*
+FirstLogicallyAdjacentTextNode(nsIContent* aNode)
 {
-  while (aIndex-- > 0) {
-    nsIContent* sibling = aParent->GetChildAt_Deprecated(aIndex);
-    if (!sibling->IsNodeOfType(nsINode::eTEXT))
-      return aIndex + 1;
+  nsCOMPtr<nsIContent> parent = aNode->GetParent();
+
+  while (aNode) {
+    nsIContent* sibling = aNode->GetPreviousSibling();
+    if (!sibling || !sibling->IsNodeOfType(nsINode::eTEXT)) {
+      return aNode;
+    }
+    aNode = sibling;
   }
-  return 0;
+
+  return parent->GetFirstChild();
 }
 
-/* static */ int32_t
-nsGenericDOMDataNode::LastLogicallyAdjacentTextNode(nsIContent* aParent,
-                                                    int32_t aIndex,
-                                                    uint32_t aCount)
+static nsIContent*
+LastLogicallyAdjacentTextNode(nsIContent* aNode)
 {
-  while (++aIndex < int32_t(aCount)) {
-    nsIContent* sibling = aParent->GetChildAt_Deprecated(aIndex);
-    if (!sibling->IsNodeOfType(nsINode::eTEXT))
-      return aIndex - 1;
+  nsCOMPtr<nsIContent> parent = aNode->GetParent();
+
+  while (aNode) {
+    nsIContent* sibling = aNode->GetNextSibling();
+    if (!sibling) break;
+
+    if (!sibling->IsNodeOfType(nsINode::eTEXT)) {
+      return aNode;
+    }
+
+    aNode = sibling;
   }
-  return aCount - 1;
+
+  return parent->GetLastChild();
 }
 
 nsresult
 nsGenericDOMDataNode::GetWholeText(nsAString& aWholeText)
 {
   nsIContent* parent = GetParent();
 
   // Handle parent-less nodes
   if (!parent)
     return GetData(aWholeText);
 
   int32_t index = parent->IndexOf(this);
   NS_WARNING_ASSERTION(index >= 0,
                        "Trying to use .wholeText with an anonymous"
                        "text node child of a binding parent?");
   NS_ENSURE_TRUE(index >= 0, NS_ERROR_DOM_NOT_SUPPORTED_ERR);
-  int32_t first =
-    FirstLogicallyAdjacentTextNode(parent, index);
-  int32_t last =
-    LastLogicallyAdjacentTextNode(parent, index, parent->GetChildCount());
+  nsCOMPtr<nsIContent> first = FirstLogicallyAdjacentTextNode(this);
+  nsCOMPtr<nsIContent> last = LastLogicallyAdjacentTextNode(this);
 
   aWholeText.Truncate();
 
   nsCOMPtr<nsIDOMText> node;
   nsAutoString tmp;
-  do {
-    node = do_QueryInterface(parent->GetChildAt_Deprecated(first));
+
+  while (true) {
+    node = do_QueryInterface(first);
     node->GetData(tmp);
     aWholeText.Append(tmp);
-  } while (first++ < last);
+
+    if (first == last) {
+      break;
+    }
+
+    first = first->GetNextSibling();
+  }
 
   return NS_OK;
 }
 
 //----------------------------------------------------------------------
 
 // Implementation of the nsIContent interface text functions
 
--- a/dom/base/nsGenericDOMDataNode.h
+++ b/dom/base/nsGenericDOMDataNode.h
@@ -229,23 +229,16 @@ protected:
 
     return parent && parent->IsElement() ? parent->AsElement() : nullptr;
   }
 
   nsresult SplitText(uint32_t aOffset, nsIDOMText** aReturn);
 
   nsresult GetWholeText(nsAString& aWholeText);
 
-  static int32_t FirstLogicallyAdjacentTextNode(nsIContent* aParent,
-                                                int32_t aIndex);
-
-  static int32_t LastLogicallyAdjacentTextNode(nsIContent* aParent,
-                                               int32_t aIndex,
-                                               uint32_t aCount);
-
   nsresult SetTextInternal(uint32_t aOffset, uint32_t aCount,
                            const char16_t* aBuffer, uint32_t aLength,
                            bool aNotify,
                            CharacterDataChangeInfo::Details* aDetails = nullptr);
 
   /**
    * Method to clone this node. This needs to be overriden by all derived
    * classes. If aCloneText is true the text content will be cloned too.
--- a/dom/html/nsGenericHTMLElement.cpp
+++ b/dom/html/nsGenericHTMLElement.cpp
@@ -3097,22 +3097,22 @@ nsGenericHTMLElement::SetInnerText(const
   FireNodeRemovedForChildren();
 
   // Might as well stick a batch around this since we're performing several
   // mutations.
   mozAutoDocUpdate updateBatch(GetComposedDoc(),
     UPDATE_CONTENT_MODEL, true);
   nsAutoMutationBatch mb;
 
-  uint32_t childCount = GetChildCount();
-
   mb.Init(this, true, false);
-  for (uint32_t i = 0; i < childCount; ++i) {
-    RemoveChildAt_Deprecated(0, true);
+
+  while (HasChildren()) {
+    RemoveChildNode(nsINode::GetFirstChild(), true);
   }
+
   mb.RemovalDone();
 
   nsString str;
   const char16_t* s = aValue.BeginReading();
   const char16_t* end = aValue.EndReading();
   while (true) {
     if (s != end && *s == '\r' && s + 1 != end && s[1] == '\n') {
       // a \r\n pair should only generate one <br>, so just skip the \r
--- a/dom/security/nsCSPUtils.cpp
+++ b/dom/security/nsCSPUtils.cpp
@@ -255,16 +255,19 @@ CSP_ContentTypeToDirective(nsContentPoli
 
     // csp shold not block top level loads, e.g. in case
     // of a redirect.
     case nsIContentPolicy::TYPE_DOCUMENT:
     // CSP can not block csp reports
     case nsIContentPolicy::TYPE_CSP_REPORT:
       return nsIContentSecurityPolicy::NO_DIRECTIVE;
 
+    case nsIContentPolicy::TYPE_SAVEAS_DOWNLOAD:
+      return nsIContentSecurityPolicy::NO_DIRECTIVE;
+
     // Fall through to error for all other directives
     default:
       MOZ_ASSERT(false, "Can not map nsContentPolicyType to CSPDirective");
   }
   return nsIContentSecurityPolicy::DEFAULT_SRC_DIRECTIVE;
 }
 
 nsCSPHostSrc*
--- a/dom/xbl/nsXBLPrototypeBinding.cpp
+++ b/dom/xbl/nsXBLPrototypeBinding.cpp
@@ -379,19 +379,19 @@ nsXBLPrototypeBinding::AttributeChanged(
       // set or unset on us.  We may also be a tag that is having
       // xbl:text set on us.
 
       if ((dstAttr == nsGkAtoms::text && dstNs == kNameSpaceID_XBL) ||
           (realElement->NodeInfo()->Equals(nsGkAtoms::html,
                                            kNameSpaceID_XUL) &&
            dstAttr == nsGkAtoms::value)) {
         // Flush out all our kids.
-        uint32_t childCount = realElement->GetChildCount();
-        for (uint32_t i = 0; i < childCount; i++)
-          realElement->RemoveChildAt_Deprecated(0, aNotify);
+        while (realElement->HasChildren()) {
+          realElement->RemoveChildNode(realElement->GetFirstChild(), aNotify);
+        }
 
         if (!aRemoveFlag) {
           // Construct a new text node and insert it.
           nsAutoString value;
           aChangedElement->GetAttr(aNameSpaceID, aAttribute, value);
           if (!value.IsEmpty()) {
             RefPtr<nsTextNode> textContent =
               new nsTextNode(realElement->NodeInfo()->NodeInfoManager());
--- a/dom/xul/nsXULSortService.cpp
+++ b/dom/xul/nsXULSortService.cpp
@@ -175,18 +175,17 @@ XULSortServiceImpl::SortContainer(nsICon
     nsIContent* child = items[i].content;
     nsIContent* parent = child->GetParent();
 
     if (parent) {
       // remember the parent so that it can be reinserted back
       // into the same parent. This is necessary as multiple rules
       // may generate results which get placed in different locations.
       items[i].parent = parent;
-      int32_t index = parent->IndexOf(child);
-      parent->RemoveChildAt_Deprecated(index, true);
+      parent->RemoveChildNode(child, true);
     }
   }
 
   // now add the items back in sorted order
   for (i = 0; i < numResults; i++)
   {
     nsIContent* child = items[i].content;
     nsIContent* parent = items[i].parent;
--- a/gfx/layers/wr/WebRenderCommandBuilder.cpp
+++ b/gfx/layers/wr/WebRenderCommandBuilder.cpp
@@ -522,19 +522,25 @@ WebRenderCommandBuilder::GenerateFallbac
 
   // XXX not sure if paintSize should be in layer or layoutdevice pixels, it
   // has some sort of scaling applied.
   LayerIntSize paintSize = RoundedToInt(LayerSize(bounds.Width() * scale.width, bounds.Height() * scale.height));
   if (paintSize.width == 0 || paintSize.height == 0) {
     return nullptr;
   }
 
+  // Some display item may draw exceed the paintSize, we need prepare a larger
+  // draw target to contain the result.
+  auto scaledBounds = bounds * LayoutDeviceToLayerScale(1);
+  scaledBounds.Scale(scale.width, scale.height);
+  LayerIntSize dtSize = RoundedToInt(scaledBounds).Size();
+
   bool needPaint = true;
   LayoutDeviceIntPoint offset = RoundedToInt(bounds.TopLeft());
-  aImageRect = LayoutDeviceRect(offset, LayoutDeviceSize(RoundedToInt(bounds.Size())));
+  aImageRect = LayoutDeviceRect(offset, LayoutDeviceSize(RoundedToInt(bounds).Size()));
   LayerRect paintRect = LayerRect(LayerPoint(0, 0), LayerSize(paintSize));
   nsDisplayItemGeometry* geometry = fallbackData->GetGeometry();
 
   // nsDisplayFilter is rendered via BasicLayerManager which means the invalidate
   // region is unknown until we traverse the displaylist contained by it.
   if (geometry && !fallbackData->IsInvalid() &&
       aItem->GetType() != DisplayItemType::TYPE_FILTER &&
       aItem->GetType() != DisplayItemType::TYPE_SVG_WRAPPER &&
@@ -576,29 +582,29 @@ WebRenderCommandBuilder::GenerateFallbac
           aStream.write((const char*)&count, sizeof(count));
           for (auto unscaled : aUnscaledFonts) {
             wr::FontKey key = mManager->WrBridge()->GetFontKeyForUnscaledFont(unscaled);
             aStream.write((const char*)&key, sizeof(key));
           }
         });
       RefPtr<gfx::DrawTarget> dummyDt =
         gfx::Factory::CreateDrawTarget(gfx::BackendType::SKIA, gfx::IntSize(1, 1), format);
-      RefPtr<gfx::DrawTarget> dt = gfx::Factory::CreateRecordingDrawTarget(recorder, dummyDt, paintSize.ToUnknownSize());
+      RefPtr<gfx::DrawTarget> dt = gfx::Factory::CreateRecordingDrawTarget(recorder, dummyDt, dtSize.ToUnknownSize());
       if (!fallbackData->mBasicLayerManager) {
         fallbackData->mBasicLayerManager = new BasicLayerManager(BasicLayerManager::BLM_INACTIVE);
       }
       bool isInvalidated = PaintItemByDrawTarget(aItem, dt, paintRect, offset, aDisplayListBuilder,
                                                  fallbackData->mBasicLayerManager, scale, highlight);
       recorder->FlushItem(IntRect());
       recorder->Finish();
 
       if (isInvalidated) {
         Range<uint8_t> bytes((uint8_t *)recorder->mOutputStream.mData, recorder->mOutputStream.mLength);
         wr::ImageKey key = mManager->WrBridge()->GetNextImageKey();
-        wr::ImageDescriptor descriptor(paintSize.ToUnknownSize(), 0, dt->GetFormat(), isOpaque);
+        wr::ImageDescriptor descriptor(dtSize.ToUnknownSize(), 0, dt->GetFormat(), isOpaque);
         if (!aResources.AddBlobImage(key, descriptor, bytes)) {
           return nullptr;
         }
         fallbackData->SetKey(key);
       } else {
         // If there is no invalidation region and we don't have a image key,
         // it means we don't need to push image for the item.
         if (!fallbackData->GetKey().isSome()) {
@@ -607,29 +613,29 @@ WebRenderCommandBuilder::GenerateFallbac
       }
     } else {
       fallbackData->CreateImageClientIfNeeded();
       RefPtr<ImageClient> imageClient = fallbackData->GetImageClient();
       RefPtr<ImageContainer> imageContainer = LayerManager::CreateImageContainer();
       bool isInvalidated = false;
 
       {
-        UpdateImageHelper helper(imageContainer, imageClient, paintSize.ToUnknownSize(), format);
+        UpdateImageHelper helper(imageContainer, imageClient, dtSize.ToUnknownSize(), format);
         {
           RefPtr<gfx::DrawTarget> dt = helper.GetDrawTarget();
           if (!dt) {
             return nullptr;
           }
           if (!fallbackData->mBasicLayerManager) {
             fallbackData->mBasicLayerManager = new BasicLayerManager(mManager->GetWidget());
           }
           isInvalidated = PaintItemByDrawTarget(aItem, dt, paintRect, offset,
-                                               aDisplayListBuilder,
-                                               fallbackData->mBasicLayerManager, scale,
-                                               highlight);
+                                                aDisplayListBuilder,
+                                                fallbackData->mBasicLayerManager, scale,
+                                                highlight);
         }
 
         if (isInvalidated) {
           // Update image if there it's invalidated.
           if (!helper.UpdateImage()) {
             return nullptr;
           }
         } else {
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -3750,25 +3750,22 @@ EvalInThread(JSContext* cx, unsigned arg
         return false;
     }
 
     if (cooperative) {
         cooperationState->numThreads++;
         CooperativeBeginWait(cx);
     }
 
-    auto thread = js_new<Thread>(Thread::Options().setStackSize(gMaxStackSize + 128 * 1024));
-    if (!thread || !thread->init(WorkerMain, input)) {
-        ReportOutOfMemory(cx);
-        if (cooperative) {
-            cooperationState->numThreads--;
-            CooperativeYield();
-            CooperativeEndWait(cx);
-        }
-        return false;
+    Thread* thread;
+    {
+        AutoEnterOOMUnsafeRegion oomUnsafe;
+        thread = js_new<Thread>(Thread::Options().setStackSize(gMaxStackSize + 128 * 1024));
+        if (!thread || !thread->init(WorkerMain, input))
+            oomUnsafe.crash("EvalInThread");
     }
 
     if (cooperative) {
         CooperativeEndWait(cx);
     } else {
         AutoLockWorkerThreads alwt;
         if (!workerThreads.append(thread)) {
             ReportOutOfMemory(cx);
--- a/layout/forms/nsTextControlFrame.cpp
+++ b/layout/forms/nsTextControlFrame.cpp
@@ -1304,17 +1304,20 @@ nsTextControlFrame::UpdateValueDisplay(b
   // EnsureEditorInitialized takes care of this.
   if ((mPlaceholderDiv || mPreviewDiv) && !aBeforeEditorInit) {
     AutoWeakFrame weakFrame(this);
     txtCtrl->UpdateOverlayTextVisibility(aNotify);
     NS_ENSURE_STATE(weakFrame.IsAlive());
   }
 
   if (aBeforeEditorInit && value.IsEmpty()) {
-    mRootNode->RemoveChildAt_Deprecated(0, true);
+    nsIContent* node = mRootNode->GetFirstChild();
+    if (node) {
+      mRootNode->RemoveChildNode(node, true);
+    }
     return NS_OK;
   }
 
   if (!value.IsEmpty() && IsPasswordTextControl()) {
     TextEditRules::FillBufWithPWChars(&value, value.Length());
   }
   return textContent->SetText(value, aNotify);
 }
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1424177-ref.html
@@ -0,0 +1,14 @@
+<html>
+  <head>
+    <style>
+      #sel {
+        left: 10px;
+        width: 101px;
+        position: absolute;
+      }
+    </style>
+  </head>
+  <body>
+    <select id="sel"></select>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1424177.html
@@ -0,0 +1,14 @@
+<html>
+  <head>
+    <style>
+      #sel {
+        left: 10.4px;
+        width: 100.4px;
+        position: absolute;
+      }
+    </style>
+  </head>
+  <body>
+    <select id="sel"></select>
+  </body>
+</html>
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -2046,10 +2046,11 @@ needs-focus != 1377447-1.html 1377447-2.
 == 1405878-1.xml 1405878-1-ref.xml
 == 1404057.html 1404057-ref.html
 != 1404057.html 1404057-noref.html
 == 1406183-1.html 1406183-1-ref.html
 == 1410028.html 1410028-ref.html
 test-pref(font.size.systemFontScale,200) == 1412743.html 1412743-ref.html
 == 1419820-1.html 1419820-1-ref.html
 == 1420946-1.html 1420946-1-ref.html
+== 1424177.html 1424177-ref.html
 == 1424680.html 1424680-ref.html
 == 1424798-1.html 1424798-ref.html
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -2720,18 +2720,18 @@ var NativeWindow = {
     },
 
     /* Returns a label to be shown in a tabbed ui if there are multiple "contexts". For instance, if this
      * is an image inside an <a> tag, we may have a "link" context and an "image" one.
      */
     _getContextType: function(element) {
       // For anchor nodes, we try to use the scheme to pick a string
       if (ChromeUtils.getClassName(element) === "HTMLAnchorElement") {
-        let uri = this.makeURI(this._getLinkURL(element));
         try {
+          let uri = this.makeURI(this._getLinkURL(element));
           return Strings.browser.GetStringFromName("browser.menu.context." + uri.scheme);
         } catch(ex) { }
       }
 
       // Otherwise we try the nodeName
       try {
         return Strings.browser.GetStringFromName("browser.menu.context." + element.nodeName.toLowerCase());
       } catch(ex) { }
--- a/netwerk/cache2/CacheObserver.cpp
+++ b/netwerk/cache2/CacheObserver.cpp
@@ -18,20 +18,17 @@
 #include <time.h>
 #include <math.h>
 
 namespace mozilla {
 namespace net {
 
 CacheObserver* CacheObserver::sSelf = nullptr;
 
-static int32_t const kDefaultHalfLifeExperiment = -1; // Disabled
-int32_t CacheObserver::sHalfLifeExperiment = kDefaultHalfLifeExperiment;
-
-static float const kDefaultHalfLifeHours = 1.0F; // 1 hour
+static float const kDefaultHalfLifeHours = 24.0F; // 24 hours
 float CacheObserver::sHalfLifeHours = kDefaultHalfLifeHours;
 
 static bool const kDefaultUseDiskCache = true;
 bool CacheObserver::sUseDiskCache = kDefaultUseDiskCache;
 
 static bool const kDefaultUseMemoryCache = true;
 bool CacheObserver::sUseMemoryCache = kDefaultUseMemoryCache;
 
@@ -178,62 +175,18 @@ CacheObserver::AttachToPreferences()
   // http://mxr.mozilla.org/mozilla-central/source/netwerk/cache/nsCacheEntryDescriptor.cpp#367
   mozilla::Preferences::AddUintVarCache(
     &sCompressionLevel, "browser.cache.compression_level", kDefaultCompressionLevel);
 
   mozilla::Preferences::GetComplex(
     "browser.cache.disk.parent_directory", NS_GET_IID(nsIFile),
     getter_AddRefs(mCacheParentDirectoryOverride));
 
-  // First check the default value.  If it is at -1, the experient
-  // is turned off.  If it is at 0, then use the user pref value
-  // instead.
-  sHalfLifeExperiment = mozilla::Preferences::GetInt(
-    "browser.cache.frecency_experiment", kDefaultHalfLifeExperiment,
-    PrefValueKind::Default);
-
-  if (sHalfLifeExperiment == 0) {
-    // Default preferences indicate we want to run the experiment,
-    // hence read the user value.
-    sHalfLifeExperiment = mozilla::Preferences::GetInt(
-      "browser.cache.frecency_experiment", sHalfLifeExperiment);
-  }
-
-  if (sHalfLifeExperiment == 0) {
-    // The experiment has not yet been initialized but is engaged, do
-    // the initialization now.
-    srand(time(NULL));
-    sHalfLifeExperiment = (rand() % 4) + 1;
-    // Store the experiemnt value, since we need it not to change between
-    // browser sessions.
-    mozilla::Preferences::SetInt(
-      "browser.cache.frecency_experiment", sHalfLifeExperiment);
-  }
-
-  switch (sHalfLifeExperiment) {
-  case 1: // The experiment is engaged
-    sHalfLifeHours = 0.083F; // ~5 mintues
-    break;
-  case 2:
-    sHalfLifeHours = 0.25F; // 15 mintues
-    break;
-  case 3:
-    sHalfLifeHours = 1.0F;
-    break;
-  case 4:
-    sHalfLifeHours = 6.0F;
-    break;
-
-  case -1:
-  default: // The experiment is off or broken
-    sHalfLifeExperiment = -1;
-    sHalfLifeHours = std::max(0.01F, std::min(1440.0F, mozilla::Preferences::GetFloat(
-      "browser.cache.frecency_half_life_hours", kDefaultHalfLifeHours)));
-    break;
-  }
+  sHalfLifeHours = std::max(0.01F, std::min(1440.0F, mozilla::Preferences::GetFloat(
+    "browser.cache.frecency_half_life_hours", kDefaultHalfLifeHours)));
 
   mozilla::Preferences::AddBoolVarCache(
     &sSanitizeOnShutdown, "privacy.sanitize.sanitizeOnShutdown", kDefaultSanitizeOnShutdown);
   mozilla::Preferences::AddBoolVarCache(
     &sClearCacheOnShutdown, "privacy.clearOnShutdown.cache", kDefaultClearCacheOnShutdown);
 
   mozilla::Preferences::AddAtomicUintVarCache(
     &sMaxShutdownIOLag, "browser.cache.max_shutdown_io_lag", kDefaultMaxShutdownIOLag);
--- a/netwerk/cache2/CacheObserver.h
+++ b/netwerk/cache2/CacheObserver.h
@@ -51,18 +51,16 @@ class CacheObserver : public nsIObserver
     { return sMaxDiskEntrySize << 10; }
   static uint32_t MaxDiskChunksMemoryUsage(bool aPriority) // result in bytes.
     { return aPriority ? sMaxDiskPriorityChunksMemoryUsage << 10
                        : sMaxDiskChunksMemoryUsage << 10; }
   static uint32_t CompressionLevel()
     { return sCompressionLevel; }
   static uint32_t HalfLifeSeconds()
     { return sHalfLifeHours * 60.0F * 60.0F; }
-  static int32_t HalfLifeExperiment()
-    { return sHalfLifeExperiment; }
   static bool ClearCacheOnShutdown()
     { return sSanitizeOnShutdown && sClearCacheOnShutdown; }
   static bool CacheFSReported()
     { return sCacheFSReported; }
   static void SetCacheFSReported();
   static bool HashStatsReported()
     { return sHashStatsReported; }
   static void SetHashStatsReported();
@@ -96,17 +94,16 @@ private:
   static bool sSmartCacheSizeEnabled;
   static uint32_t sPreloadChunkCount;
   static int32_t sMaxMemoryEntrySize;
   static int32_t sMaxDiskEntrySize;
   static uint32_t sMaxDiskChunksMemoryUsage;
   static uint32_t sMaxDiskPriorityChunksMemoryUsage;
   static uint32_t sCompressionLevel;
   static float sHalfLifeHours;
-  static int32_t sHalfLifeExperiment;
   static bool sSanitizeOnShutdown;
   static bool sClearCacheOnShutdown;
   static bool sCacheFSReported;
   static bool sHashStatsReported;
   static Atomic<uint32_t, Relaxed> sMaxShutdownIOLag;
   static Atomic<PRIntervalTime> sShutdownDemandedTime;
 
   // Non static properties, accessible via sSelf
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -151,22 +151,16 @@ enum CacheDisposition {
     kCacheMissedViaReval = 3,
     kCacheMissed = 4
 };
 
 void
 AccumulateCacheHitTelemetry(CacheDisposition hitOrMiss)
 {
     Telemetry::Accumulate(Telemetry::HTTP_CACHE_DISPOSITION_2_V2, hitOrMiss);
-
-    int32_t experiment = CacheObserver::HalfLifeExperiment();
-    if (experiment > 0 && hitOrMiss == kCacheMissed) {
-        Telemetry::Accumulate(Telemetry::HTTP_CACHE_MISS_HALFLIFE_EXPERIMENT_2,
-                              experiment - 1);
-    }
 }
 
 // Computes and returns a SHA1 hash of the input buffer. The input buffer
 // must be a null-terminated string.
 nsresult
 Hash(const char *buf, nsACString &hash)
 {
     nsresult rv;
--- a/parser/html/nsHtml5TreeOperation.cpp
+++ b/parser/html/nsHtml5TreeOperation.cpp
@@ -236,38 +236,35 @@ IsElementOrTemplateContent(nsINode* aNod
 
 void
 nsHtml5TreeOperation::Detach(nsIContent* aNode, nsHtml5DocumentBuilder* aBuilder)
 {
   MOZ_ASSERT(aBuilder);
   MOZ_ASSERT(aBuilder->IsInDocUpdate());
   nsCOMPtr<nsINode> parent = aNode->GetParentNode();
   if (parent) {
-    nsHtml5OtherDocUpdate update(parent->OwnerDoc(),
-        aBuilder->GetDocument());
-    int32_t pos = parent->IndexOf(aNode);
-    NS_ASSERTION((pos >= 0), "Element not found as child of its parent");
-    parent->RemoveChildAt_Deprecated(pos, true);
+    nsHtml5OtherDocUpdate update(parent->OwnerDoc(), aBuilder->GetDocument());
+    parent->RemoveChildNode(aNode, true);
   }
 }
 
 nsresult
 nsHtml5TreeOperation::AppendChildrenToNewParent(nsIContent* aNode,
                                                 nsIContent* aParent,
                                                 nsHtml5DocumentBuilder* aBuilder)
 {
   MOZ_ASSERT(aBuilder);
   MOZ_ASSERT(aBuilder->IsInDocUpdate());
   nsHtml5OtherDocUpdate update(aParent->OwnerDoc(),
                                aBuilder->GetDocument());
 
   bool didAppend = false;
   while (aNode->HasChildren()) {
     nsCOMPtr<nsIContent> child = aNode->GetFirstChild();
-    aNode->RemoveChildAt_Deprecated(0, true);
+    aNode->RemoveChildNode(child, true);
     nsresult rv = aParent->AppendChildTo(child, false);
     NS_ENSURE_SUCCESS(rv, rv);
     didAppend = true;
   }
   if (didAppend) {
     nsNodeUtils::ContentAppended(aParent, aParent->GetLastChild());
   }
   return NS_OK;
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -2899,23 +2899,16 @@
   },
   "HTTP_CACHE_DISPOSITION_2_V2": {
     "record_in_processes": ["main", "content"],
     "expires_in_version": "never",
     "kind": "enumerated",
     "n_values": 5,
     "description": "HTTP Cache v2 Hit, Reval, Failed-Reval, Miss"
   },
-  "HTTP_CACHE_MISS_HALFLIFE_EXPERIMENT_2": {
-    "record_in_processes": ["main", "content"],
-    "expires_in_version": "never",
-    "kind": "enumerated",
-    "n_values": 4,
-    "description": "HTTP Cache v2 Miss by half-life value (5 min, 15 min, 1 hour, 6 hours)"
-  },
   "HTTP_CACHE_ENTRY_RELOAD_TIME": {
     "record_in_processes": ["main", "content"],
     "expires_in_version": "never",
     "kind": "exponential",
     "high": 900000,
     "n_buckets": 50,
     "description": "Time before we reload an HTTP cache entry again to memory"
   },
--- a/toolkit/components/telemetry/histogram-whitelists.json
+++ b/toolkit/components/telemetry/histogram-whitelists.json
@@ -246,17 +246,16 @@
     "HISTORY_LASTVISITED_TREE_QUERY_TIME_MS",
     "HTTPCONNMGR_TOTAL_SPECULATIVE_CONN",
     "HTTPCONNMGR_UNUSED_SPECULATIVE_CONN",
     "HTTPCONNMGR_USED_SPECULATIVE_CONN",
     "HTTP_CACHE_DISPOSITION_2_V2",
     "HTTP_CACHE_ENTRY_ALIVE_TIME",
     "HTTP_CACHE_ENTRY_RELOAD_TIME",
     "HTTP_CACHE_ENTRY_REUSE_COUNT",
-    "HTTP_CACHE_MISS_HALFLIFE_EXPERIMENT_2",
     "HTTP_CONNECTION_ENTRY_CACHE_HIT_1",
     "HTTP_DISK_CACHE_OVERHEAD",
     "HTTP_KBREAD_PER_CONN",
     "HTTP_OFFLINE_CACHE_DOCUMENT_LOAD",
     "HTTP_PAGE_CACHE_READ_TIME_V2",
     "HTTP_PAGE_COMPLETE_LOAD_CACHED_V2",
     "HTTP_PAGE_COMPLETE_LOAD_NET_V2",
     "HTTP_PAGE_COMPLETE_LOAD_V2",
@@ -896,17 +895,16 @@
     "HISTORY_LASTVISITED_TREE_QUERY_TIME_MS",
     "HTTPCONNMGR_TOTAL_SPECULATIVE_CONN",
     "HTTPCONNMGR_UNUSED_SPECULATIVE_CONN",
     "HTTPCONNMGR_USED_SPECULATIVE_CONN",
     "HTTP_CACHE_DISPOSITION_2_V2",
     "HTTP_CACHE_ENTRY_ALIVE_TIME",
     "HTTP_CACHE_ENTRY_RELOAD_TIME",
     "HTTP_CACHE_ENTRY_REUSE_COUNT",
-    "HTTP_CACHE_MISS_HALFLIFE_EXPERIMENT_2",
     "HTTP_CONNECTION_ENTRY_CACHE_HIT_1",
     "HTTP_CONTENT_ENCODING",
     "HTTP_DISK_CACHE_OVERHEAD",
     "HTTP_KBREAD_PER_CONN",
     "HTTP_OFFLINE_CACHE_DOCUMENT_LOAD",
     "HTTP_PAGE_CACHE_READ_TIME_V2",
     "HTTP_PAGE_COMPLETE_LOAD_CACHED_V2",
     "HTTP_PAGE_COMPLETE_LOAD_NET_V2",
--- a/toolkit/crashreporter/client/crashreporter.h
+++ b/toolkit/crashreporter/client/crashreporter.h
@@ -162,15 +162,15 @@ void UIPruneSavedDumps(const std::string
 // If wait is true, wait for the program to terminate execution before
 // returning. Returns true if the program was launched correctly, false
 // otherwise.
 bool UIRunProgram(const std::string& exename,
                   const std::vector<std::string>& args,
                   bool wait = false);
 
 // Read the environment variable specified by name
-std::string UIGetEnv(const std::string name);
+std::string UIGetEnv(const std::string& name);
 
 #ifdef _MSC_VER
 # pragma warning( pop )
 #endif
 
 #endif
--- a/toolkit/crashreporter/client/crashreporter_unix_common.cpp
+++ b/toolkit/crashreporter/client/crashreporter_unix_common.cpp
@@ -158,17 +158,17 @@ std::ofstream* UIOpenWrite(const string&
 
   if (binary) {
     mode = mode | std::ios::binary;
   }
 
   return new std::ofstream(filename.c_str(), mode);
 }
 
-string UIGetEnv(const string name)
+string UIGetEnv(const string& name)
 {
   const char *var = getenv(name.c_str());
   if (var && *var) {
     return var;
   }
 
   return "";
 }
--- a/toolkit/crashreporter/client/crashreporter_win.cpp
+++ b/toolkit/crashreporter/client/crashreporter_win.cpp
@@ -1600,17 +1600,17 @@ bool UIRunProgram(const string& exename,
   }
 
   CloseHandle(pi.hProcess);
   CloseHandle(pi.hThread);
   return true;
 }
 
 string
-UIGetEnv(const string name)
+UIGetEnv(const string& name)
 {
   const wchar_t *var = _wgetenv(UTF8ToWide(name).c_str());
   if (var && *var) {
     return WideToUTF8(var);
   }
 
   return "";
 }