merge mozilla-inbound to mozilla-central. r=merge a=merge
authorSebastian Hengst <archaeopteryx@coole-files.de>
Sun, 20 Aug 2017 23:24:15 +0200
changeset 375859 7dddbd85047c6dc73ddbe1e423cd643a217845b3
parent 375849 0286df0f0eba0e81e2c628c332f90457c38ea926 (current diff)
parent 375858 47172ec305228afaa7fff15c8cb3c864954ef14c (diff)
child 375860 9914f61c12671114a6e063b353f5ac70394ab9ae
child 375901 6668a2b3f65ac1b362fc1c2c4511ad8d8ee13d2f
push id49207
push userarchaeopteryx@coole-files.de
push dateSun, 20 Aug 2017 21:26:25 +0000
treeherderautoland@9914f61c1267 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge, merge
milestone57.0a1
first release with
nightly linux32
7dddbd85047c / 57.0a1 / 20170821100350 / files
nightly linux64
7dddbd85047c / 57.0a1 / 20170821100350 / files
nightly mac
7dddbd85047c / 57.0a1 / 20170821100350 / files
nightly win32
7dddbd85047c / 57.0a1 / 20170821100350 / files
nightly win64
7dddbd85047c / 57.0a1 / 20170821100350 / 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 mozilla-inbound to mozilla-central. r=merge a=merge MozReview-Commit-ID: 1yS8D5e0Ejz
--- a/devtools/client/inspector/rules/test/browser_rules_eyedropper.js
+++ b/devtools/client/inspector/rules/test/browser_rules_eyedropper.js
@@ -96,16 +96,19 @@ function* testSelect(view, swatch, inspe
                                    options: {type: "mouseup"}});
 
   yield onPicked;
   yield onRuleViewChanged;
 
   let color = swatch.style.backgroundColor;
   is(color, EXPECTED_COLOR, "swatch changed colors");
 
+  ok(!swatch.eyedropperOpen, "swatch eye dropper is closed");
+  ok(!swatch.activeSwatch, "no active swatch");
+
   is((yield getComputedStyleProperty("div", null, "background-color")),
      EXPECTED_COLOR,
      "div's color set to body color after dropper");
 }
 
 function* openEyedropper(view, swatch) {
   let tooltip = view.tooltips.getTooltip("colorPicker").tooltip;
 
--- a/devtools/client/netmonitor/src/assets/styles/netmonitor.css
+++ b/devtools/client/netmonitor/src/assets/styles/netmonitor.css
@@ -92,25 +92,31 @@ body,
   align-items: center;
 }
 
 .requests-list-filter-buttons {
   display: flex;
   flex-wrap: wrap;
 }
 
