Bug 1658097 - [fission] Send resource timing data for cross-origin frames to the correct process r=nika,necko-reviewers,dragana
authorValentin Gosu <valentin.gosu@gmail.com>
Fri, 13 Nov 2020 13:48:00 +0000
changeset 557256 f8ce8da605a894697914a0e780fda51f54d47abd
parent 557255 4b5ac6fbe89662c0fc8d58efa241dd3edd13f09d
child 557257 cc70ff610a7edf4cc4eb19a97d301292ef8ce04f
push id37950
push userbtara@mozilla.com
push dateSun, 15 Nov 2020 09:34:18 +0000
treeherdermozilla-central@25b666d6e2ab [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnika, necko-reviewers, dragana
bugs1658097
milestone84.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1658097 - [fission] Send resource timing data for cross-origin frames to the correct process r=nika,necko-reviewers,dragana Differential Revision: https://phabricator.services.mozilla.com/D96754
dom/ipc/ContentChild.cpp
dom/ipc/ContentChild.h
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
dom/ipc/PContent.ipdl
dom/performance/PerformanceMainThread.cpp
dom/performance/PerformanceMainThread.h
dom/performance/PerformanceStorage.h
dom/performance/PerformanceStorageWorker.h
dom/performance/PerformanceTiming.h
dom/tests/mochitest/general/mochitest.ini
netwerk/protocol/http/HttpBaseChannel.cpp
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -191,16 +191,17 @@
 #endif
 #include "IHistory.h"
 #include "ReferrerInfo.h"
 #include "base/message_loop.h"
 #include "base/process_util.h"
 #include "base/task.h"
 #include "mozilla/dom/BlobURLProtocolHandler.h"
 #include "mozilla/dom/PCycleCollectWithLogsChild.h"
+#include "mozilla/dom/PerformanceStorage.h"
 #include "nsChromeRegistryContent.h"
 #include "nsFrameMessageManager.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsNetUtil.h"
 #include "nsWindowMemoryReporter.h"
 
 #ifdef MOZ_WEBRTC
 #  include "jsapi/WebrtcGlobalChild.h"
@@ -4073,16 +4074,34 @@ mozilla::ipc::IPCResult ContentChild::Re
                                 aColNumber, aFlags, aCategory, aInnerWindowId,
                                 aFromChromeContext);
   rv = consoleService->LogMessage(scriptError);
   NS_ENSURE_SUCCESS(rv, IPC_FAIL(this, "Failed to log script error"));
 
   return IPC_OK();
 }
 
+mozilla::ipc::IPCResult ContentChild::RecvReportFrameTimingData(
+    uint64_t innerWindowId, const nsString& entryName,
+    const nsString& initiatorType, UniquePtr<PerformanceTimingData>&& aData) {
+  auto* innerWindow = nsGlobalWindowInner::GetInnerWindowWithId(innerWindowId);
+  if (!innerWindow) {
+    return IPC_OK();
+  }
+
+  mozilla::dom::Performance* performance = innerWindow->GetPerformance();
+  if (!performance) {
+    return IPC_OK();
+  }
+
+  performance->AsPerformanceStorage()->AddEntry(entryName, initiatorType,
+                                                std::move(aData));
+  return IPC_OK();
+}
+
 mozilla::ipc::IPCResult ContentChild::RecvLoadURI(
     const MaybeDiscarded<BrowsingContext>& aContext,
     nsDocShellLoadState* aLoadState, bool aSetNavigating,
     LoadURIResolver&& aResolve) {
   auto resolveOnExit = MakeScopeExit([&] { aResolve(true); });
 
   if (aContext.IsNullOrDiscarded()) {
     return IPC_OK();
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -758,16 +758,20 @@ class ContentChild final : public PConte
 
   mozilla::ipc::IPCResult RecvScriptError(
       const nsString& aMessage, const nsString& aSourceName,
       const nsString& aSourceLine, const uint32_t& aLineNumber,
       const uint32_t& aColNumber, const uint32_t& aFlags,
       const nsCString& aCategory, const bool& aFromPrivateWindow,
       const uint64_t& aInnerWindowId, const bool& aFromChromeContext);
 
+  mozilla::ipc::IPCResult RecvReportFrameTimingData(
+      uint64_t innerWindowId, const nsString& entryName,
+      const nsString& initiatorType, UniquePtr<PerformanceTimingData>&& aData);
+
   mozilla::ipc::IPCResult RecvLoadURI(
       const MaybeDiscarded<BrowsingContext>& aContext,
       nsDocShellLoadState* aLoadState, bool aSetNavigating,
       LoadURIResolver&& aResolve);
 
   mozilla::ipc::IPCResult RecvInternalLoad(nsDocShellLoadState* aLoadState,
                                            bool aTakeFocus);
 
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -4499,16 +4499,33 @@ mozilla::ipc::IPCResult ContentParent::R
     return IPC_OK();
   }
 
   RefPtr<nsConsoleMessage> msg(new nsConsoleMessage(aMessage.get()));
   consoleService->LogMessageWithMode(msg, nsConsoleService::SuppressLog);
   return IPC_OK();
 }
 