-.learn-more-link {
-  color: var(--theme-highlight-blue);
-  cursor: pointer;
-  margin: 0 5px;
-  white-space: nowrap;
+/* Learn more links */
+
+.learn-more-link::before {
+  background-image: url(chrome://devtools/skin/images/help.svg);
 }
 
-.learn-more-link:hover {
-  text-decoration: underline;
+.tree-container .treeTable tr .learn-more-link {
+  position: absolute;
+  top: 0;
+  left: 0;
+  padding: 0;
+}
+
+.tree-container .treeTable tr:not(:hover) .learn-more-link {
+  opacity: 0.1;
 }
 
 /* Status bar */
 
 .devtools-status-bar-label {
   flex: 0;
 }
 
@@ -851,16 +857,17 @@ body,
    * Therefore, we set height with this magic number in order to remove the
    * redundant scrollbar when source editor appears.
    */
   height: calc(100% - 4px);
 }
 
 .tree-container .treeTable tr {
   display: block;
+  position: relative;
 }
 
 /* Make right td fill available horizontal space */
 .tree-container .treeTable td:last-child {
   width: 100%;
 }
 
 .properties-view .devtools-searchbox,
@@ -980,20 +987,16 @@ body,
 .headers-summary .textbox-input {
   margin-inline-end: 2px;
 }
 
 .headers-summary .status-text {
     width: auto!important;
 }
 
-.headers-summary .learn-more-link {
-  flex-grow: 1;
-}
-
 /* Response tabpanel */
 
 .response-error-header {
   margin: 0;
   padding: 3px 8px;
   background-color: var(--theme-highlight-red);
   color: var(--theme-selection-color);
 }
--- a/devtools/client/netmonitor/src/components/mdn-link.js
+++ b/devtools/client/netmonitor/src/components/mdn-link.js
@@ -14,20 +14,20 @@ const { L10N } = require("../utils/l10n"
 
 const { a } = DOM;
 
 const LEARN_MORE = L10N.getStr("netmonitor.headers.learnMore");
 
 function MDNLink({ url }) {
   return (
     a({
-      className: "learn-more-link",
-      title: url,
+      className: "devtools-button learn-more-link",
+      title: LEARN_MORE,
       onClick: (e) => onLearnMoreClick(e, url),
-    }, `[${LEARN_MORE}]`)
+    })
   );
 }
 
 MDNLink.displayName = "MDNLink";
 
 MDNLink.propTypes = {
   url: PropTypes.string.isRequired,
 };
--- a/devtools/client/netmonitor/test/browser_net_raw_headers.js
+++ b/devtools/client/netmonitor/test/browser_net_raw_headers.js
@@ -27,17 +27,17 @@ add_task(function* () {
 
   wait = waitForDOM(document, ".headers-overview");
   EventUtils.sendMouseEvent({ type: "mousedown" },
     document.querySelectorAll(".request-list-item")[0]);
   yield wait;
 
   wait = waitForDOM(document, ".raw-headers-container textarea", 2);
   EventUtils.sendMouseEvent({ type: "click" },
-    document.querySelectorAll(".headers-summary .devtools-button")[1]);
+    document.querySelectorAll(".headers-summary .devtools-button")[2]);
   yield wait;
 
   testShowRawHeaders(getSortedRequests(store.getState()).get(0));
 
   EventUtils.sendMouseEvent({ type: "click" },
     document.querySelectorAll(".headers-summary .devtools-button")[1]);
 
   testHideRawHeaders(document);
--- a/devtools/client/shared/widgets/tooltip/SwatchColorPickerTooltip.js
+++ b/devtools/client/shared/widgets/tooltip/SwatchColorPickerTooltip.js
@@ -171,16 +171,17 @@ SwatchColorPickerTooltip.prototype = Her
       this.hide();
 
       this.tooltip.emit("eyedropper-opened");
     }, e => console.error(e));
 
     inspector.once("color-picked", color => {
       toolbox.win.focus();
       this._selectColor(color);
+      this._onEyeDropperDone();
     });
 
     inspector.once("color-pick-canceled", () => {
       this._onEyeDropperDone();
     });
   },
 
   _onEyeDropperDone: function () {
--- a/devtools/client/themes/images/help.svg
+++ b/devtools/client/themes/images/help.svg
@@ -1,4 +1,6 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
-  <circle cx="12" cy="12" r="11" stroke-width="2" stroke="currentColor" fill="none"/>
-  <path d="M12.2,4.9c-1.6,0-2.9,0.4-3.8,0.8L9.2,8c0.6-0.4,1.5-0.6,2.2-0.6c1.1,0,1.6,0.5,1.6,1.2 c0,0.7-0.6,1.3-1.3,2.1c-1,1.1-1.4,2.1-1.3,3.2l0,0.5h3V14c0-0.9,0.3-1.7,1.2-2.5c0.9-0.9,1.9-1.9,1.9-3.4 C16.6,6.4,15.2,4.9,12.2,4.9z M12,16.1c-1.1,0-1.9,0.8-1.9,1.9c0,1.1,0.8,1.9,1.9,1.9c1.2,0,1.9-0.8,1.9-1.9 C13.9,16.9,13.1,16.1,12,16.1z"/>
+<!-- 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/. -->
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
+  <path fill="context-fill" d="M8 1a7 7 0 1 0 7 7 7.008 7.008 0 0 0-7-7zm0 13a6 6 0 1 1 6-6 6.007 6.007 0 0 1-6 6zM8 3.125A2.7 2.7 0 0 0 5.125 6a.875.875 0 0 0 1.75 0c0-1 .6-1.125 1.125-1.125a1.105 1.105 0 0 1 1.13.744.894.894 0 0 1-.53 1.016A2.738 2.738 0 0 0 7.125 9v.337a.875.875 0 0 0 1.75 0v-.37a1.041 1.041 0 0 1 .609-.824A2.637 2.637 0 0 0 10.82 5.16 2.838 2.838 0 0 0 8 3.125zm0 7.625A1.25 1.25 0 1 0 9.25 12 1.25 1.25 0 0 0 8 10.75z"></path>
 </svg>
--- a/layout/style/ServoBindings.cpp
+++ b/layout/style/ServoBindings.cpp
@@ -84,16 +84,17 @@ using namespace mozilla::dom;
     result.swap(mPtr);               \
     return result.forget();          \
   }
 #include "mozilla/ServoArcTypeList.h"
 SERVO_ARC_TYPE(StyleContext, ServoStyleContext)
 #undef SERVO_ARC_TYPE
 
 static Mutex* sServoFontMetricsLock = nullptr;