+mozilla::ipc::IPCResult ContentParent::RecvReportFrameTimingData(
+    uint64_t aInnerWindowId, const nsString& entryName,
+    const nsString& initiatorType, UniquePtr<PerformanceTimingData>&& aData) {
+  RefPtr<WindowGlobalParent> parent =
+      WindowGlobalParent::GetByInnerWindowId(aInnerWindowId);
+  if (!parent || !parent->GetContentParent()) {
+    return IPC_OK();
+  }
+
+  MOZ_ASSERT(parent->GetContentParent() != this,
+             "No need to bounce around if in the same process");
+
+  Unused << parent->GetContentParent()->SendReportFrameTimingData(
+      aInnerWindowId, entryName, initiatorType, std::move(aData));
+  return IPC_OK();
+}
+
 mozilla::ipc::IPCResult ContentParent::RecvScriptError(
     const nsString& aMessage, const nsString& aSourceName,
     const nsString& aSourceLine, const uint32_t& aLineNumber,
     const uint32_t& aColNumber, const uint32_t& aFlags,
     const nsCString& aCategory, const bool& aFromPrivateWindow,
     const uint64_t& aInnerWindowId, const bool& aFromChromeContext) {
   return RecvScriptErrorInternal(aMessage, aSourceName, aSourceLine,
                                  aLineNumber, aColNumber, aFlags, aCategory,
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -1092,16 +1092,20 @@ class ContentParent final
 
   mozilla::ipc::IPCResult RecvScriptError(
       const nsString& aMessage, const nsString& aSourceName,
       const nsString& aSourceLine, const uint32_t& aLineNumber,
       const uint32_t& aColNumber, const uint32_t& aFlags,
       const nsCString& aCategory, const bool& aIsFromPrivateWindow,
       const uint64_t& aInnerWindowId, const bool& aIsFromChromeContext);
 
+  mozilla::ipc::IPCResult RecvReportFrameTimingData(
+      uint64_t innerWindowId, const nsString& entryName,
+      const nsString& initiatorType, UniquePtr<PerformanceTimingData>&& aData);
+
   mozilla::ipc::IPCResult RecvScriptErrorWithStack(
       const nsString& aMessage, const nsString& aSourceName,
       const nsString& aSourceLine, const uint32_t& aLineNumber,
       const uint32_t& aColNumber, const uint32_t& aFlags,
       const nsCString& aCategory, const bool& aIsFromPrivateWindow,
       const bool& aIsFromChromeContext, const ClonedMessageData& aStack);
 
  private:
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -128,16 +128,17 @@ using mozilla::ContentBlocking::StorageA
 using JSActorMessageKind from "mozilla/dom/JSActor.h";
 using JSActorMessageMeta from "mozilla/dom/PWindowGlobal.h";
 using mozilla::PermissionDelegateHandler::DelegatedPermissionList from "mozilla/PermissionDelegateIPCUtils.h";
 using refcounted class nsILayoutHistoryState from "nsILayoutHistoryState.h";
 using class mozilla::dom::SessionHistoryInfo from "mozilla/dom/SessionHistoryEntry.h";
 using nsPoint from "mozilla/GfxMessageUtils.h";
 using struct mozilla::dom::LoadingSessionHistoryInfo from "mozilla/dom/SessionHistoryEntry.h";
 using mozilla::PDMFactory::MediaCodecsSupported from "PDMFactory.h";
+using mozilla::dom::PerformanceTimingData from "mozilla/dom/PerformanceTiming.h";
 
 union ChromeRegistryItem
 {
     ChromePackage;
     OverrideMapping;
     SubstitutionMapping;
 };
 
@@ -1703,16 +1704,26 @@ parent:
         MaybeDiscardedBrowsingContext aContext);
 
 both:
     async ScriptError(nsString message, nsString sourceName, nsString sourceLine,
                       uint32_t lineNumber, uint32_t colNumber, uint32_t flags,
                       nsCString category, bool privateWindow, uint64_t innerWindowId,
                       bool fromChromeContext);
 
+    /**
+     * Used in fission to report timing data when the parent window is in
+     * another process. Child frame will send data to its ContentParent which
+     * will then identify the ContentParent for the innerWindowId and pass
+     * the data to the correct process.
+     */
+    async ReportFrameTimingData(uint64_t innerWindowId, nsString entryName,
+                                nsString initiatorType,
+                                UniquePtr<PerformanceTimingData> aData);
+
     async CommitBrowsingContextTransaction(MaybeDiscardedBrowsingContext aContext,
                                            BrowsingContextTransaction aTransaction,
                                            uint64_t aEpoch);
 
     async AsyncMessage(nsString aMessage, ClonedMessageData aData);
 
     /**
      * Notify `push-subscription-modified` observers in the parent and child.
--- a/dom/performance/PerformanceMainThread.cpp
+++ b/dom/performance/PerformanceMainThread.cpp
@@ -149,16 +149,22 @@ void PerformanceMainThread::AddEntry(nsI
       PerformanceTimingData::Create(timedChannel, channel, 0, initiatorType,
                                     entryName));
   if (!performanceTimingData) {
     return;
   }
   AddRawEntry(std::move(performanceTimingData), initiatorType, entryName);
 }
 
+void PerformanceMainThread::AddEntry(const nsString& entryName,
+                                     const nsString& initiatorType,
+                                     UniquePtr<PerformanceTimingData>&& aData) {
+  AddRawEntry(std::move(aData), initiatorType, entryName);
+}
+
 void PerformanceMainThread::AddRawEntry(UniquePtr<PerformanceTimingData> aData,
                                         const nsAString& aInitiatorType,
                                         const nsAString& aEntryName) {
   // The PerformanceResourceTiming object will use the PerformanceTimingData
   // object to get all the required timings.
   auto entry =
       MakeRefPtr<PerformanceResourceTiming>(std::move(aData), this, aEntryName);
   entry->SetInitiatorType(aInitiatorType);
--- a/dom/performance/PerformanceMainThread.h
+++ b/dom/performance/PerformanceMainThread.h
@@ -29,16 +29,19 @@ class PerformanceMainThread final : publ
   PerformanceStorage* AsPerformanceStorage() override { return this; }
 
   virtual PerformanceTiming* Timing() override;
 
   virtual PerformanceNavigation* Navigation() override;
 
   virtual void AddEntry(nsIHttpChannel* channel,
                         nsITimedChannel* timedChannel) override;
+  virtual void AddEntry(const nsString& entryName,
+                        const nsString& initiatorType,
+                        UniquePtr<PerformanceTimingData>&& aData) override;
 
   void AddRawEntry(UniquePtr<PerformanceTimingData>,
                    const nsAString& aInitiatorType,
                    const nsAString& aEntryName);
   virtual void SetFCPTimingEntry(PerformancePaintTiming* aEntry) override;
 
   TimeStamp CreationTimeStamp() const override;
 
--- a/dom/performance/PerformanceStorage.h
+++ b/dom/performance/PerformanceStorage.h
@@ -18,16 +18,19 @@ namespace dom {
 class PerformanceTimingData;
 
 class PerformanceStorage {
  public:
   NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING
 
   virtual void AddEntry(nsIHttpChannel* aChannel,
                         nsITimedChannel* aTimedChannel) = 0;
+  virtual void AddEntry(const nsString& entryName,
+                        const nsString& initiatorType,
+                        UniquePtr<PerformanceTimingData>&& aData) = 0;
 
  protected:
   virtual ~PerformanceStorage() = default;
 };
 
 }  // namespace dom
 }  // namespace mozilla
 
--- a/dom/performance/PerformanceStorageWorker.h
+++ b/dom/performance/PerformanceStorageWorker.h
@@ -24,17 +24,19 @@ class PerformanceStorageWorker final : p
 
   static already_AddRefed<PerformanceStorageWorker> Create(
       WorkerPrivate* aWorkerPrivate);
 
   void ShutdownOnWorker();
 
   void AddEntry(nsIHttpChannel* aChannel,
                 nsITimedChannel* aTimedChannel) override;
-
+  virtual void AddEntry(const nsString& entryName,
+                        const nsString& initiatorType,
+                        UniquePtr<PerformanceTimingData>&& aData) override {}
   void AddEntryOnWorker(UniquePtr<PerformanceProxyData>&& aData);
 
  private:
   PerformanceStorageWorker();
   ~PerformanceStorageWorker();
 
   Mutex mMutex;
 
--- a/dom/performance/PerformanceTiming.h
+++ b/dom/performance/PerformanceTiming.h
@@ -11,28 +11,34 @@
 #include "mozilla/BasePrincipal.h"
 #include "mozilla/StaticPrefs_dom.h"
 #include "nsContentUtils.h"
 #include "nsDOMNavigationTiming.h"
 #include "nsRFPService.h"
 #include "nsWrapperCache.h"
 #include "Performance.h"
 #include "nsITimedChannel.h"
+#include "mozilla/ipc/IPDLParamTraits.h"
+#include "ipc/IPCMessageUtils.h"
+#include "mozilla/net/nsServerTiming.h"
 
 class nsIHttpChannel;
 
 namespace mozilla {
 namespace dom {
 
 class PerformanceTiming;
 
 class PerformanceTimingData final {
   friend class PerformanceTiming;
+  friend struct mozilla::ipc::IPDLParamTraits<
+      mozilla::dom::PerformanceTimingData>;
 
  public:
+  PerformanceTimingData() = default;  // For deserialization
   // This can return null.
   static PerformanceTimingData* Create(nsITimedChannel* aChannel,
                                        nsIHttpChannel* aHttpChannel,
                                        DOMHighResTimeStamp aZeroTime,
                                        nsAString& aInitiatorType,
                                        nsAString& aEntryName);
 
   PerformanceTimingData(nsITimedChannel* aChannel, nsIHttpChannel* aHttpChannel,
@@ -176,38 +182,38 @@ class PerformanceTimingData final {
   TimeStamp mWorkerStart;
   TimeStamp mWorkerRequestStart;
   TimeStamp mWorkerResponseEnd;
 
   // This is an offset that will be added to each timing ([ms] resolution).
   // There are only 2 possible values: (1) logicaly equal to navigationStart
   // TimeStamp (results are absolute timstamps - wallclock); (2) "0" (results
   // are relative to the navigation start).
-  DOMHighResTimeStamp mZeroTime;
+  DOMHighResTimeStamp mZeroTime = 0;
 
-  DOMHighResTimeStamp mFetchStart;
+  DOMHighResTimeStamp mFetchStart = 0;
 
-  uint64_t mEncodedBodySize;
-  uint64_t mTransferSize;
-  uint64_t mDecodedBodySize;
+  uint64_t mEncodedBodySize = 0;
+  uint64_t mTransferSize = 0;
+  uint64_t mDecodedBodySize = 0;
 
-  uint8_t mRedirectCount;
+  uint8_t mRedirectCount = 0;
 
-  bool mAllRedirectsSameOrigin;
+  bool mAllRedirectsSameOrigin = false;
 
   // If the resourceTiming object should have non-zero redirectStart and
   // redirectEnd attributes. It is false if there were no redirects, or if any
   // of the responses didn't pass the timing-allow-check
-  bool mReportCrossOriginRedirect;
+  bool mReportCrossOriginRedirect = false;
 
-  bool mSecureConnection;
+  bool mSecureConnection = false;
 
-  bool mTimingAllowed;
+  bool mTimingAllowed = false;
 
-  bool mInitialized;
+  bool mInitialized = false;
 };
 
 // Script "performance.timing" object
 class PerformanceTiming final : public nsWrapperCache {
  public:
   /**
    * @param   aPerformance
    *          The performance object (the JS parent).
@@ -403,9 +409,186 @@ class PerformanceTiming final : public n
   RefPtr<Performance> mPerformance;
 
   UniquePtr<PerformanceTimingData> mTimingData;
 };
 
 }  // namespace dom
 }  // namespace mozilla
 
+namespace mozilla {
+namespace ipc {
+
+template <>
+struct IPDLParamTraits<mozilla::dom::PerformanceTimingData> {
+  typedef mozilla::dom::PerformanceTimingData paramType;
+  static void Write(IPC::Message* aMsg, IProtocol* aActor,
+                    const paramType& aParam) {
+    WriteIPDLParam(aMsg, aActor, aParam.mServerTiming);
+    WriteIPDLParam(aMsg, aActor, aParam.mNextHopProtocol);
+    WriteIPDLParam(aMsg, aActor, aParam.mAsyncOpen);
+    WriteIPDLParam(aMsg, aActor, aParam.mRedirectStart);
+    WriteIPDLParam(aMsg, aActor, aParam.mRedirectEnd);
+    WriteIPDLParam(aMsg, aActor, aParam.mDomainLookupStart);
+    WriteIPDLParam(aMsg, aActor, aParam.mDomainLookupEnd);
+    WriteIPDLParam(aMsg, aActor, aParam.mConnectStart);
+    WriteIPDLParam(aMsg, aActor, aParam.mSecureConnectionStart);
+    WriteIPDLParam(aMsg, aActor, aParam.mConnectEnd);
+    WriteIPDLParam(aMsg, aActor, aParam.mRequestStart);
+    WriteIPDLParam(aMsg, aActor, aParam.mResponseStart);
+    WriteIPDLParam(aMsg, aActor, aParam.mCacheReadStart);
+    WriteIPDLParam(aMsg, aActor, aParam.mResponseEnd);
+    WriteIPDLParam(aMsg, aActor, aParam.mCacheReadEnd);
+    WriteIPDLParam(aMsg, aActor, aParam.mWorkerStart);
+    WriteIPDLParam(aMsg, aActor, aParam.mWorkerRequestStart);
+    WriteIPDLParam(aMsg, aActor, aParam.mWorkerResponseEnd);
+    WriteIPDLParam(aMsg, aActor, aParam.mZeroTime);
+    WriteIPDLParam(aMsg, aActor, aParam.mFetchStart);
+    WriteIPDLParam(aMsg, aActor, aParam.mEncodedBodySize);
+    WriteIPDLParam(aMsg, aActor, aParam.mTransferSize);
+    WriteIPDLParam(aMsg, aActor, aParam.mDecodedBodySize);
+    WriteIPDLParam(aMsg, aActor, aParam.mRedirectCount);
+    WriteIPDLParam(aMsg, aActor, aParam.mAllRedirectsSameOrigin);
+    WriteIPDLParam(aMsg, aActor, aParam.mReportCrossOriginRedirect);
+    WriteIPDLParam(aMsg, aActor, aParam.mSecureConnection);
+    WriteIPDLParam(aMsg, aActor, aParam.mTimingAllowed);
+    WriteIPDLParam(aMsg, aActor, aParam.mInitialized);
+  }
+
+  static bool Read(const IPC::Message* aMsg, PickleIterator* aIter,
+                   IProtocol* aActor, paramType* aResult) {
+    if (!ReadIPDLParam(aMsg, aIter, aActor, &aResult->mServerTiming)) {
+      return false;
+    }
+    if (!ReadIPDLParam(aMsg, aIter, aActor, &aResult->mNextHopProtocol)) {
+      return false;
+    }
+    if (!ReadIPDLParam(aMsg, aIter, aActor, &aResult->mAsyncOpen)) {
+      return false;
+    }
+    if (!ReadIPDLParam(aMsg, aIter, aActor, &aResult->mRedirectStart)) {
+      return false;
+    }
+    if (!ReadIPDLParam(aMsg, aIter, aActor, &aResult->mRedirectEnd)) {
+      return false;
+    }
+    if (!ReadIPDLParam(aMsg, aIter, aActor, &aResult->mDomainLookupStart)) {
+      return false;
+    }
+    if (!ReadIPDLParam(aMsg, aIter, aActor, &aResult->mDomainLookupEnd)) {
+      return false;
+    }
+    if (!ReadIPDLParam(aMsg, aIter, aActor, &aResult->mConnectStart)) {
+      return false;
+    }
+    if (!ReadIPDLParam(aMsg, aIter, aActor, &aResult->mSecureConnectionStart)) {
+      return false;
+    }
+    if (!ReadIPDLParam(aMsg, aIter, aActor, &aResult->mConnectEnd)) {
+      return false;
+    }
+    if (!ReadIPDLParam(aMsg, aIter, aActor, &aResult->mRequestStart)) {
+      return false;
+    }
+    if (!ReadIPDLParam(aMsg, aIter, aActor, &aResult->mResponseStart)) {
+      return false;
+    }
+    if (!ReadIPDLParam(aMsg, aIter, aActor, &aResult->mCacheReadStart)) {
+      return false;
+    }
+    if (!ReadIPDLParam(aMsg, aIter, aActor, &aResult->mResponseEnd)) {
+      return false;
+    }
+    if (!ReadIPDLParam(aMsg, aIter, aActor, &aResult->mCacheReadEnd)) {
+      return false;
+    }
+    if (!ReadIPDLParam(aMsg, aIter, aActor, &aResult->mWorkerStart)) {
+      return false;
+    }
+    if (!ReadIPDLParam(aMsg, aIter, aActor, &aResult->mWorkerRequestStart)) {
+      return false;
+    }
+    if (!ReadIPDLParam(aMsg, aIter, aActor, &aResult->mWorkerResponseEnd)) {
+      return false;
+    }
+    if (!ReadIPDLParam(aMsg, aIter, aActor, &aResult->mZeroTime)) {
+      return false;
+    }
+    if (!ReadIPDLParam(aMsg, aIter, aActor, &aResult->mFetchStart)) {
+      return false;
+    }
+    if (!ReadIPDLParam(aMsg, aIter, aActor, &aResult->mEncodedBodySize)) {
+      return false;
+    }
+    if (!ReadIPDLParam(aMsg, aIter, aActor, &aResult->mTransferSize)) {
+      return false;
+    }
+    if (!ReadIPDLParam(aMsg, aIter, aActor, &aResult->mDecodedBodySize)) {
+      return false;
+    }
+    if (!ReadIPDLParam(aMsg, aIter, aActor, &aResult->mRedirectCount)) {
+      return false;
+    }
+    if (!ReadIPDLParam(aMsg, aIter, aActor,
+                       &aResult->mAllRedirectsSameOrigin)) {
+      return false;
+    }
+    if (!ReadIPDLParam(aMsg, aIter, aActor,
+                       &aResult->mReportCrossOriginRedirect)) {
+      return false;
+    }
+    if (!ReadIPDLParam(aMsg, aIter, aActor, &aResult->mSecureConnection)) {
+      return false;
+    }
+    if (!ReadIPDLParam(aMsg, aIter, aActor, &aResult->mTimingAllowed)) {
+      return false;
+    }
+    if (!ReadIPDLParam(aMsg, aIter, aActor, &aResult->mInitialized)) {
+      return false;
+    }
+    return true;
+  }
+};
+
+template <>
+struct IPDLParamTraits<nsCOMPtr<nsIServerTiming>> {
+  typedef nsCOMPtr<nsIServerTiming> paramType;
+  static void Write(IPC::Message* aMsg, IProtocol* aActor,
+                    const paramType& aParam) {
+    nsAutoCString name;
+    Unused << aParam->GetName(name);
+    double duration = 0;
+    Unused << aParam->GetDuration(&duration);
+    nsAutoCString description;
+    Unused << aParam->GetDescription(description);
+    WriteIPDLParam(aMsg, aActor, name);
+    WriteIPDLParam(aMsg, aActor, duration);
+    WriteIPDLParam(aMsg, aActor, description);
+  }
+
+  static bool Read(const IPC::Message* aMsg, PickleIterator* aIter,
+                   IProtocol* aActor, paramType* aResult) {
+    nsAutoCString name;
+    double duration;
+    nsAutoCString description;
+    if (!ReadIPDLParam(aMsg, aIter, aActor, &name)) {
+      return false;
+    }
+    if (!ReadIPDLParam(aMsg, aIter, aActor, &duration)) {
+      return false;
+    }
+    if (!ReadIPDLParam(aMsg, aIter, aActor, &description)) {
+      return false;
+    }
+
+    RefPtr<nsServerTiming> timing = new nsServerTiming();
+    timing->SetName(name);
+    timing->SetDuration(duration);
+    timing->SetDescription(description);
+    *aResult = timing;
+    return true;
+  }
+};
+
+}  // namespace ipc
+}  // namespace mozilla
+
 #endif  // mozilla_dom_PerformanceTiming_h
--- a/dom/tests/mochitest/general/mochitest.ini
+++ b/dom/tests/mochitest/general/mochitest.ini
@@ -114,17 +114,16 @@ skip-if = verify
 [test_picture_apng.html]
 [test_picture_mutations.html]
 [test_pointerPreserves3D.html]
 [test_pointerPreserves3DClip.html]
 [test_pointerPreserves3DPerspective.html]
 [test_resource_timing.html]
 skip-if = verify
 [test_resource_timing_cross_origin.html]
-skip-if = fission # bug 1658097
 [test_resource_timing_frameset.html]
 [test_selectevents.html]
 skip-if = toolkit == 'android' # bug 1627523
 [test_showModalDialog_removed.html]
 [test_storagePermissionsAccept.html]
 [test_storagePermissionsLimitForeign.html]
 [test_storagePermissionsReject.html]
 [test_storagePermissionsRejectForeign.html]
--- a/netwerk/protocol/http/HttpBaseChannel.cpp
+++ b/netwerk/protocol/http/HttpBaseChannel.cpp
@@ -83,16 +83,17 @@
 #include "nsServerTiming.h"
 #include "nsStreamListenerWrapper.h"
 #include "nsStreamUtils.h"
 #include "nsThreadUtils.h"
 #include "nsURLHelper.h"
 #include "mozilla/RemoteLazyInputStreamChild.h"
 #include "mozilla/RemoteLazyInputStreamUtils.h"
 #include "mozilla/net/SFVService.h"
+#include "mozilla/dom/ContentChild.h"
 
 namespace mozilla {
 namespace net {
 
 static bool IsHeaderBlacklistedForRedirectCopy(nsHttpAtom const& aHeader) {
   // IMPORTANT: keep this list ASCII-code sorted
   static nsHttpAtom const* blackList[] = {&nsHttp::Accept,
                                           &nsHttp::Accept_Encoding,
@@ -4826,20 +4827,47 @@ mozilla::dom::PerformanceStorage* HttpBa
   // performance.
   if (XRE_IsE10sParentProcess()) {
     return nullptr;
   }
   return mLoadInfo->GetPerformanceStorage();
 }
 
 void HttpBaseChannel::MaybeReportTimingData() {
+  if (XRE_IsE10sParentProcess()) {
+    return;
+  }
+
   mozilla::dom::PerformanceStorage* documentPerformance =
       GetPerformanceStorage();
   if (documentPerformance) {
     documentPerformance->AddEntry(this, this);
+    return;
+  }
+
+  if (!nsGlobalWindowInner::GetInnerWindowWithId(
+          mLoadInfo->GetInnerWindowID())) {
+    // The inner window is in a different process.
+    dom::ContentChild* child = dom::ContentChild::GetSingleton();
+
+    if (!child) {
+      return;
+    }
+    nsAutoString initiatorType;
+    nsAutoString entryName;
+
+    UniquePtr<dom::PerformanceTimingData> performanceTimingData(
+        dom::PerformanceTimingData::Create(this, this, 0, initiatorType,
+                                           entryName));
+    if (!performanceTimingData) {
+      return;
+    }
+    child->SendReportFrameTimingData(mLoadInfo->GetInnerWindowID(), entryName,
+                                     initiatorType,
+                                     std::move(performanceTimingData));
   }
 }
 
 NS_IMETHODIMP
 HttpBaseChannel::SetReportResourceTiming(bool enabled) {
   mReportTiming = enabled;
   return NS_OK;
 }