+static Mutex* sServoWidgetLock = nullptr;
 static RWLock* sServoLangFontPrefsLock = nullptr;
 
 static
 const nsFont*
 ThreadSafeGetDefaultFontHelper(const nsPresContext* aPresContext,
                                nsIAtom* aLanguage, uint8_t aGenericId)
 {
   bool needsCache = false;
@@ -857,22 +858,24 @@ Gecko_FillAllMaskLists(nsStyleImageLayer
 }
 
 RawGeckoElementBorrowedOrNull
 Gecko_GetBody(RawGeckoPresContextBorrowed aPresContext)
 {
   return aPresContext->Document()->GetBodyElement();
 }
 
-nscolor Gecko_GetLookAndFeelSystemColor(int32_t aId,
-                                        RawGeckoPresContextBorrowed aPresContext)
+nscolor
+Gecko_GetLookAndFeelSystemColor(int32_t aId,
+                                RawGeckoPresContextBorrowed aPresContext)
 {
   bool useStandinsForNativeColors = aPresContext && !aPresContext->IsChrome();
   nscolor result;
   LookAndFeel::ColorID colorId = static_cast<LookAndFeel::ColorID>(aId);
+  MutexAutoLock guard(*sServoWidgetLock);
   LookAndFeel::GetColor(colorId, useStandinsForNativeColors, &result);
   return result;
 }
 
 bool
 Gecko_MatchStringArgPseudo(RawGeckoElementBorrowed aElement,
                            CSSPseudoClassType aType,
                            const char16_t* aIdent,
@@ -2453,23 +2456,29 @@ Gecko_XBLBinding_InheritsStyle(RawGeckoX
 
 void
 InitializeServo()
 {
   URLExtraData::InitDummy();
   Servo_Initialize(URLExtraData::Dummy());
 
   sServoFontMetricsLock = new Mutex("Gecko_GetFontMetrics");
+  sServoWidgetLock = new Mutex("Servo::WidgetLock");
   sServoLangFontPrefsLock = new RWLock("nsPresContext::GetDefaultFont");
 }
 
 void
 ShutdownServo()
 {
+  MOZ_ASSERT(sServoFontMetricsLock);
+  MOZ_ASSERT(sServoWidgetLock);
+  MOZ_ASSERT(sServoLangFontPrefsLock);
+
   delete sServoFontMetricsLock;
+  delete sServoWidgetLock;
   delete sServoLangFontPrefsLock;
   Servo_Shutdown();
 }
 
 namespace mozilla {
 
 void
 AssertIsMainThreadOrServoFontMetricsLocked()
--- a/netwerk/base/TCPFastOpenLayer.h
+++ b/netwerk/base/TCPFastOpenLayer.h
@@ -14,20 +14,30 @@ namespace net {
 
 /**
  * This layer must be placed just above PR-tcp socket, i.e. it must be under
  * nss layer.
  * At the beginning of TCPFastOpenLayer.cpp there is explanation what this
  * layer do.
  **/
 
-#define TFO_NOT_TRIED 0
-#define TFO_TRIED     1
-#define TFO_DATA_SENT 2
-#define TFO_FAILED    3
+typedef enum {
+  TFO_NOT_TRIED,
+  TFO_TRIED,
+  TFO_DATA_SENT,
+  TFO_FAILED_CONNECTION_REFUSED,
+  TFO_FAILED_NET_TIMEOUT,
+  TFO_FAILED_UNKNOW_ERROR,
+  TFO_FAILED_BACKUP_CONNECTION,
+  TFO_FAILED_CONNECTION_REFUSED_NO_TFO_FAILED_TOO,
+  TFO_FAILED_NET_TIMEOUT__NO_TFO_FAILED_TOO,
+  TFO_FAILED_UNKNOW_ERROR_NO_TFO_FAILED_TOO,
+  TFO_FAILED_BACKUP_CONNECTION_NO_TFO_FAILED_TOO,
+  TFO_FAILED
+} TFOResult;
 
 nsresult AttachTCPFastOpenIOLayer(PRFileDesc *fd);
 
 // Get the result of TCP Fast Open.
 void TCPFastOpenFinish(PRFileDesc *fd, PRErrorCode &err,
                        bool &fastOpenNotSupported, uint8_t &tfoStatus);
 
 int32_t TCPFastOpenGetBufferSizeLeft(PRFileDesc *fd);
--- a/netwerk/base/nsISocketTransport.idl
+++ b/netwerk/base/nsISocketTransport.idl
@@ -266,9 +266,11 @@ interface nsISocketTransport : nsITransp
      * Note that the attribute as well as the setter can only accessed
      * in the socket thread.
      */
     attribute boolean keepaliveEnabled;
     void setKeepaliveVals(in long keepaliveIdleTime,
                           in long keepaliveRetryInterval);
 
     [noscript] void setFastOpenCallback(in TCPFastOpenPtr aFastOpen);
+
+    readonly attribute nsresult firstRetryError;
 };
--- a/netwerk/base/nsSocketTransport2.cpp
+++ b/netwerk/base/nsSocketTransport2.cpp
@@ -795,16 +795,18 @@ nsSocketTransport::nsSocketTransport()
     , mOutput(this)
     , mQoSBits(0x00)
     , mKeepaliveEnabled(false)
     , mKeepaliveIdleTimeS(-1)
     , mKeepaliveRetryIntervalS(-1)
     , mKeepaliveProbeCount(-1)
     , mFastOpenCallback(nullptr)
     , mFastOpenLayerHasBufferedData(false)
+    , mFastOpenStatus(TFO_NOT_TRIED)
+    , mFirstRetryError(NS_OK)
     , mDoNotRetryToConnect(false)
 {
     SOCKET_LOG(("creating nsSocketTransport @%p\n", this));
 
     mTimeouts[TIMEOUT_CONNECT]    = UINT16_MAX; // no timeout
     mTimeouts[TIMEOUT_READ_WRITE] = UINT16_MAX; // no timeout
 }
 
@@ -1565,35 +1567,34 @@ nsSocketTransport::InitiateSocket()
             mFastOpenCallback = nullptr;
             MutexAutoLock lock(mLock);
             mFDFastOpenInProgress = false;
             return rv;
         }
         status = PR_FAILURE;
         connectCalled = false;
         bool fastOpenNotSupported = false;
-        uint8_t tfoStatus = TFO_NOT_TRIED;
-        TCPFastOpenFinish(fd, code, fastOpenNotSupported, tfoStatus);
+        TCPFastOpenFinish(fd, code, fastOpenNotSupported, mFastOpenStatus);
 
         // If we have sent data, trigger a socket status event.
-        if (tfoStatus == TFO_DATA_SENT) {
+        if (mFastOpenStatus == TFO_DATA_SENT) {
             SendStatus(NS_NET_STATUS_SENDING_TO);
         }
 
         // If we have still some data buffered this data must be flush before
         // mOutput.OnSocketReady(NS_OK) is called in
         // nsSocketTransport::OnSocketReady, partially to keep socket status
         // event in order.
         mFastOpenLayerHasBufferedData = TCPFastOpenGetCurrentBufferSize(fd);
 
-        mFastOpenCallback->SetFastOpenStatus(tfoStatus);
+        mFastOpenCallback->SetFastOpenStatus(mFastOpenStatus);
         SOCKET_LOG(("called StartFastOpen - code=%d; fastOpen is %s "
                     "supported.\n", code,
                     fastOpenNotSupported ? "not" : ""));
-        SOCKET_LOG(("TFO status %d\n", tfoStatus));
+        SOCKET_LOG(("TFO status %d\n", mFastOpenStatus));
 
         if (fastOpenNotSupported) {
           // When TCP_FastOpen is turned off on the local host
           // SendTo will return PR_NOT_TCP_SOCKET_ERROR. This is only
           // on Linux.
           // If a windows version does not support Fast Open, the return value
           // will be PR_NOT_IMPLEMENTED_ERROR. This is only for windows 10
           // versions older than version 1607, because we do not have subverion
@@ -1771,18 +1772,23 @@ nsSocketTransport::RecoverFromError()
         tryAgain = true;
         // If we cancel the connection because backup socket was successfully
         // connected, mFDFastOpenInProgress will be true but mFastOpenCallback
         // will be nullptr.
         if (mFastOpenCallback) {
             mFastOpenCallback->SetFastOpenConnected(mCondition, true);
         }
         mFastOpenCallback = nullptr;
+
     } else {
 
+        // This is only needed for telemetry.
+        if (NS_SUCCEEDED(mFirstRetryError)) {
+            mFirstRetryError = mCondition;
+        }
         if ((mState == STATE_CONNECTING) && mDNSRecord &&
             mSocketTransportService->IsTelemetryEnabledAndNotSleepPhase()) {
             if (mNetAddr.raw.family == AF_INET) {
                 Telemetry::Accumulate(Telemetry::IPV4_AND_IPV6_ADDRESS_CONNECTIVITY,
                                       UNSUCCESSFUL_CONNECTING_TO_IPV4_ADDRESS);
             } else if (mNetAddr.raw.family == AF_INET6) {
                 Telemetry::Accumulate(Telemetry::IPV4_AND_IPV6_ADDRESS_CONNECTIVITY,
                                       UNSUCCESSFUL_CONNECTING_TO_IPV6_ADDRESS);
@@ -2212,16 +2218,34 @@ nsSocketTransport::OnSocketReady(PRFileD
         // nsIOService::LastConectivityChange time to be atomic.
         PRIntervalTime connectStarted = 0;
         if (gSocketTransportService->IsTelemetryEnabledAndNotSleepPhase()) {
             connectStarted = PR_IntervalNow();
         }
 
         PRStatus status = PR_ConnectContinue(fd, outFlags);
 
+#if defined(_WIN64) && defined(WIN95)
+#ifndef TCP_FASTOPEN
+#define TCP_FASTOPEN 15
+#endif
+
+        if (mFDFastOpenInProgress && mFastOpenCallback &&
+            (mFastOpenStatus == TFO_DATA_SENT)) {
+            PROsfd osfd = PR_FileDesc2NativeHandle(fd);
+            BOOL option = 0;
+            int len = sizeof(option);
+            PRInt32 rv = getsockopt((SOCKET)osfd, IPPROTO_TCP, TCP_FASTOPEN, (char*)&option, &len);
+            if ((rv != 0) && !option) {
+                // On error, I will let the normal necko paths pickup the error.
+                mFastOpenCallback->SetFastOpenStatus(TFO_NOT_TRIED);
+            }
+        }
+#endif
+
         if (gSocketTransportService->IsTelemetryEnabledAndNotSleepPhase() &&
             connectStarted) {
             SendPRBlockingTelemetry(connectStarted,
                 Telemetry::PRCONNECTCONTINUE_BLOCKING_TIME_NORMAL,
                 Telemetry::PRCONNECTCONTINUE_BLOCKING_TIME_SHUTDOWN,
                 Telemetry::PRCONNECTCONTINUE_BLOCKING_TIME_CONNECTIVITY_CHANGE,
                 Telemetry::PRCONNECTCONTINUE_BLOCKING_TIME_LINK_CHANGE,
                 Telemetry::PRCONNECTCONTINUE_BLOCKING_TIME_OFFLINE);
@@ -3579,10 +3603,17 @@ nsSocketTransport::SendPRBlockingTelemet
 
 NS_IMETHODIMP
 nsSocketTransport::SetFastOpenCallback(TCPFastOpen *aFastOpen)
 {
   mFastOpenCallback = aFastOpen;
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsSocketTransport::GetFirstRetryError(nsresult *aFirstRetryError)
+{
+  *aFirstRetryError = mFirstRetryError;
+  return NS_OK;
+}
+
 } // namespace net
 } // namespace mozilla
--- a/netwerk/base/nsSocketTransport2.h
+++ b/netwerk/base/nsSocketTransport2.h
@@ -473,16 +473,18 @@ private:
     // Keepalive config (support varies by platform).
     int32_t mKeepaliveIdleTimeS;
     int32_t mKeepaliveRetryIntervalS;
     int32_t mKeepaliveProbeCount;
 
     // A Fast Open callback.
     TCPFastOpen *mFastOpenCallback;
     bool mFastOpenLayerHasBufferedData;
+    uint8_t mFastOpenStatus;
+    nsresult mFirstRetryError;
 
     bool mDoNotRetryToConnect;
 };
 
 } // namespace net
 } // namespace mozilla
 
 #endif // !nsSocketTransport_h__
--- a/netwerk/protocol/http/TunnelUtils.cpp
+++ b/netwerk/protocol/http/TunnelUtils.cpp
@@ -1520,16 +1520,22 @@ SocketTransportShim::SetEventSink(nsITra
 }
 
 NS_IMETHODIMP
 SocketTransportShim::Bind(NetAddr *aLocalAddr)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
+NS_IMETHODIMP
+SocketTransportShim::GetFirstRetryError(nsresult *aFirstRetryError)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
 #define FWD_TS_PTR(fx, ts) NS_IMETHODIMP \
 SocketTransportShim::fx(ts *arg) { return mWrapped->fx(arg); }
 
 #define FWD_TS_ADDREF(fx, ts) NS_IMETHODIMP \
 SocketTransportShim::fx(ts **arg) { return mWrapped->fx(arg); }
 
 #define FWD_TS(fx, ts) NS_IMETHODIMP \
 SocketTransportShim::fx(ts arg) { return mWrapped->fx(arg); }
--- a/netwerk/protocol/http/nsHttpConnection.cpp
+++ b/netwerk/protocol/http/nsHttpConnection.cpp
@@ -120,17 +120,30 @@ nsHttpConnection::~nsHttpConnection()
                               Telemetry::HTTP_KBREAD_PER_CONN,
                               totalKBRead);
     }
     if (mForceSendTimer) {
         mForceSendTimer->Cancel();
         mForceSendTimer = nullptr;
     }
 
-    Telemetry::Accumulate(Telemetry::TCP_FAST_OPEN, mFastOpenStatus);
+    if ((mFastOpenStatus != TFO_FAILED) &&
+        ((mFastOpenStatus != TFO_NOT_TRIED) ||
+ #if defined(_WIN64) && defined(WIN95)
+         (gHttpHandler->UseFastOpen() &&
+          gSocketTransportService &&
+          gSocketTransportService->HasFileDesc2PlatformOverlappedIOHandleFunc()))) {
+#else
+         gHttpHandler->UseFastOpen())) {
+#endif
+        // TFO_FAILED will be reported in the replacement connection with more
+        // details.
+        // Otherwise report only if TFO is enabled and supported.
+        Telemetry::Accumulate(Telemetry::TCP_FAST_OPEN_2, mFastOpenStatus);
+    }
 }
 
 nsresult
 nsHttpConnection::Init(nsHttpConnectionInfo *info,
                        uint16_t maxHangTime,
                        nsISocketTransport *transport,
                        nsIAsyncInputStream *instream,
                        nsIAsyncOutputStream *outstream,
@@ -2389,15 +2402,28 @@ nsHttpConnection::SetFastOpen(bool aFast
     if (!mFastOpen &&
         mTransaction &&
         !mTransaction->IsNullTransaction()) {
         mExperienced = true;
     }
 }
 
 void
+nsHttpConnection::SetFastOpenStatus(uint8_t tfoStatus) {
+    mFastOpenStatus = tfoStatus;
+    if ((mFastOpenStatus >= TFO_FAILED_CONNECTION_REFUSED) &&
+        mSocketTransport) {
+        nsresult firstRetryError;
+        if (NS_SUCCEEDED(mSocketTransport->GetFirstRetryError(&firstRetryError)) &&
+            (NS_FAILED(firstRetryError))) {
+            mFastOpenStatus = tfoStatus + 4; 
+        }
+    }
+}
+
+void
 nsHttpConnection::BootstrapTimings(TimingStruct times)
 {
     mBootstrappedTimings = times;
 }
 
 } // namespace net
 } // namespace mozilla
--- a/netwerk/protocol/http/nsHttpConnection.h
+++ b/netwerk/protocol/http/nsHttpConnection.h
@@ -228,19 +228,17 @@ public:
             !mFastOpen;
     }
     // override of nsAHttpConnection
     virtual uint32_t Version();
 
     bool TestJoinConnection(const nsACString &hostname, int32_t port);
     bool JoinConnection(const nsACString &hostname, int32_t port);
 
-    void SetFastOpenStatus(uint8_t tfoStatus) {
-        mFastOpenStatus = tfoStatus;
-    }
+    void SetFastOpenStatus(uint8_t tfoStatus);
 
 private:
     // Value (set in mTCPKeepaliveConfig) indicates which set of prefs to use.
     enum TCPKeepaliveConfig {
       kTCPKeepaliveDisabled = 0,
       kTCPKeepaliveShortLivedConfig,
       kTCPKeepaliveLongLivedConfig
     };
--- a/netwerk/protocol/http/nsHttpConnectionMgr.cpp
+++ b/netwerk/protocol/http/nsHttpConnectionMgr.cpp
@@ -3721,16 +3721,17 @@ nsHalfOpenSocket::nsHalfOpenSocket(nsCon
     , mIsFromPredictor(isFromPredictor)
     , mAllow1918(true)
     , mHasConnected(false)
     , mPrimaryConnectedOK(false)
     , mBackupConnectedOK(false)
     , mFreeToUse(true)
     , mPrimaryStreamStatus(NS_OK)
     , mFastOpenInProgress(false)
+    , mFastOpenStatus(TFO_NOT_TRIED)
     , mEnt(ent)
 {
     MOZ_ASSERT(ent && trans, "constructor with null arguments");
     LOG(("Creating nsHalfOpenSocket [this=%p trans=%p ent=%s key=%s]\n",
          this, trans, ent->mConnInfo->Origin(), ent->mConnInfo->HashKey().get()));
 
     if (speculative) {
         Telemetry::AutoCounter<Telemetry::HTTPCONNMGR_TOTAL_SPECULATIVE_CONN> totalSpeculativeConn;
@@ -4171,16 +4172,17 @@ nsHalfOpenSocket::OnOutputStreamReady(ns
         }
         if (mEnt->mUseFastOpen) {
             gHttpHandler->IncrementFastOpenConsecutiveFailureCounter();
             mEnt->mUseFastOpen = false;
         }
 
         mFastOpenInProgress = false;
         mConnectionNegotiatingFastOpen = nullptr;
+        mFastOpenStatus = TFO_FAILED_BACKUP_CONNECTION;
     }
 
     nsresult rv =  SetupConn(out, false);
     if (mEnt) {
         mEnt->mDoNotDestroy = false;
     }
     return rv;
 }
@@ -4353,16 +4355,17 @@ nsHalfOpenSocket::SetFastOpenConnected(n
     if (aWillRetry &&
         ((aError == NS_ERROR_CONNECTION_REFUSED) ||
 #if defined(_WIN64) && defined(WIN95)
          // On Windows PR_ContinueConnect can return NS_ERROR_FAILURE.
          // This will be fixed in bug 1386719 and this is just a temporary
          // work around.
          (aError == NS_ERROR_FAILURE) ||
 #endif
+         (aError == NS_ERROR_PROXY_CONNECTION_REFUSED) ||
          (aError == NS_ERROR_NET_TIMEOUT))) {
         if (mEnt->mUseFastOpen) {
             gHttpHandler->IncrementFastOpenConsecutiveFailureCounter();
             mEnt->mUseFastOpen = false;
         }
         // This is called from nsSocketTransport::RecoverFromError. The
         // socket will try connect and we need to rewind nsHttpTransaction.
 
@@ -4392,16 +4395,24 @@ nsHalfOpenSocket::SetFastOpenConnected(n
         gHttpHandler->ConnMgr()->StartedConnect();
 
         // Restore callbacks.
         mStreamOut->AsyncWait(this, 0, 0, nullptr);
         mSocketTransport->SetEventSink(this, nullptr);
         mSocketTransport->SetSecurityCallbacks(this);
         mStreamIn->AsyncWait(nullptr, 0, 0, nullptr);
 
+        if (aError == NS_ERROR_CONNECTION_REFUSED) {
+            mFastOpenStatus = TFO_FAILED_CONNECTION_REFUSED;
+        } else if (aError == NS_ERROR_NET_TIMEOUT) {
+            mFastOpenStatus = TFO_FAILED_NET_TIMEOUT;
+        } else {
+            mFastOpenStatus = TFO_FAILED_UNKNOW_ERROR;
+        }
+
     } else {
         // On success or other error we proceed with connection, we just need
         // to close backup timer and halfOpenSock.
         CancelBackupTimer();
         if (NS_SUCCEEDED(aError)) {
             NetAddr peeraddr;
             if (NS_SUCCEEDED(mSocketTransport->GetPeerAddr(&peeraddr))) {
                 mEnt->RecordIPFamilyPreference(peeraddr.raw.family);
@@ -4653,16 +4664,18 @@ nsHalfOpenSocket::SetupConn(nsIAsyncOutp
         MOZ_ASSERT(mEnt);
         MOZ_ASSERT(static_cast<int32_t>(mEnt->mIdleConns.IndexOf(conn)) == -1);
         int32_t idx = mEnt->mActiveConns.IndexOf(conn);
         if (NS_SUCCEEDED(rv) && (idx != -1)) {
             mConnectionNegotiatingFastOpen = conn;
         } else {
             conn->SetFastOpen(false);
         }
+    } else {
+        conn->SetFastOpenStatus(mFastOpenStatus);
     }
 
     // If this halfOpenConn was speculative, but at the ende the conn got a
     // non-null transaction than this halfOpen is not speculative anymore!
     if (conn->Transaction() && !conn->Transaction()->IsNullTransaction()) {
         Claim();
     }
 
--- a/netwerk/protocol/http/nsHttpConnectionMgr.h
+++ b/netwerk/protocol/http/nsHttpConnectionMgr.h
@@ -468,16 +468,17 @@ private:
         // but the transaction can be dispatch to another connection. In that
         // case we can free this transaction to be claimed by other
         // transactions.
         bool                           mFreeToUse;
         nsresult                       mPrimaryStreamStatus;
 
         bool                           mFastOpenInProgress;
         RefPtr<nsHttpConnection>       mConnectionNegotiatingFastOpen;
+        uint8_t                        mFastOpenStatus;
 
         RefPtr<nsConnectionEntry>      mEnt;
         nsCOMPtr<nsITimer>             mSynTimer;
         nsCOMPtr<nsISocketTransport>   mBackupTransport;
         nsCOMPtr<nsIAsyncOutputStream> mBackupStreamOut;
         nsCOMPtr<nsIAsyncInputStream>  mBackupStreamIn;
     };
     friend class nsHalfOpenSocket;
--- a/netwerk/protocol/http/nsHttpHandler.cpp
+++ b/netwerk/protocol/http/nsHttpHandler.cpp
@@ -2294,16 +2294,26 @@ nsHttpHandler::Observe(nsISupports *subj
         // depend on this value.
         mSessionStartTime = NowInSeconds();
 
         if (!mDoNotTrackEnabled) {
             Telemetry::Accumulate(Telemetry::DNT_USAGE, 2);
         } else {
             Telemetry::Accumulate(Telemetry::DNT_USAGE, 1);
         }
+
+        if (UseFastOpen()) {
+            Telemetry::Accumulate(Telemetry::TCP_FAST_OPEN_STATUS, 0);
+        } else if (!mFastOpenSupported) {
+            Telemetry::Accumulate(Telemetry::TCP_FAST_OPEN_STATUS, 1);
+        } else if (!mUseFastOpen) {
+            Telemetry::Accumulate(Telemetry::TCP_FAST_OPEN_STATUS, 2);
+        } else {
+            Telemetry::Accumulate(Telemetry::TCP_FAST_OPEN_STATUS, 3);
+        }
     } else if (!strcmp(topic, "profile-change-net-restore")) {
         // initialize connection manager
         rv = InitConnectionMgr();
         MOZ_ASSERT(NS_SUCCEEDED(rv));
     } else if (!strcmp(topic, "net:clear-active-logins")) {
         Unused << mAuthCache.ClearAll();
         Unused << mPrivateAuthCache.ClearAll();
     } else if (!strcmp(topic, "net:prune-dead-connections")) {
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -2540,24 +2540,33 @@
     "alert_emails": ["necko@mozilla.com"],
     "bug_numbers": [1357682],
     "expires_in_version": "61",
     "kind": "categorical",
     "keyed": true,
     "description": "Stats about success rate of HTTP OMT request in content process, keyed by content policy.",
     "labels": ["success", "successMainThread", "failListener", "failListenerChain", "notRequested"]
   },
-  "TCP_FAST_OPEN": {
+  "TCP_FAST_OPEN_2": {
+    "record_in_processes": ["main", "content"],
+    "expires_in_version": "61",
+    "kind": "enumerated",
+    "n_values": 16,
+    "description": "When a http connection is closed, track whether or not TCP Fast Open was used: 0=TFO_NOT_TRIED(There was no http connection and it was not TLS), 1=TFO_TRIED_NEGOTIATING, 2=TFO_DATA_SENT, 3=TFO_FAILED_CONNECTION_REFUSED, 4=TFO_FAILED_NET_TIMEOUT, 5=TFO_FAILED_UNKNOW_ERROR, 6=TFO_FAILED_BACKUP_CONNECTION, 7=TFO_FAILED_CONNECTION_REFUSED_NO_TFO_FAILED_TOO, 8=TFO_FAILED_NET_TIMEOUT__NO_TFO_FAILED_TOO, 9=TFO_FAILED_UNKNOW_ERROR_NO_TFO_FAILED_TOO, 10=TFO_FAILED_BACKUP_CONNECTION_NO_TFO_FAILED_TOO.",
+    "alert_emails": ["necko@mozilla.com", "ddamjanovic@mozilla.com"],
+    "bug_numbers": [1390881]
+  },
+  "TCP_FAST_OPEN_STATUS": {
     "record_in_processes": ["main", "content"],
     "expires_in_version": "61",
     "kind": "enumerated",
     "n_values": 8,
-    "description": "When a http connection is closed, track whether or not TCP Fast Open was used: 0=TFO_NOT_TRIED, 1=TFO_TRIED_NEGOTIATING, 2=TFO_DATA_SENT, 3=TFO_FAILED.",
-    "alert_emails": ["necko@mozilla.com"],
-    "bug_numbers": [1352271]
+    "description": "TCP Fast Open was: 0=enabled during the session, 1=not available or disabled in the os, 2=disabled by the pref, 3=disabled based on the too many connection failures.",
+    "alert_emails": ["necko@mozilla.com", "ddamjanovic@mozilla.com"],
+    "bug_numbers": [1390881]
   },
   "TLS_EARLY_DATA_NEGOTIATED": {
     "record_in_processes": ["main", "content"],
     "expires_in_version": "58",
     "kind": "enumerated",
     "n_values": 3,
     "description": "Sending TLS early data was possible: 0 - not possible, 1 - possible but not used, 2 - possible and used.",
     "alert_emails": ["necko@mozilla.com"],