Merge autoland to mozilla-central. a=merge
authorCosmin Sabou <csabou@mozilla.com>
Sat, 23 Feb 2019 23:38:17 +0200
changeset 518619 98e5989a28405532380ead065a65cd829730dd6d
parent 518607 9f20371d98ecbafed01fd8a3836d570e7f1e09b7 (current diff)
parent 518618 95d0c10a390cee0b2b10bbc8452960754d88607a (diff)
child 518621 492e4409f468f4841def795627356148d0bb7347
push id10862
push userffxbld-merge
push dateMon, 11 Mar 2019 13:01:11 +0000
treeherdermozilla-beta@a2e7f5c935da [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone67.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
Merge autoland to mozilla-central. a=merge
--- a/browser/components/preferences/in-content/privacy.js
+++ b/browser/components/preferences/in-content/privacy.js
@@ -1088,21 +1088,16 @@ var gPrivacyPane = {
    * Displays the notifications exceptions dialog where specific site notification
    * preferences can be set.
    */
   showNotificationExceptions() {
     let params = { permissionType: "desktop-notification" };
 
     gSubDialog.open("chrome://browser/content/preferences/sitePermissions.xul",
       "resizable=yes", params);
-
-    try {
-      Services.telemetry
-        .getHistogramById("WEB_NOTIFICATION_EXCEPTIONS_OPENED").add();
-    } catch (e) { }
   },
 
 
   // MEDIA
 
   blockAutoplayReadPrefs() {
     let blocked =
       Preferences.get("media.autoplay.default").value == Ci.nsIAutoplay.BLOCKED;
--- a/browser/locales/en-US/browser/pageInfo.ftl
+++ b/browser/locales/en-US/browser/pageInfo.ftl
@@ -114,19 +114,16 @@ security-view-privacy-viewpasswords =
     .label = View Saved Passwords
     .accesskey = w
 security-view-technical =
     .value = Technical Details
 
 help-button =
     .label = Help
 
-security-site-data-cookies-only = Yes, cookies
-security-site-data-no = No
-
 ## These strings are used to tell the user if the website is storing cookies
 ## and data on the users computer in the security tab of pageInfo
 ## Variables:
 ##   $value (number) - Amount of data being stored
 ##   $unit (string) - The unit of data being stored (Usually KB)
 security-site-data-cookies = Yes, cookies and { $value } { $unit } of site data
 security-site-data-only = Yes, { $value } { $unit } of site data
 
new file mode 100644
--- /dev/null
+++ b/build/build-clang/android-mangling-error.patch
@@ -0,0 +1,34 @@
+Workaround segfault in clang's mangling code that is tickled when
+attempting to mangle the declaration:
+ std:__ndk1::__find_detail::__find_exactly_one_checked::__matches
+in the <tuple> header in the Android NDK.
+This codepath is exercised by MozsearchIndexer.cpp (the searchfox
+indexer) when indexing on Android. See also
+https://bugs.llvm.org/show_bug.cgi?id=40747
+
+diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
+index 2dc04f2f3d8..054fc27003d 100644
+--- a/clang/lib/AST/ItaniumMangle.cpp
++++ b/clang/lib/AST/ItaniumMangle.cpp
+@@ -3495,16 +3495,21 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) {
+   //              ::= <expr-primary>
+   // <expr-primary> ::= L <type> <value number> E    # integer literal
+   //                ::= L <type <value float> E      # floating literal
+   //                ::= L <mangled-name> E           # external name
+   //                ::= fpT                          # 'this' expression
+   QualType ImplicitlyConvertedToType;
+ 
+ recurse:
++  if (!E) {
++    Out << "MOZ_WE_HACKED_AROUND_BUG_1500941";
++    return;
++  }
++
+   switch (E->getStmtClass()) {
+   case Expr::NoStmtClass:
+ #define ABSTRACT_STMT(Type)
+ #define EXPR(Type, Base)
+ #define STMT(Type, Base) \
+   case Expr::Type##Class:
+ #include "clang/AST/StmtNodes.inc"
+     // fallthrough
--- a/build/build-clang/clang-7-linux64.json
+++ b/build/build-clang/clang-7-linux64.json
@@ -14,11 +14,12 @@
     "gcc_dir": "/builds/worker/workspace/build/src/gcc",
     "cc": "/builds/worker/workspace/build/src/gcc/bin/gcc",
     "cxx": "/builds/worker/workspace/build/src/gcc/bin/g++",
     "as": "/builds/worker/workspace/build/src/gcc/bin/gcc",
     "patches": [
       "static-llvm-symbolizer.patch",
       "find_symbolizer_linux.patch",
       "rename_gcov_flush_.patch",
-      "r350774.patch"
+      "r350774.patch",
+      "android-mangling-error.patch"
     ]
 }
--- a/dom/base/ChromeUtils.cpp
+++ b/dom/base/ChromeUtils.cpp
@@ -11,27 +11,32 @@
 #include "jsfriendapi.h"
 #include "WrapperFactory.h"
 
 #include "mozilla/Base64.h"
 #include "mozilla/BasePrincipal.h"
 #include "mozilla/CycleCollectedJSRuntime.h"
 #include "mozilla/PerformanceMetricsCollector.h"
 #include "mozilla/Preferences.h"
+#include "mozilla/ProcInfo.h"
+#include "mozilla/RDDProcessManager.h"
 #include "mozilla/ResultExtensions.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/dom/BrowsingContext.h"
+#include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/IdleDeadline.h"
 #include "mozilla/dom/JSWindowActorService.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/ReportingHeader.h"
 #include "mozilla/dom/UnionTypes.h"
 #include "mozilla/dom/WindowBinding.h"  // For IdleRequestCallback/Options
+#include "mozilla/gfx/GPUProcessManager.h"
 #include "mozilla/net/UrlClassifierFeatureFactory.h"
 #include "IOActivityMonitor.h"
+#include "nsIOService.h"
 #include "nsThreadUtils.h"
 #include "mozJSComponentLoader.h"
 #include "GeckoProfiler.h"
 #include "nsIException.h"
 
 namespace mozilla {
 namespace dom {
 
@@ -637,16 +642,185 @@ static bool DefineGetter(JSContext* aCx,
   auto runtime = CycleCollectedJSRuntime::Get();
   MOZ_ASSERT(runtime);
 
   runtime->ClearRecentDevError();
 }
 #endif  // NIGHTLY_BUILD
 
 /* static */
+already_AddRefed<Promise> ChromeUtils::RequestProcInfo(GlobalObject& aGlobal,
+                                                       ErrorResult& aRv) {
+  // This function will use IPDL to enable threads info on macOS
+  // see https://bugzilla.mozilla.org/show_bug.cgi?id=1529023
+  if (!XRE_IsParentProcess()) {
+    aRv.Throw(NS_ERROR_FAILURE);
+    return nullptr;
+  }
+  // Creating a JS promise
+  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
+  MOZ_ASSERT(global);
+  RefPtr<Promise> domPromise = Promise::Create(global, aRv);
+  if (NS_WARN_IF(aRv.Failed())) {
+    return nullptr;
+  }
+  MOZ_ASSERT(domPromise);
+
+  base::ProcessId parentPid = base::GetCurrentProcId();
+  RefPtr<nsISerialEventTarget> target =
+      global->EventTargetFor(TaskCategory::Performance);
+
+  // Getting the parent proc info
+  mozilla::GetProcInfo(parentPid, 0, mozilla::ProcType::Browser)
+      ->Then(
+          target, __func__,
+          [target, domPromise, parentPid](ProcInfo aParentInfo) {
+            // Iterate over each child process to build an array of promises.
+            nsTArray<ContentParent*> parents;
+            ContentParent::GetAll(parents);
+            nsTArray<RefPtr<ProcInfoPromise>> promises;
+            for (ContentParent* contentParent : parents) {
+              // Getting the child process id.
+              int32_t childPid = contentParent->Pid();
+              if (childPid == -1) {
+                continue;
+              }
+              // Converting the Content Type into a ProcType
+              nsAutoString processType;
+              processType.Assign(contentParent->GetRemoteType());
+              mozilla::ProcType type = mozilla::ProcType::Unknown;
+              if (processType.EqualsLiteral(DEFAULT_REMOTE_TYPE)) {
+                type = mozilla::ProcType::Web;
+              } else if (processType.EqualsLiteral(FILE_REMOTE_TYPE)) {
+                type = mozilla::ProcType::File;
+              } else if (processType.EqualsLiteral(EXTENSION_REMOTE_TYPE)) {
+                type = mozilla::ProcType::Extension;
+              } else if (processType.EqualsLiteral(PRIVILEGED_REMOTE_TYPE)) {
+                type = mozilla::ProcType::Privileged;
+              } else if (processType.EqualsLiteral(
+                             LARGE_ALLOCATION_REMOTE_TYPE)) {
+                type = mozilla::ProcType::WebLargeAllocation;
+              }
+
+              promises.AppendElement(mozilla::GetProcInfo(
+                  (base::ProcessId)childPid, contentParent->ChildID(), type));
+            }
+
+            // Getting the Socket Process
+            int32_t SocketPid = net::gIOService->SocketProcessPid();
+            if (SocketPid != 0) {
+              promises.AppendElement(mozilla::GetProcInfo(
+                  (base::ProcessId)SocketPid, 0, mozilla::ProcType::Socket));
+            }
+
+            // Getting the GPU and RDD processes on supported platforms
+            gfx::GPUProcessManager* pm = gfx::GPUProcessManager::Get();
+            if (pm) {
+              base::ProcessId GpuPid = pm->GPUProcessPid();
+              if (GpuPid != -1) {
+                promises.AppendElement(
+                    mozilla::GetProcInfo(GpuPid, 0, mozilla::ProcType::Gpu));
+              }
+            }
+            RDDProcessManager* RDDPm = RDDProcessManager::Get();
+            if (RDDPm) {
+              base::ProcessId RDDPid = RDDPm->RDDProcessPid();
+              if (RDDPid != -1) {
+                promises.AppendElement(
+                    mozilla::GetProcInfo(RDDPid, 0, mozilla::ProcType::Rdd));
+              }
+            }
+
+            // two more processes to add: VR and GMP
+            // see https://bugzilla.mozilla.org/show_bug.cgi?id=1529022
+
+            auto ProcInfoResolver =
+                [domPromise, parentPid, parentInfo = aParentInfo](
+                    const nsTArray<ProcInfo>& aChildrenInfo) {
+                  mozilla::dom::ParentProcInfoDictionary procInfo;
+                  // parent, basic info.
+                  procInfo.mPid = parentPid;
+                  procInfo.mFilename.Assign(parentInfo.filename);
+                  procInfo.mType = mozilla::dom::ProcType::Browser;
+                  procInfo.mVirtualMemorySize = parentInfo.virtualMemorySize;
+                  procInfo.mResidentSetSize = parentInfo.residentSetSize;
+                  procInfo.mCpuUser = parentInfo.cpuUser;
+                  procInfo.mCpuKernel = parentInfo.cpuKernel;
+
+                  // parent, threads info.
+                  mozilla::dom::Sequence<mozilla::dom::ThreadInfoDictionary>
+                      threads;
+                  for (const ThreadInfo& entry : parentInfo.threads) {
+                    ThreadInfoDictionary* thread =
+                        threads.AppendElement(fallible);
+                    if (NS_WARN_IF(!thread)) {
+                      domPromise->MaybeReject(NS_ERROR_OUT_OF_MEMORY);
+                      return;
+                    }
+                    thread->mCpuUser = entry.cpuUser;
+                    thread->mCpuKernel = entry.cpuKernel;
+                    thread->mTid = entry.tid;
+                  }
+                  procInfo.mThreads = threads;
+
+                  mozilla::dom::Sequence<mozilla::dom::ChildProcInfoDictionary>
+                      children;
+                  for (const ProcInfo& info : aChildrenInfo) {
+                    ChildProcInfoDictionary* childProcInfo =
+                        children.AppendElement(fallible);
+                    if (NS_WARN_IF(!childProcInfo)) {
+                      domPromise->MaybeReject(NS_ERROR_OUT_OF_MEMORY);
+                      return;
+                    }
+                    // Basic info.
+                    childProcInfo->mChildID = info.childId;
+                    childProcInfo->mType = static_cast<ProcType>(info.type);
+                    childProcInfo->mPid = info.pid;
+                    childProcInfo->mFilename.Assign(info.filename);
+                    childProcInfo->mVirtualMemorySize = info.virtualMemorySize;
+                    childProcInfo->mResidentSetSize = info.residentSetSize;
+                    childProcInfo->mCpuUser = info.cpuUser;
+                    childProcInfo->mCpuKernel = info.cpuKernel;
+
+                    // Threads info.
+                    mozilla::dom::Sequence<mozilla::dom::ThreadInfoDictionary>
+                        threads;
+                    for (const ThreadInfo& entry : info.threads) {
+                      ThreadInfoDictionary* thread =
+                          threads.AppendElement(fallible);
+                      if (NS_WARN_IF(!thread)) {
+                        domPromise->MaybeReject(NS_ERROR_OUT_OF_MEMORY);
+                        return;
+                      }
+                      thread->mCpuUser = entry.cpuUser;
+                      thread->mCpuKernel = entry.cpuKernel;
+                      thread->mTid = entry.tid;
+                      thread->mName.Assign(entry.name);
+                    }
+                    childProcInfo->mThreads = threads;
+                  }
+                  procInfo.mChildren = children;
+                  domPromise->MaybeResolve(procInfo);
+                };  // end of ProcInfoResolver
+
+            ProcInfoPromise::All(target, promises)
+                ->Then(target, __func__, std::move(ProcInfoResolver),
+                       [domPromise](const nsresult aResult) {
+                         domPromise->MaybeReject(aResult);
+                       });  // end of ProcInfoPromise::All
+          },
+          [domPromise](nsresult aRv) {
+            domPromise->MaybeReject(aRv);
+          });  // end of mozilla::GetProcInfo
+
+  // sending back the promise instance
+  return domPromise.forget();
+}
+
+/* static */
 already_AddRefed<Promise> ChromeUtils::RequestPerformanceMetrics(
     GlobalObject& aGlobal, ErrorResult& aRv) {
   MOZ_ASSERT(XRE_IsParentProcess());
 
   // Creating a JS promise
   nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
   MOZ_ASSERT(global);
   RefPtr<Promise> domPromise = Promise::Create(global, aRv);
--- a/dom/base/ChromeUtils.h
+++ b/dom/base/ChromeUtils.h
@@ -136,16 +136,19 @@ class ChromeUtils {
                                   JS::MutableHandleValue aRetval,
                                   ErrorResult& aRv);
 
   static void ClearRecentJSDevError(GlobalObject& aGlobal);
 
   static already_AddRefed<Promise> RequestPerformanceMetrics(
       GlobalObject& aGlobal, ErrorResult& aRv);
 
+  static already_AddRefed<Promise> RequestProcInfo(GlobalObject& aGlobal,
+                                                   ErrorResult& aRv);
+
   static void Import(const GlobalObject& aGlobal, const nsAString& aResourceURI,
                      const Optional<JS::Handle<JSObject*>>& aTargetObj,
                      JS::MutableHandle<JSObject*> aRetval, ErrorResult& aRv);
 
   static void DefineModuleGetter(const GlobalObject& global,
                                  JS::Handle<JSObject*> target,
                                  const nsAString& id,
                                  const nsAString& resourceURI,
--- a/dom/chrome-webidl/ChromeUtils.webidl
+++ b/dom/chrome-webidl/ChromeUtils.webidl
@@ -363,16 +363,22 @@ partial namespace ChromeUtils {
   Promise<sequence<PerformanceInfoDictionary>> requestPerformanceMetrics();
 
   /**
   * Returns a Promise containing a sequence of I/O activities
   */
   [Throws]
   Promise<sequence<IOActivityDataDictionary>> requestIOActivity();
 
+  /**
+  * Returns a Promise containing all processes info
+  */
+  [Throws]
+  Promise<ParentProcInfoDictionary> requestProcInfo();
+
   [ChromeOnly, Throws]
   boolean hasReportingHeaderForOrigin(DOMString aOrigin);
 
   [ChromeOnly]
   PopupBlockerState getPopupControlState();
 
   [ChromeOnly]
   boolean isPopupTokenUnused();
@@ -396,20 +402,72 @@ partial namespace ChromeUtils {
   void unregisterWindowActor(DOMString aName);
 
   [ChromeOnly]
   // aError should a nsresult.
   boolean isClassifierBlockingErrorCode(unsigned long aError);
 };
 
 /**
+ * Holds information about Firefox running processes & threads.
+ *
+ * See widget/ProcInfo.h for fields documentation.
+ */
+enum ProcType {
+ "web",
+ "file",
+ "extension",
+ "privileged",
+ "webLargeAllocation",
+ "gpu",
+ "rdd",
+ "socket",
+ "browser",
+ "unknown"
+};
+
+dictionary ThreadInfoDictionary {
+  long long tid = 0;
+  DOMString name = "";
+  unsigned long long cpuUser = 0;
+  unsigned long long cpuKernel = 0;
+};
+
+dictionary ChildProcInfoDictionary {
+  // System info
+  long long pid = 0;
+  DOMString filename = "";
+  unsigned long long virtualMemorySize = 0;
+  long long residentSetSize = 0;
+  unsigned long long cpuUser = 0;
+  unsigned long long cpuKernel = 0;
+  sequence<ThreadInfoDictionary> threads = [];
+  // Firefox info
+  unsigned long long ChildID = 0;
+  ProcType type = "web";
+};
+
+dictionary ParentProcInfoDictionary {
+  // System info
+  long long pid = 0;
+  DOMString filename = "";
+  unsigned long long virtualMemorySize = 0;
+  long long residentSetSize = 0;
+  unsigned long long cpuUser = 0;
+  unsigned long long cpuKernel = 0;
+  sequence<ThreadInfoDictionary> threads = [];
+  sequence<ChildProcInfoDictionary> children = [];
+  // Firefox info
+  ProcType type = "browser";
+};
+
+/**
  * Dictionaries duplicating IPDL types in dom/ipc/DOMTypes.ipdlh
  * Used by requestPerformanceMetrics
  */
-
 dictionary MediaMemoryInfoDictionary {
   unsigned long long audioSize = 0;
   unsigned long long videoSize = 0;
   unsigned long long resourcesSize = 0;
 };
 
 dictionary MemoryInfoDictionary {
   unsigned long long domDom = 0;
--- a/dom/notification/Notification.cpp
+++ b/dom/notification/Notification.cpp
@@ -618,21 +618,16 @@ void NotificationTelemetryService::Recor
     rv = enumerator->GetNext(getter_AddRefs(supportsPermission));
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return;
     }
     uint32_t capability;
     if (!GetNotificationPermission(supportsPermission, &capability)) {
       continue;
     }
-    if (capability == nsIPermissionManager::DENY_ACTION) {
-      Telemetry::Accumulate(Telemetry::WEB_NOTIFICATION_PERMISSIONS, 0);
-    } else if (capability == nsIPermissionManager::ALLOW_ACTION) {
-      Telemetry::Accumulate(Telemetry::WEB_NOTIFICATION_PERMISSIONS, 1);
-    }
   }
 }
 
 bool NotificationTelemetryService::GetNotificationPermission(
     nsISupports* aSupports, uint32_t* aCapability) {
   nsCOMPtr<nsIPermission> permission = do_QueryInterface(aSupports);
   if (!permission) {
     return false;
@@ -1124,30 +1119,26 @@ class NotificationClickWorkerRunnable fi
 };
 
 NS_IMETHODIMP
 NotificationObserver::Observe(nsISupports* aSubject, const char* aTopic,
                               const char16_t* aData) {
   AssertIsOnMainThread();
 
   if (!strcmp("alertdisablecallback", aTopic)) {
-    Telemetry::Accumulate(Telemetry::WEB_NOTIFICATION_MENU, 1);
     if (XRE_IsParentProcess()) {
       return Notification::RemovePermission(mPrincipal);
     }
     // Permissions can't be removed from the content process. Send a message
     // to the parent; `ContentParent::RecvDisableNotifications` will call
     // `RemovePermission`.
     ContentChild::GetSingleton()->SendDisableNotifications(
         IPC::Principal(mPrincipal));
     return NS_OK;
-  } else if (!strcmp("alertclickcallback", aTopic)) {
-    Telemetry::Accumulate(Telemetry::WEB_NOTIFICATION_CLICKED, 1);
   } else if (!strcmp("alertsettingscallback", aTopic)) {
-    Telemetry::Accumulate(Telemetry::WEB_NOTIFICATION_MENU, 2);
     if (XRE_IsParentProcess()) {
       return Notification::OpenSettings(mPrincipal);
     }
     // `ContentParent::RecvOpenNotificationSettings` notifies observers in the
     // parent process.
     ContentChild::GetSingleton()->SendOpenNotificationSettings(
         IPC::Principal(mPrincipal));
     return NS_OK;
@@ -1155,21 +1146,16 @@ NotificationObserver::Observe(nsISupport
     RefPtr<NotificationTelemetryService> telemetry =
         NotificationTelemetryService::GetInstance();
     if (telemetry) {
       // Record whether "do not disturb" is supported after the first
       // notification, to account for falling back to XUL alerts.
       telemetry->RecordDNDSupported();
     }
     Unused << NS_WARN_IF(NS_FAILED(AdjustPushQuota(aTopic)));
-
-    if (!strcmp("alertshow", aTopic)) {
-      // Record notifications actually shown (e.g. don't count if DND is on).
-      Telemetry::Accumulate(Telemetry::WEB_NOTIFICATION_SHOWN, 1);
-    }
   }
 
   return mObserver->Observe(aSubject, aTopic, aData);
 }
 
 nsresult NotificationObserver::AdjustPushQuota(const char* aTopic) {
   nsCOMPtr<nsIPushQuotaManager> pushQuotaManager =
       do_GetService("@mozilla.org/push/Service;1");
--- a/gfx/gl/GLContext.cpp
+++ b/gfx/gl/GLContext.cpp
@@ -829,38 +829,37 @@ bool GLContext::InitImpl() {
 
   raw_fGetIntegerv(LOCAL_GL_VIEWPORT, mViewportRect);
   raw_fGetIntegerv(LOCAL_GL_SCISSOR_BOX, mScissorRect);
   raw_fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
   raw_fGetIntegerv(LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE, &mMaxCubeMapTextureSize);
   raw_fGetIntegerv(LOCAL_GL_MAX_RENDERBUFFER_SIZE, &mMaxRenderbufferSize);
   raw_fGetIntegerv(LOCAL_GL_MAX_VIEWPORT_DIMS, mMaxViewportDims);
 
+  if (mWorkAroundDriverBugs) {
 #ifdef XP_MACOSX
-  if (mWorkAroundDriverBugs && nsCocoaFeatures::OSXVersionMajor() == 10 &&
-      nsCocoaFeatures::OSXVersionMinor() < 12) {
-    if (mVendor == GLVendor::Intel) {
-      // see bug 737182 for 2D textures, bug 684882 for cube map textures.
-      mMaxTextureSize = std::min(mMaxTextureSize, 4096);
-      mMaxCubeMapTextureSize = std::min(mMaxCubeMapTextureSize, 512);
-      // for good measure, we align renderbuffers on what we do for 2D textures
-      mMaxRenderbufferSize = std::min(mMaxRenderbufferSize, 4096);
-      mNeedsTextureSizeChecks = true;
-    } else if (mVendor == GLVendor::NVIDIA) {
-      // See bug 879656.  8192 fails, 8191 works.
-      mMaxTextureSize = std::min(mMaxTextureSize, 8191);
-      mMaxRenderbufferSize = std::min(mMaxRenderbufferSize, 8191);
-
-      // Part of the bug 879656, but it also doesn't hurt the 877949
-      mNeedsTextureSizeChecks = true;
+    if (!nsCocoaFeatures::IsAtLeastVersion(10, 12)) {
+      if (mVendor == GLVendor::Intel) {
+        // see bug 737182 for 2D textures, bug 684882 for cube map textures.
+        mMaxTextureSize = std::min(mMaxTextureSize, 4096);
+        mMaxCubeMapTextureSize = std::min(mMaxCubeMapTextureSize, 512);
+        // for good measure, we align renderbuffers on what we do for 2D textures
+        mMaxRenderbufferSize = std::min(mMaxRenderbufferSize, 4096);
+        mNeedsTextureSizeChecks = true;
+      } else if (mVendor == GLVendor::NVIDIA) {
+        // See bug 879656.  8192 fails, 8191 works.
+        mMaxTextureSize = std::min(mMaxTextureSize, 8191);
+        mMaxRenderbufferSize = std::min(mMaxRenderbufferSize, 8191);
+
+        // Part of the bug 879656, but it also doesn't hurt the 877949
+        mNeedsTextureSizeChecks = true;
+      }
     }
-  }
 #endif
 #ifdef MOZ_X11
-  if (mWorkAroundDriverBugs) {
     if (mVendor == GLVendor::Nouveau) {
       // see bug 814716. Clamp MaxCubeMapTextureSize at 2K for Nouveau.
       mMaxCubeMapTextureSize = std::min(mMaxCubeMapTextureSize, 2048);
       mNeedsTextureSizeChecks = true;
     } else if (mVendor == GLVendor::Intel) {
       // Bug 1199923. Driver seems to report a larger max size than
       // actually supported.
       mMaxTextureSize /= 2;
@@ -869,44 +868,43 @@ bool GLContext::InitImpl() {
     }
     // Bug 1367570. Explicitly set vertex attributes [1,3] to opaque
     // black because Nvidia doesn't do it for us.
     if (mVendor == GLVendor::NVIDIA) {
       for (size_t i = 1; i <= 3; ++i) {
         mSymbols.fVertexAttrib4f(i, 0, 0, 0, 1);
       }
     }
-  }
 #endif
-  if (mWorkAroundDriverBugs && Renderer() == GLRenderer::AdrenoTM420) {
-    // see bug 1194923. Calling glFlush before glDeleteFramebuffers
-    // prevents occasional driver crash.
-    mNeedsFlushBeforeDeleteFB = true;
-  }
+    if (Renderer() == GLRenderer::AdrenoTM420) {
+      // see bug 1194923. Calling glFlush before glDeleteFramebuffers
+      // prevents occasional driver crash.
+      mNeedsFlushBeforeDeleteFB = true;
+    }
 #ifdef MOZ_WIDGET_ANDROID
-  if (mWorkAroundDriverBugs &&
-      (Renderer() == GLRenderer::AdrenoTM305 ||
-       Renderer() == GLRenderer::AdrenoTM320 ||
-       Renderer() == GLRenderer::AdrenoTM330) &&
-      jni::GetAPIVersion() < 21) {
-    // Bug 1164027. Driver crashes when functions such as
-    // glTexImage2D fail due to virtual memory exhaustion.
-    mTextureAllocCrashesOnMapFailure = true;
-  }
+    if ((Renderer() == GLRenderer::AdrenoTM305 ||
+         Renderer() == GLRenderer::AdrenoTM320 ||
+         Renderer() == GLRenderer::AdrenoTM330) &&
+        jni::GetAPIVersion() < 21) {
+      // Bug 1164027. Driver crashes when functions such as
+      // glTexImage2D fail due to virtual memory exhaustion.
+      mTextureAllocCrashesOnMapFailure = true;
+    }
 #endif
 #if MOZ_WIDGET_ANDROID
-  if (mWorkAroundDriverBugs && Renderer() == GLRenderer::SGX540 &&
-      jni::GetAPIVersion() <= 15) {
-    // Bug 1288446. Driver sometimes crashes when uploading data to a
-    // texture if the render target has changed since the texture was
-    // rendered from. Calling glCheckFramebufferStatus after
-    // glFramebufferTexture2D prevents the crash.
-    mNeedsCheckAfterAttachTextureToFb = true;
+    if (Renderer() == GLRenderer::SGX540 &&
+        jni::GetAPIVersion() <= 15) {
+      // Bug 1288446. Driver sometimes crashes when uploading data to a
+      // texture if the render target has changed since the texture was
+      // rendered from. Calling glCheckFramebufferStatus after
+      // glFramebufferTexture2D prevents the crash.
+      mNeedsCheckAfterAttachTextureToFb = true;
+    }
+#endif
   }
-#endif
 
   if (IsSupported(GLFeature::framebuffer_multisample)) {
     fGetIntegerv(LOCAL_GL_MAX_SAMPLES, (GLint*)&mMaxSamples);
   }
 
   mMaxTexOrRbSize = std::min(mMaxTextureSize, mMaxRenderbufferSize);
 
   ////////////////////////////////////////////////////////////////////////////
@@ -1632,19 +1630,17 @@ void GLContext::InitExtensions() {
     }
 
 #ifdef XP_MACOSX
     // Bug 1009642: On OSX Mavericks (10.9), the driver for Intel HD
     // 3000 appears to be buggy WRT updating sub-images of S3TC
     // textures with glCompressedTexSubImage2D. Works on Intel HD 4000
     // and Intel HD 5000/Iris that I tested.
     // Bug 1124996: Appears to be the same on OSX Yosemite (10.10)
-    if (nsCocoaFeatures::OSXVersionMajor() == 10 &&
-        nsCocoaFeatures::OSXVersionMinor() >= 9 &&
-        Renderer() == GLRenderer::IntelHD3000) {
+    if (Renderer() == GLRenderer::IntelHD3000) {
       MarkExtensionUnsupported(EXT_texture_compression_s3tc);
     }
 
     // OSX supports EXT_texture_sRGB in Legacy contexts, but not in Core
     // contexts. Though EXT_texture_sRGB was included into GL2.1, it *excludes*
     // the interactions with s3tc. Strictly speaking, you must advertize support
     // for EXT_texture_sRGB in order to allow for srgb+s3tc on desktop GL. The
     // omission of EXT_texture_sRGB in OSX Core contexts appears to be a bug.
--- a/js/src/builtin/DataViewObject.cpp
+++ b/js/src/builtin/DataViewObject.cpp
@@ -308,16 +308,24 @@ template <>
 struct DataToRepType<int32_t> {
   typedef uint32_t result;
 };
 template <>
 struct DataToRepType<uint32_t> {
   typedef uint32_t result;
 };
 template <>
+struct DataToRepType<int64_t> {
+  typedef uint64_t result;
+};
+template <>
+struct DataToRepType<uint64_t> {
+  typedef uint64_t result;
+};
+template <>
 struct DataToRepType<float> {
   typedef uint32_t result;
 };
 template <>
 struct DataToRepType<double> {
   typedef uint64_t result;
 };
 
@@ -414,44 +422,68 @@ static inline bool WebIDLCast(JSContext*
   // Technically, the behavior of assigning an out of range value to a signed
   // variable is undefined. In practice, compilers seem to do what we want
   // without issuing any warnings.
   *out = static_cast<NativeType>(temp);
   return true;
 }
 
 template <>
+inline bool WebIDLCast<int64_t>(JSContext* cx, HandleValue value,
+                                int64_t* out) {
+  RootedBigInt bi(cx, ToBigInt(cx, value));
+  if (!bi) {
+    return false;
+  }
+  *out = BigInt::toInt64(bi);
+  return true;
+}
+
+template <>
+inline bool WebIDLCast<uint64_t>(JSContext* cx, HandleValue value,
+                                 uint64_t* out) {
+  RootedBigInt bi(cx, ToBigInt(cx, value));
+  if (!bi) {
+    return false;
+  }
+  *out = BigInt::toUint64(bi);
+  return true;
+}
+
+template <>
 inline bool WebIDLCast<float>(JSContext* cx, HandleValue value, float* out) {
   double temp;
   if (!ToNumber(cx, value, &temp)) {
     return false;
   }
   *out = static_cast<float>(temp);
   return true;
 }
 
 template <>
 inline bool WebIDLCast<double>(JSContext* cx, HandleValue value, double* out) {
   return ToNumber(cx, value, out);
 }
 
+// https://tc39.github.io/ecma262/#sec-setviewvalue
+// SetViewValue ( view, requestIndex, isLittleEndian, type, value )
 template <typename NativeType>
 /* static */ bool DataViewObject::write(JSContext* cx,
                                         Handle<DataViewObject*> obj,
                                         const CallArgs& args) {
   // Steps 1-2. done by the caller
   // Step 3. unnecessary assert
 
   // Step 4.
   uint64_t getIndex;
   if (!ToIndex(cx, args.get(0), &getIndex)) {
     return false;
   }
 
-  // Step 5. Should just call ToNumber (unobservable)
+  // Step 5. Extended by the BigInt proposal to call either ToBigInt or ToNumber
   NativeType value;
   if (!WebIDLCast(cx, args.get(1), &value)) {
     return false;
   }
 
 #ifdef JS_MORE_DETERMINISTIC
   // See the comment in ElementSpecific::doubleToNative.
   if (TypeIsFloatingPoint<NativeType>()) {
@@ -597,16 +629,68 @@ bool DataViewObject::getUint32Impl(JSCon
   return true;
 }
 
 bool DataViewObject::fun_getUint32(JSContext* cx, unsigned argc, Value* vp) {
   CallArgs args = CallArgsFromVp(argc, vp);
   return CallNonGenericMethod<is, getUint32Impl>(cx, args);
 }
 
+// BigInt proposal 7.26
+// DataView.prototype.getBigInt64 ( byteOffset [ , littleEndian ] )
+bool DataViewObject::getBigInt64Impl(JSContext* cx, const CallArgs& args) {
+  MOZ_ASSERT(is(args.thisv()));
+
+  Rooted<DataViewObject*> thisView(
+      cx, &args.thisv().toObject().as<DataViewObject>());
+
+  int64_t val;
+  if (!read(cx, thisView, args, &val)) {
+    return false;
+  }
+
+  BigInt* bi = BigInt::createFromInt64(cx, val);
+  if (!bi) {
+    return false;
+  }
+  args.rval().setBigInt(bi);
+  return true;
+}
+
+bool DataViewObject::fun_getBigInt64(JSContext* cx, unsigned argc, Value* vp) {
+  CallArgs args = CallArgsFromVp(argc, vp);
+  return CallNonGenericMethod<is, getBigInt64Impl>(cx, args);
+}
+
+// BigInt proposal 7.27
+// DataView.prototype.getBigUint64 ( byteOffset [ , littleEndian ] )
+bool DataViewObject::getBigUint64Impl(JSContext* cx, const CallArgs& args) {
+  MOZ_ASSERT(is(args.thisv()));
+
+  Rooted<DataViewObject*> thisView(
+      cx, &args.thisv().toObject().as<DataViewObject>());
+
+  int64_t val;
+  if (!read(cx, thisView, args, &val)) {
+    return false;
+  }
+
+  BigInt* bi = BigInt::createFromUint64(cx, val);
+  if (!bi) {
+    return false;
+  }
+  args.rval().setBigInt(bi);
+  return true;
+}
+
+bool DataViewObject::fun_getBigUint64(JSContext* cx, unsigned argc, Value* vp) {
+  CallArgs args = CallArgsFromVp(argc, vp);
+  return CallNonGenericMethod<is, getBigUint64Impl>(cx, args);
+}
+
 bool DataViewObject::getFloat32Impl(JSContext* cx, const CallArgs& args) {
   MOZ_ASSERT(is(args.thisv()));
 
   Rooted<DataViewObject*> thisView(
       cx, &args.thisv().toObject().as<DataViewObject>());
 
   float val;
   if (!read(cx, thisView, args, &val)) {
@@ -745,16 +829,56 @@ bool DataViewObject::setUint32Impl(JSCon
   return true;
 }
 
 bool DataViewObject::fun_setUint32(JSContext* cx, unsigned argc, Value* vp) {
   CallArgs args = CallArgsFromVp(argc, vp);
   return CallNonGenericMethod<is, setUint32Impl>(cx, args);
 }
 
+// BigInt proposal 7.28
+// DataView.prototype.setBigInt64 ( byteOffset, value [ , littleEndian ] )
+bool DataViewObject::setBigInt64Impl(JSContext* cx, const CallArgs& args) {
+  MOZ_ASSERT(is(args.thisv()));
+
+  Rooted<DataViewObject*> thisView(
+      cx, &args.thisv().toObject().as<DataViewObject>());
+
+  if (!write<int64_t>(cx, thisView, args)) {
+    return false;
+  }
+  args.rval().setUndefined();
+  return true;
+}
+
+bool DataViewObject::fun_setBigInt64(JSContext* cx, unsigned argc, Value* vp) {
+  CallArgs args = CallArgsFromVp(argc, vp);
+  return CallNonGenericMethod<is, setBigInt64Impl>(cx, args);
+}
+
+// BigInt proposal 7.29
+// DataView.prototype.setBigUint64 ( byteOffset, value [ , littleEndian ] )
+bool DataViewObject::setBigUint64Impl(JSContext* cx, const CallArgs& args) {
+  MOZ_ASSERT(is(args.thisv()));
+
+  Rooted<DataViewObject*> thisView(
+      cx, &args.thisv().toObject().as<DataViewObject>());
+
+  if (!write<uint64_t>(cx, thisView, args)) {
+    return false;
+  }
+  args.rval().setUndefined();
+  return true;
+}
+
+bool DataViewObject::fun_setBigUint64(JSContext* cx, unsigned argc, Value* vp) {
+  CallArgs args = CallArgsFromVp(argc, vp);
+  return CallNonGenericMethod<is, setBigUint64Impl>(cx, args);
+}
+
 bool DataViewObject::setFloat32Impl(JSContext* cx, const CallArgs& args) {
   MOZ_ASSERT(is(args.thisv()));
 
   Rooted<DataViewObject*> thisView(
       cx, &args.thisv().toObject().as<DataViewObject>());
 
   if (!write<float>(cx, thisView, args)) {
     return false;
@@ -840,16 +964,25 @@ bool DataViewObject::byteOffsetGetter(JS
   return CallNonGenericMethod<is, byteOffsetGetterImpl>(cx, args);
 }
 
 JSObject* DataViewObject::CreatePrototype(JSContext* cx, JSProtoKey key) {
   return GlobalObject::createBlankPrototype(cx, cx->global(),
                                             &DataViewObject::protoClass_);
 }
 
+// Add extra methods for BigInt if its run-time option is enabled.
+bool DataViewObject::finishInit(JSContext* cx, JS::HandleObject ctor,
+                                JS::HandleObject proto) {
+  if (cx->realm()->creationOptions().getBigIntEnabled()) {
+    return JS_DefineFunctions(cx, proto, bigIntMethods);
+  }
+  return true;
+}
+
 static const ClassOps DataViewObjectClassOps = {nullptr, /* addProperty */
                                                 nullptr, /* delProperty */
                                                 nullptr, /* enumerate */
                                                 nullptr, /* newEnumerate */
                                                 nullptr, /* resolve */
                                                 nullptr, /* mayResolve */
                                                 nullptr, /* finalize */
                                                 nullptr, /* call */
@@ -860,16 +993,17 @@ static const ClassOps DataViewObjectClas
 const ClassSpec DataViewObject::classSpec_ = {
     GenericCreateConstructor<DataViewObject::construct, 1,
                              gc::AllocKind::FUNCTION>,
     GenericCreatePrototype<DataViewObject>,
     nullptr,
     nullptr,
     DataViewObject::methods,
     DataViewObject::properties,
+    DataViewObject::finishInit
 };
 
 const Class DataViewObject::class_ = {
     "DataView",
     JSCLASS_HAS_PRIVATE |
         JSCLASS_HAS_RESERVED_SLOTS(DataViewObject::RESERVED_SLOTS) |
         JSCLASS_HAS_CACHED_PROTO(JSProto_DataView),
     &DataViewObjectClassOps, &DataViewObject::classSpec_};
@@ -892,16 +1026,23 @@ const JSFunctionSpec DataViewObject::met
     JS_FN("setInt16", DataViewObject::fun_setInt16, 2, 0),
     JS_FN("setUint16", DataViewObject::fun_setUint16, 2, 0),
     JS_FN("setInt32", DataViewObject::fun_setInt32, 2, 0),
     JS_FN("setUint32", DataViewObject::fun_setUint32, 2, 0),
     JS_FN("setFloat32", DataViewObject::fun_setFloat32, 2, 0),
     JS_FN("setFloat64", DataViewObject::fun_setFloat64, 2, 0),
     JS_FS_END};
 
+const JSFunctionSpec DataViewObject::bigIntMethods[] = {
+    JS_FN("getBigInt64", DataViewObject::fun_getBigInt64, 1, 0),
+    JS_FN("getBigUint64", DataViewObject::fun_getBigUint64, 1, 0),
+    JS_FN("setBigInt64", DataViewObject::fun_setBigInt64, 2, 0),
+    JS_FN("setBigUint64", DataViewObject::fun_setBigUint64, 2, 0),
+    JS_FS_END};
+
 const JSPropertySpec DataViewObject::properties[] = {
     JS_PSG("buffer", DataViewObject::bufferGetter, 0),
     JS_PSG("byteLength", DataViewObject::byteLengthGetter, 0),
     JS_PSG("byteOffset", DataViewObject::byteOffsetGetter, 0),
     JS_STRING_SYM_PS(toStringTag, "DataView", JSPROP_READONLY), JS_PS_END};
 
 JS_FRIEND_API JSObject* JS_NewDataView(JSContext* cx, HandleObject buffer,
                                        uint32_t byteOffset,
--- a/js/src/builtin/DataViewObject.h
+++ b/js/src/builtin/DataViewObject.h
@@ -96,16 +96,22 @@ class DataViewObject : public ArrayBuffe
   static bool fun_getUint16(JSContext* cx, unsigned argc, Value* vp);
 
   static bool getInt32Impl(JSContext* cx, const CallArgs& args);
   static bool fun_getInt32(JSContext* cx, unsigned argc, Value* vp);
 
   static bool getUint32Impl(JSContext* cx, const CallArgs& args);
   static bool fun_getUint32(JSContext* cx, unsigned argc, Value* vp);
 
+  static bool getBigInt64Impl(JSContext* cx, const CallArgs& args);
+  static bool fun_getBigInt64(JSContext* cx, unsigned argc, Value* vp);
+
+  static bool getBigUint64Impl(JSContext* cx, const CallArgs& args);
+  static bool fun_getBigUint64(JSContext* cx, unsigned argc, Value* vp);
+
   static bool getFloat32Impl(JSContext* cx, const CallArgs& args);
   static bool fun_getFloat32(JSContext* cx, unsigned argc, Value* vp);
 
   static bool getFloat64Impl(JSContext* cx, const CallArgs& args);
   static bool fun_getFloat64(JSContext* cx, unsigned argc, Value* vp);
 
   static bool setInt8Impl(JSContext* cx, const CallArgs& args);
   static bool fun_setInt8(JSContext* cx, unsigned argc, Value* vp);
@@ -120,29 +126,39 @@ class DataViewObject : public ArrayBuffe
   static bool fun_setUint16(JSContext* cx, unsigned argc, Value* vp);
 
   static bool setInt32Impl(JSContext* cx, const CallArgs& args);
   static bool fun_setInt32(JSContext* cx, unsigned argc, Value* vp);
 
   static bool setUint32Impl(JSContext* cx, const CallArgs& args);
   static bool fun_setUint32(JSContext* cx, unsigned argc, Value* vp);
 
+  static bool setBigInt64Impl(JSContext* cx, const CallArgs& args);
+  static bool fun_setBigInt64(JSContext* cx, unsigned argc, Value* vp);
+
+  static bool setBigUint64Impl(JSContext* cx, const CallArgs& args);
+  static bool fun_setBigUint64(JSContext* cx, unsigned argc, Value* vp);
+
   static bool setFloat32Impl(JSContext* cx, const CallArgs& args);
   static bool fun_setFloat32(JSContext* cx, unsigned argc, Value* vp);
 
   static bool setFloat64Impl(JSContext* cx, const CallArgs& args);
   static bool fun_setFloat64(JSContext* cx, unsigned argc, Value* vp);
 
   template <typename NativeType>
   static bool read(JSContext* cx, Handle<DataViewObject*> obj,
                    const CallArgs& args, NativeType* val);
   template <typename NativeType>
   static bool write(JSContext* cx, Handle<DataViewObject*> obj,
                     const CallArgs& args);
 
  private:
   static const JSFunctionSpec methods[];
   static const JSPropertySpec properties[];
+
+  static const JSFunctionSpec bigIntMethods[];
+  static bool finishInit(JSContext* cx, JS::HandleObject ctor,
+                         JS::HandleObject proto);
 };
 
 }  // namespace js
 
 #endif /* vm_DataViewObject_h */
--- a/js/src/tests/jstests.list
+++ b/js/src/tests/jstests.list
@@ -913,58 +913,16 @@ skip script test262/built-ins/TypedArray
 skip script test262/built-ins/TypedArrayConstructors/prototype/every/bigint-inherited.js
 skip script test262/built-ins/TypedArrayConstructors/prototype/reduce/bigint-inherited.js
 skip script test262/built-ins/TypedArrayConstructors/prototype/fill/bigint-inherited.js
 skip script test262/built-ins/TypedArrayConstructors/prototype/reduceRight/bigint-inherited.js
 skip script test262/built-ins/TypedArrayConstructors/prototype/copyWithin/bigint-inherited.js
 skip script test262/built-ins/TypedArrayConstructors/prototype/map/bigint-inherited.js
 skip script test262/built-ins/TypedArrayConstructors/prototype/set/bigint-inherited.js
 skip script test262/built-ins/TypedArrayConstructors/prototype/sort/bigint-inherited.js
-skip script test262/built-ins/DataView/prototype/getBigInt64/negative-byteoffset-throws.js
-skip script test262/built-ins/DataView/prototype/getBigInt64/return-value-clean-arraybuffer.js
-skip script test262/built-ins/DataView/prototype/getBigInt64/return-abrupt-from-tonumber-byteoffset.js
-skip script test262/built-ins/DataView/prototype/getBigInt64/return-values-custom-offset.js
-skip script test262/built-ins/DataView/prototype/getBigInt64/name.js
-skip script test262/built-ins/DataView/prototype/getBigInt64/detached-buffer-after-toindex-byteoffset.js
-skip script test262/built-ins/DataView/prototype/getBigInt64/toindex-byteoffset-errors.js
-skip script test262/built-ins/DataView/prototype/getBigInt64/to-boolean-littleendian.js
-skip script test262/built-ins/DataView/prototype/getBigInt64/toindex-byteoffset.js
-skip script test262/built-ins/DataView/prototype/getBigInt64/length.js
-skip script test262/built-ins/DataView/prototype/getBigInt64/toindex-byteoffset-toprimitive.js
-skip script test262/built-ins/DataView/prototype/getBigInt64/return-values.js
-skip script test262/built-ins/DataView/prototype/getBigInt64/index-is-out-of-range.js
-skip script test262/built-ins/DataView/prototype/getBigInt64/toindex-byteoffset-wrapped-values.js
-skip script test262/built-ins/DataView/prototype/setBigInt64/return-abrupt-from-tobigint-value.js
-skip script test262/built-ins/DataView/prototype/setBigInt64/index-check-before-value-conversion.js
-skip script test262/built-ins/DataView/prototype/setBigInt64/negative-byteoffset-throws.js
-skip script test262/built-ins/DataView/prototype/setBigInt64/return-abrupt-from-tonumber-byteoffset.js
-skip script test262/built-ins/DataView/prototype/setBigInt64/set-values-little-endian-order.js
-skip script test262/built-ins/DataView/prototype/setBigInt64/name.js
-skip script test262/built-ins/DataView/prototype/setBigInt64/detached-buffer-after-toindex-byteoffset.js
-skip script test262/built-ins/DataView/prototype/setBigInt64/set-values-return-undefined.js
-skip script test262/built-ins/DataView/prototype/setBigInt64/detached-buffer-after-bigint-value.js
-skip script test262/built-ins/DataView/prototype/setBigInt64/to-boolean-littleendian.js
-skip script test262/built-ins/DataView/prototype/setBigInt64/toindex-byteoffset.js
-skip script test262/built-ins/DataView/prototype/setBigInt64/length.js
-skip script test262/built-ins/DataView/prototype/setBigInt64/index-is-out-of-range.js
-skip script test262/built-ins/DataView/prototype/setBigInt64/range-check-after-value-conversion.js
-skip script test262/built-ins/DataView/prototype/getBigUint64/negative-byteoffset-throws.js
-skip script test262/built-ins/DataView/prototype/getBigUint64/return-value-clean-arraybuffer.js
-skip script test262/built-ins/DataView/prototype/getBigUint64/return-abrupt-from-tonumber-byteoffset.js
-skip script test262/built-ins/DataView/prototype/getBigUint64/return-values-custom-offset.js
-skip script test262/built-ins/DataView/prototype/getBigUint64/name.js
-skip script test262/built-ins/DataView/prototype/getBigUint64/detached-buffer-after-toindex-byteoffset.js
-skip script test262/built-ins/DataView/prototype/getBigUint64/toindex-byteoffset-errors.js
-skip script test262/built-ins/DataView/prototype/getBigUint64/to-boolean-littleendian.js
-skip script test262/built-ins/DataView/prototype/getBigUint64/toindex-byteoffset.js
-skip script test262/built-ins/DataView/prototype/getBigUint64/length.js
-skip script test262/built-ins/DataView/prototype/getBigUint64/toindex-byteoffset-toprimitive.js
-skip script test262/built-ins/DataView/prototype/getBigUint64/return-values.js
-skip script test262/built-ins/DataView/prototype/getBigUint64/index-is-out-of-range.js
-skip script test262/built-ins/DataView/prototype/getBigUint64/toindex-byteoffset-wrapped-values.js
 
 # https://bugzilla.mozilla.org/show_bug.cgi?id=1317405
 skip script test262/language/computed-property-names/class/static/method-number.js
 skip script test262/language/computed-property-names/class/static/method-string.js
 skip script test262/language/computed-property-names/class/static/method-symbol.js
 
 # https://bugzilla.mozilla.org/show_bug.cgi?id=1286997
 # Bug 1286997 probably doesn't cover all spec violations.
new file mode 100644
--- /dev/null
+++ b/mobile/android/config/mozconfigs/android-api-16/debug-searchfox
@@ -0,0 +1,25 @@
+. "$topsrcdir/mobile/android/config/mozconfigs/common"
+
+# Global options
+ac_add_options --enable-debug
+
+# Android
+# Warning: Before increasing the with-android-min-sdk value, please note several places in and out
+# of tree have to be changed. Otherwise, places like Treeherder or archive.mozilla.org will
+# advertise a bad API level. This may confuse people. As an example, please look at bug 1384482.
+# If you think you can't handle the whole set of changes, please reach out to the Release
+# Engineering team.
+ac_add_options --with-android-min-sdk=16
+ac_add_options --target=arm-linux-androideabi
+
+export MOZILLA_OFFICIAL=1
+export MOZ_TELEMETRY_REPORTING=1
+
+ac_add_options --with-branding=mobile/android/branding/nightly
+
+# Save rust analysis (this requires unlocking the unstable features,
+# which is done in the taskcluster task definition via RUSTC_BOOTSTRAP)
+export RUSTFLAGS="-Zsave-analysis"
+ac_add_options --enable-mozsearch-plugin
+
+. "$topsrcdir/mobile/android/config/mozconfigs/common.override"
--- a/mozglue/build/WindowsDllBlocklist.cpp
+++ b/mozglue/build/WindowsDllBlocklist.cpp
@@ -26,16 +26,17 @@
 
 #include "Authenticode.h"
 #include "CrashAnnotations.h"
 #include "MozglueUtils.h"
 #include "UntrustedDllsHandler.h"
 #include "nsAutoPtr.h"
 #include "nsWindowsDllInterceptor.h"
 #include "mozilla/CmdLineAndEnvUtils.h"
+#include "mozilla/DebugOnly.h"
 #include "mozilla/ScopeExit.h"
 #include "mozilla/Sprintf.h"
 #include "mozilla/StackWalk_windows.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/Vector.h"
 #include "mozilla/WindowsVersion.h"
 #include "nsWindowsHelpers.h"
@@ -1003,19 +1004,19 @@ MFBT_API void DllBlocklist_SetFullDllSer
     if (!gNotificationCookie) {
       auto pLdrRegisterDllNotification =
           reinterpret_cast<decltype(&::LdrRegisterDllNotification)>(
               ::GetProcAddress(::GetModuleHandleW(L"ntdll.dll"),
                                "LdrRegisterDllNotification"));
 
       MOZ_DIAGNOSTIC_ASSERT(pLdrRegisterDllNotification);
 
-      NTSTATUS ntStatus = pLdrRegisterDllNotification(
+      mozilla::DebugOnly<NTSTATUS> ntStatus = pLdrRegisterDllNotification(
           0, &DllLoadNotification, nullptr, &gNotificationCookie);
-      MOZ_DIAGNOSTIC_ASSERT(NT_SUCCESS(ntStatus));
+      MOZ_ASSERT(NT_SUCCESS(ntStatus));
     }
   }
 
   gDllServices = aSvc;
 
   if (IsUntrustedDllsHandlerEnabled() && gDllServices) {
     Vector<glue::ModuleLoadEvent, 0, InfallibleAllocPolicy> events;
     if (glue::UntrustedDllsHandler::TakePendingEvents(events)) {
--- a/netwerk/base/nsIOService.cpp
+++ b/netwerk/base/nsIOService.cpp
@@ -480,16 +480,26 @@ void nsIOService::CallOrWaitForSocketPro
   MOZ_ASSERT(NS_IsMainThread());
   if (IsSocketProcessLaunchComplete() && SocketProcessReady()) {
     aFunc();
   } else {
     mPendingEvents.AppendElement(aFunc);  // infallible
   }
 }
 
+int32_t nsIOService::SocketProcessPid() {
+  if (!mSocketProcess) {
+    return 0;
+  }
+  if (SocketProcessParent *actor = mSocketProcess->GetActor()) {
+    return (int32_t)actor->OtherPid();
+  }
+  return 0;
+}
+
 bool nsIOService::IsSocketProcessLaunchComplete() {
   MOZ_ASSERT(NS_IsMainThread());
   return mSocketProcessLaunchComplete;
 }
 
 void nsIOService::OnProcessUnexpectedShutdown(SocketProcessHost *aHost) {
   MOZ_ASSERT(NS_IsMainThread());
 
--- a/netwerk/base/nsIOService.h
+++ b/netwerk/base/nsIOService.h
@@ -123,16 +123,17 @@ class nsIOService final : public nsIIOSe
 
   bool IsSocketProcessLaunchComplete();
 
   // Call func immediately if socket process is launched completely. Otherwise,
   // |func| will be queued and then executed in the *main thread* once socket
   // process is launced.
   void CallOrWaitForSocketProcess(const std::function<void()>& aFunc);
 
+  int32_t SocketProcessPid();
   friend SocketProcessMemoryReporter;
   RefPtr<MemoryReportingProcess> GetSocketProcessMemoryReporter();
 
  private:
   // These shouldn't be called directly:
   // - construct using GetInstance
   // - destroy using Release
   nsIOService();
--- a/netwerk/ipc/SocketProcessHost.cpp
+++ b/netwerk/ipc/SocketProcessHost.cpp
@@ -320,21 +320,13 @@ bool SocketProcessMemoryReporter::SendRe
   }
 
   return actor->SendRequestMemoryReport(aGeneration, aAnonymize,
                                         aMinimizeMemoryUsage, aDMDFile);
 }
 
 int32_t SocketProcessMemoryReporter::Pid() const {
   MOZ_ASSERT(gIOService);
-
-  if (!gIOService->mSocketProcess) {
-    return 0;
-  }
-
-  if (SocketProcessParent* actor = gIOService->mSocketProcess->GetActor()) {
-    return (int32_t)actor->OtherPid();
-  }
-  return 0;
+  return gIOService->SocketProcessPid();
 }
 
 }  // namespace net
 }  // namespace mozilla
--- a/taskcluster/ci/searchfox/kind.yml
+++ b/taskcluster/ci/searchfox/kind.yml
@@ -113,8 +113,44 @@ jobs:
                 - builds/taskcluster_base_win64.py
                 - builds/taskcluster_sub_win64/searchfox_debug.py
         toolchains:
             - win64-clang-cl
             - win64-node
             - win64-rust
             - win64-cbindgen
             - win64-nasm
+
+    android-armv7-searchfox/debug:
+        description: "Android ARMv7 Debug Searchfox"
+        index:
+            job-name: android-armv7-searchfox-debug
+        treeherder:
+            platform: android-4-0-armv7-api16/debug
+        worker-type: aws-provisioner-v1/gecko-{level}-b-android
+        worker:
+            docker-image: {in-tree: android-build}
+            max-run-time: 36000
+            env:
+                PERFHERDER_EXTRA_OPTIONS: searchfox
+                RUSTC_BOOTSTRAP: "1"
+                MOZSEARCH_PLATFORM: "android-armv7"
+                GRADLE_USER_HOME: "/builds/worker/workspace/build/src/mobile/android/gradle/dotgradle-offline"
+                TOOLTOOL_MANIFEST: "mobile/android/config/tooltool-manifests/android/releng.manifest"
+        run:
+            using: mozharness
+            actions: [get-secrets, build]
+            config:
+                - builds/releng_base_android_64_builds.py
+            script: "mozharness/scripts/fx_desktop_build.py"
+            secrets: true
+            custom-build-variant-cfg: api-16-debug-searchfox
+            tooltool-downloads: internal
+        toolchains:
+            - android-gradle-dependencies
+            - android-ndk-linux
+            - android-sdk-linux
+            - linux64-clang
+            - linux64-rust-android
+            - linux64-rust-size
+            - linux64-cbindgen
+            - linux64-sccache
+            - linux64-node
--- a/taskcluster/taskgraph/target_tasks.py
+++ b/taskcluster/taskgraph/target_tasks.py
@@ -555,17 +555,18 @@ def target_tasks_nightly_desktop(full_ta
 
 
 # Run Searchfox analysis once daily.
 @_target_task('searchfox_index')
 def target_tasks_searchfox(full_task_graph, parameters, graph_config):
     """Select tasks required for indexing Firefox for Searchfox web site each day"""
     return ['searchfox-linux64-searchfox/debug',
             'searchfox-macosx64-searchfox/debug',
-            'searchfox-win64-searchfox/debug']
+            'searchfox-win64-searchfox/debug',
+            'searchfox-android-armv7-searchfox/debug']
 
 
 @_target_task('customv8_update')
 def target_tasks_customv8_update(full_task_graph, parameters, graph_config):
     """Select tasks required for building latest d8/v8 version."""
     return ['toolchain-linux64-custom-v8']
 
 
new file mode 100644
--- /dev/null
+++ b/testing/mozharness/configs/builds/releng_sub_android_configs/64_api_16_debug_searchfox.py
@@ -0,0 +1,9 @@
+config = {
+    'stage_platform': 'android-api-16-debug',
+    'env': {
+        'SCCACHE_DISABLE': '1',
+    },
+    'src_mozconfig': 'mobile/android/config/mozconfigs/android-api-16/debug-searchfox',
+    'multi_locale_config_platform': 'android',
+    'debug_build': True,
+}
--- a/testing/mozharness/mozharness/mozilla/building/buildbase.py
+++ b/testing/mozharness/mozharness/mozilla/building/buildbase.py
@@ -368,16 +368,17 @@ class BuildOptionParser(object):
         'noopt-debug': 'builds/releng_sub_%s_configs/%s_noopt_debug.py',
         'api-16-gradle-dependencies':
             'builds/releng_sub_%s_configs/%s_api_16_gradle_dependencies.py',
         'api-16': 'builds/releng_sub_%s_configs/%s_api_16.py',
         'api-16-artifact': 'builds/releng_sub_%s_configs/%s_api_16_artifact.py',
         'api-16-debug': 'builds/releng_sub_%s_configs/%s_api_16_debug.py',
         'api-16-debug-ccov': 'builds/releng_sub_%s_configs/%s_api_16_debug_ccov.py',
         'api-16-debug-artifact': 'builds/releng_sub_%s_configs/%s_api_16_debug_artifact.py',
+        'api-16-debug-searchfox': 'builds/releng_sub_%s_configs/%s_api_16_debug_searchfox.py',
         'api-16-gradle': 'builds/releng_sub_%s_configs/%s_api_16_gradle.py',
         'api-16-gradle-artifact': 'builds/releng_sub_%s_configs/%s_api_16_gradle_artifact.py',
         'api-16-without-google-play-services':
             'builds/releng_sub_%s_configs/%s_api_16_without_google_play_services.py',
         'rusttests': 'builds/releng_sub_%s_configs/%s_rusttests.py',
         'rusttests-debug': 'builds/releng_sub_%s_configs/%s_rusttests_debug.py',
         'x86': 'builds/releng_sub_%s_configs/%s_x86.py',
         'x86-artifact': 'builds/releng_sub_%s_configs/%s_x86_artifact.py',
--- a/toolkit/components/alerts/resources/content/alert.js
+++ b/toolkit/components/alerts/resources/content/alert.js
@@ -281,18 +281,16 @@ function onAlertClick() {
   }
 }
 
 function doNotDisturb() {
   const alertService = Cc["@mozilla.org/alerts-service;1"]
                          .getService(Ci.nsIAlertsService)
                          .QueryInterface(Ci.nsIAlertsDoNotDisturb);
   alertService.manualDoNotDisturb = true;
-  Services.telemetry.getHistogramById("WEB_NOTIFICATION_MENU")
-                    .add(0);
   onAlertClose();
 }
 
 function disableForOrigin() {
   gAlertListener.observe(null, "alertdisablecallback", gAlertCookie);
   onAlertClose();
 }
 
--- a/toolkit/components/search/SearchService.jsm
+++ b/toolkit/components/search/SearchService.jsm
@@ -2636,17 +2636,16 @@ SearchService.prototype = {
     this._addObservers();
     gInitialized = true;
     if (Components.isSuccessCode(this._initRV)) {
       this._initObservers.resolve(this._initRV);
     } else {
       this._initObservers.reject(this._initRV);
     }
     Services.obs.notifyObservers(null, SEARCH_SERVICE_TOPIC, "init-complete");
-    Services.telemetry.getHistogramById("SEARCH_SERVICE_INIT_SYNC").add(false);
 
     LOG("_init: Completed _init");
     return this._initRV;
   },
 
   _metaData: { },
   setGlobalAttr(name, val) {
     this._metaData[name] = val;
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -8140,23 +8140,16 @@
     "expires_in_version": "never",
     "releaseChannelCollection": "opt-out",
     "kind": "exponential",
     "high": 1000,
     "n_buckets": 15,
     "bug_numbers": [1489524],
     "description": "Time (ms) it takes to initialize the search service"
   },
-  "SEARCH_SERVICE_INIT_SYNC": {
-    "record_in_processes": ["main", "content"],
-    "alert_emails": ["rvitillo@mozilla.com", "gavin@mozilla.com"],
-    "expires_in_version": "never",
-    "kind": "boolean",
-    "description": "search service has been initialized synchronously"
-  },
   "SEARCH_SERVICE_COUNTRY_FETCH_TIME_MS": {
     "record_in_processes": ["main", "content"],
     "alert_emails": ["mhammond@mozilla.com", "gavin@mozilla.com"],
     "expires_in_version": "never",
     "kind": "exponential",
     "n_buckets": 30,
     "high": 100000,
     "description": "Time (ms) it takes to fetch the country code"
@@ -12572,43 +12565,16 @@
     "record_in_processes": ["main", "content", "gpu"],
     "alert_emails": ["gfx-telemetry-alerts@mozilla.com", "rhunt@mozilla.com"],
     "expires_in_version": "never",
     "kind": "enumerated",
     "n_values": 100,
     "releaseChannelCollection": "opt-out",
     "description": "Graphics Crash Reason (...)"
   },
-  "WEB_NOTIFICATION_CLICKED": {
-    "record_in_processes": ["main", "content"],
-    "releaseChannelCollection": "opt-out",
-    "alert_emails": ["firefox-dev@mozilla.org", "push@mozilla.com"],
-    "bug_numbers": [1225336, 1429286],
-    "expires_in_version": "never",
-    "kind": "count",
-    "description": "Count of times a web notification was clicked"
-  },
-  "WEB_NOTIFICATION_MENU": {
-    "record_in_processes": ["main", "content"],
-    "alert_emails": ["firefox-dev@mozilla.org"],
-    "bug_numbers": [1225336],
-    "expires_in_version": "50",
-    "kind": "enumerated",
-    "n_values": 5,
-    "description": "Count of times a contextual menu item was used from a Notification (0: DND, 1: Disable, 2: Settings)"
-  },
-  "WEB_NOTIFICATION_SHOWN": {
-    "record_in_processes": ["main", "content"],
-    "releaseChannelCollection": "opt-out",
-    "alert_emails": ["firefox-dev@mozilla.org", "push@mozilla.com"],
-    "bug_numbers": [1225336, 1429286],
-    "expires_in_version": "never",
-    "kind": "count",
-    "description": "Count of times a Notification was rendered (accounting for XUL DND). A system backend may put the notification directly into the tray if its own DND is on."
-  },
   "WEBFONT_DOWNLOAD_TIME": {
     "record_in_processes": ["main", "content"],
     "alert_emails": ["jdaggett@mozilla.com"],
     "expires_in_version": "never",
     "kind": "exponential",
     "high": 60000,
     "n_buckets": 50,
     "description": "Time to download a webfont (ms)"
@@ -12698,34 +12664,16 @@
   "ALERTS_SERVICE_DND_SUPPORTED_FLAG": {
     "record_in_processes": ["main", "content"],
     "alert_emails": ["firefox-dev@mozilla.org"],
     "bug_numbers": [1219030],
     "expires_in_version": "50",
     "kind": "flag",
     "description": "Whether the do not disturb option is supported. True if the browser uses XUL alerts."
   },
-  "WEB_NOTIFICATION_EXCEPTIONS_OPENED": {
-    "record_in_processes": ["main", "content"],
-    "alert_emails": ["firefox-dev@mozilla.org"],
-    "bug_numbers": [1219030],
-    "expires_in_version": "50",
-    "kind": "count",
-    "description": "Number of times the Notification Permissions dialog has been opened."
-  },
-  "WEB_NOTIFICATION_PERMISSIONS": {
-    "record_in_processes": ["main", "content"],
-    "releaseChannelCollection": "opt-out",
-    "alert_emails": ["firefox-dev@mozilla.org", "push@mozilla.com"],
-    "bug_numbers": [1219030, 1429286],
-    "expires_in_version": "never",
-    "kind": "enumerated",
-    "n_values": 10,
-    "description": "Number of origins with the web notifications permission (0 = denied, 1 = allowed)."
-  },
   "PLUGIN_DRAWING_MODEL": {
     "record_in_processes": ["main", "content"],
     "alert_emails": ["gfx-telemetry-alerts@mozilla.com", "rhunt@mozilla.com"],
     "expires_in_version": "never",
     "kind": "enumerated",
     "bug_numbers": [1229961],
     "n_values": 12,
     "releaseChannelCollection": "opt-out",
--- a/toolkit/components/telemetry/histogram-whitelists.json
+++ b/toolkit/components/telemetry/histogram-whitelists.json
@@ -957,17 +957,16 @@
     "READER_MODE_PARSE_RESULT",
     "REFRESH_DRIVER_TICK",
     "REQUESTS_OF_ORIGINAL_CONTENT",
     "SAFE_MODE_USAGE",
     "SEARCH_SERVICE_COUNTRY_FETCH_CAUSED_SYNC_INIT",
     "SEARCH_SERVICE_COUNTRY_FETCH_RESULT",
     "SEARCH_SERVICE_COUNTRY_FETCH_TIME_MS",
     "SEARCH_SERVICE_COUNTRY_TIMEOUT",
-    "SEARCH_SERVICE_INIT_SYNC",
     "SEARCH_SERVICE_NONUS_COUNTRY_MISMATCHED_PLATFORM_OSX",
     "SEARCH_SERVICE_NONUS_COUNTRY_MISMATCHED_PLATFORM_WIN",
     "SEARCH_SERVICE_US_COUNTRY_MISMATCHED_PLATFORM_OSX",
     "SEARCH_SERVICE_US_COUNTRY_MISMATCHED_PLATFORM_WIN",
     "SEARCH_SERVICE_US_COUNTRY_MISMATCHED_TIMEZONE",
     "SEARCH_SERVICE_US_TIMEZONE_MISMATCHED_COUNTRY",
     "SERVICE_WORKER_CONTROLLED_DOCUMENTS",
     "SERVICE_WORKER_LIFE_TIME",
@@ -1543,14 +1542,11 @@
     "UPDATE_SERVICE_MANUALLY_UNINSTALLED_EXTERNAL",
     "UPDATE_SERVICE_MANUALLY_UNINSTALLED_NOTIFY",
     "UPDATE_UNABLE_TO_APPLY_EXTERNAL",
     "UPDATE_UNABLE_TO_APPLY_NOTIFY",
     "VIDEO_FASTSEEK_USED",
     "WEBFONT_PER_PAGE",
     "WEBRTC_CALL_COUNT_2",
     "WEBVTT_USED_VTT_CUES",
-    "WEB_NOTIFICATION_CLICKED",
-    "WEB_NOTIFICATION_EXCEPTIONS_OPENED",
-    "WEB_NOTIFICATION_SHOWN",
     "XUL_CACHE_DISABLED"
   ]
 }
new file mode 100644
--- /dev/null
+++ b/widget/ProcInfo.h
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef __mozilla_ProcInfo_h
+#define __mozilla_ProcInfo_h
+
+#include <base/process.h>
+#include <stdint.h>
+#include "mozilla/dom/ipc/IdType.h"
+
+namespace mozilla {
+
+// Process types
+enum class ProcType {
+  // These must match the ones in ContentParent.h and E10SUtils.jsm
+  Web,
+  File,
+  Extension,
+  Privileged,
+  WebLargeAllocation,
+  // GPU process (only on Windows)
+  Gpu,
+  // RDD process (Windows and macOS)
+  Rdd,
+  // Socket process
+  Socket,
+  // Main process
+  Browser,
+  // Unknown type of process
+  Unknown
+};
+
+struct ThreadInfo {
+  // Thread Id.
+  base::ProcessId tid = 0;
+  // Thread name, if any.
+  nsString name;
+  // User time in ns.
+  uint64_t cpuUser = 0;
+  // System time in ns.
+  uint64_t cpuKernel = 0;
+};
+
+struct ProcInfo {
+  // Process Id
+  base::ProcessId pid = 0;
+  // Child Id as defined by Firefox when a child process is created.
+  dom::ContentParentId childId;
+  // Process type
+  ProcType type;
+  // Process filename (without the path name).
+  nsString filename;
+  // VMS in bytes.
+  uint64_t virtualMemorySize = 0;
+  // RSS in bytes.
+  int64_t residentSetSize = 0;
+  // User time in ns.
+  uint64_t cpuUser = 0;
+  // System time in ns.
+  uint64_t cpuKernel = 0;
+  // Threads owned by this process.
+  nsTArray<ThreadInfo> threads;
+};
+
+typedef MozPromise<ProcInfo, nsresult, true> ProcInfoPromise;
+
+RefPtr<ProcInfoPromise> GetProcInfo(base::ProcessId pid, int32_t childId,
+                                    const ProcType& type);
+
+}  // namespace mozilla
+#endif  // ProcInfo_h
new file mode 100644
--- /dev/null
+++ b/widget/android/ProcInfo.cpp
@@ -0,0 +1,17 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/ProcInfo.h"
+
+namespace mozilla {
+
+RefPtr<ProcInfoPromise> GetProcInfo(base::ProcessId pid, int32_t childId,
+                                    const ProcType& type) {
+  // Not implemented on Android.
+  return nullptr;
+}
+
+}  // namespace mozilla
--- a/widget/android/moz.build
+++ b/widget/android/moz.build
@@ -57,16 +57,17 @@ UNIFIED_SOURCES += [
     'nsClipboard.cpp',
     'nsDeviceContextAndroid.cpp',
     'nsIdleServiceAndroid.cpp',
     'nsLookAndFeel.cpp',
     'nsNativeThemeAndroid.cpp',
     'nsPrintSettingsServiceAndroid.cpp',
     'nsWidgetFactory.cpp',
     'nsWindow.cpp',
+    'ProcInfo.cpp',
     'ScreenHelperAndroid.cpp',
     'WebExecutorSupport.cpp',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 # The recursive make backend treats the first output specially: it's passed as
 # an open FileAvoidWrite to the invoked script.  That doesn't work well with
new file mode 100644
--- /dev/null
+++ b/widget/cocoa/ProcInfo.mm
@@ -0,0 +1,118 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/ProcInfo.h"
+#include "mozilla/Sprintf.h"
+#include "mozilla/Logging.h"
+#include "nsNetCID.h"
+
+#include <cstdio>
+#include <cstring>
+#include <unistd.h>
+
+#include <libproc.h>
+#include <sys/sysctl.h>
+#include <mach/mach.h>
+
+namespace mozilla {
+
+RefPtr<ProcInfoPromise> GetProcInfo(base::ProcessId pid, int32_t childId, const ProcType& type) {
+  auto holder = MakeUnique<MozPromiseHolder<ProcInfoPromise>>();
+  RefPtr<ProcInfoPromise> promise = holder->Ensure(__func__);
+
+  nsresult rv = NS_OK;
+  nsCOMPtr<nsIEventTarget> target = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID, &rv);
+  if (NS_FAILED(rv)) {
+    NS_WARNING("Failed to get stream transport service");
+    holder->Reject(rv, __func__);
+    return promise;
+  }
+
+  auto ResolveGetProcinfo = [holder = std::move(holder), pid, type, childId]() {
+    ProcInfo info;
+    info.pid = pid;
+    info.childId = childId;
+    info.type = type;
+    struct proc_bsdinfo proc;
+    if ((unsigned long)proc_pidinfo(pid, PROC_PIDTBSDINFO, 0, &proc, PROC_PIDTBSDINFO_SIZE) <
+        PROC_PIDTBSDINFO_SIZE) {
+      holder->Reject(NS_ERROR_FAILURE, __func__);
+      return;
+    }
+
+    struct proc_taskinfo pti;
+    if ((unsigned long)proc_pidinfo(pid, PROC_PIDTASKINFO, 0, &pti, PROC_PIDTASKINFO_SIZE) <
+        PROC_PIDTASKINFO_SIZE) {
+      holder->Reject(NS_ERROR_FAILURE, __func__);
+      return;
+    }
+
+    // copying all the info to the ProcInfo struct
+    info.filename.AssignASCII(proc.pbi_name);
+    info.virtualMemorySize = pti.pti_virtual_size;
+    info.residentSetSize = pti.pti_resident_size;
+    info.cpuUser = pti.pti_total_user;
+    info.cpuKernel = pti.pti_total_system;
+
+    // Now getting threads info
+    mach_port_t task;
+    kern_return_t kret = task_for_pid(mach_task_self(), pid, &task);
+    if (kret != KERN_SUCCESS) {
+      // If we can't get threads detail, we just ignore that.
+      holder->Resolve(info, __func__);
+      return;
+    }
+
+    // task_threads() gives us a snapshot of the process threads
+    // but those threads can go away. All the code below makes
+    // the assumption that thread_info() calls may fail, and
+    // these errors will be ignored.
+    thread_act_port_array_t threadList;
+    mach_msg_type_number_t threadCount;
+    kret = task_threads(task, &threadList, &threadCount);
+    if (kret != KERN_SUCCESS) {
+      holder->Resolve(info, __func__);
+      return;
+    }
+
+    for (mach_msg_type_number_t i = 0; i < threadCount; i++) {
+      // Basic thread info.
+      mach_msg_type_number_t threadInfoCount = THREAD_EXTENDED_INFO_COUNT;
+      thread_extended_info_data_t threadInfoData;
+      kret = thread_info(threadList[i], THREAD_EXTENDED_INFO, (thread_info_t)&threadInfoData,
+                         &threadInfoCount);
+      if (kret != KERN_SUCCESS) {
+        continue;
+      }
+
+      // Getting the thread id.
+      thread_identifier_info identifierInfo;
+      kret = thread_info(threadList[i], THREAD_IDENTIFIER_INFO, (thread_info_t)&identifierInfo,
+                         &threadInfoCount);
+      if (kret != KERN_SUCCESS) {
+        continue;
+      }
+
+      // The two system calls were successful, let's add that thread
+      ThreadInfo thread;
+      thread.cpuUser = threadInfoData.pth_user_time;
+      thread.cpuKernel = threadInfoData.pth_system_time;
+      thread.name.AssignASCII(threadInfoData.pth_name);
+      thread.tid = identifierInfo.thread_id;
+      info.threads.AppendElement(thread);
+    }
+    holder->Resolve(info, __func__);
+  };
+
+  RefPtr<nsIRunnable> r = NS_NewRunnableFunction(__func__, std::move(ResolveGetProcinfo));
+  rv = target->Dispatch(r.forget(), NS_DISPATCH_NORMAL);
+  if (NS_FAILED(rv)) {
+    NS_WARNING("Failed to dispatch the LoadDataRunnable.");
+  }
+  return promise;
+}
+
+}
--- a/widget/cocoa/moz.build
+++ b/widget/cocoa/moz.build
@@ -54,16 +54,17 @@ UNIFIED_SOURCES += [
     'nsStandaloneNativeMenu.mm',
     'nsSystemStatusBarCocoa.mm',
     'nsToolkit.mm',
     'nsTouchBar.mm',
     'nsTouchBarUpdater.mm',
     'nsWidgetFactory.mm',
     'nsWindowMap.mm',
     'OSXNotificationCenter.mm',
+    'ProcInfo.mm',
     'RectTextureImage.mm',
     'ScreenHelperCocoa.mm',
     'SwipeTracker.mm',
     'TextInputHandler.mm',
     'VibrancyManager.mm',
     'ViewRegion.mm',
     'WidgetTraceEvent.mm',
 ]
new file mode 100644
--- /dev/null
+++ b/widget/gtk/ProcInfo.cpp
@@ -0,0 +1,276 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/ProcInfo.h"
+#include "mozilla/Sprintf.h"
+#include "mozilla/Logging.h"
+#include "nsAutoRef.h"
+#include "nsLocalFile.h"
+#include "nsNetCID.h"
+#include "nsWhitespaceTokenizer.h"
+
+#include <cstdio>
+#include <cstring>
+#include <unistd.h>
+#include <dirent.h>
+
+#define NANOPERSEC 1000000000.
+
+template <>
+class nsAutoRefTraits<DIR> : public nsPointerRefTraits<DIR> {
+ public:
+  static void Release(DIR* dirHandle) { closedir(dirHandle); }
+};
+
+namespace mozilla {
+
+// StatReader can parse and tokenize a POSIX stat file.
+// see http://man7.org/linux/man-pages/man5/proc.5.html
+//
+// Its usage is quite simple:
+//
+// StatReader reader(pid);
+// ProcInfo info;
+// rv = reader.ParseProc(info);
+// if (NS_FAILED(rv)) {
+//     // the reading of the file or its parsing failed.
+// }
+//
+class StatReader {
+ public:
+  explicit StatReader(const base::ProcessId aPid)
+      : mPid(aPid), mMaxIndex(53), mTicksPerSec(sysconf(_SC_CLK_TCK)) {
+    mFilepath.AppendPrintf("/proc/%u/stat", mPid);
+  }
+
+  nsresult ParseProc(ProcInfo& aInfo) {
+    nsAutoString fileContent;
+    nsresult rv = ReadFile(fileContent);
+    NS_ENSURE_SUCCESS(rv, rv);
+    // We first extract the filename
+    int32_t startPos = fileContent.RFindChar('(');
+    if (startPos == -1) {
+      return NS_ERROR_FAILURE;
+    }
+    int32_t endPos = fileContent.RFindChar(')');
+    if (endPos == -1) {
+      return NS_ERROR_FAILURE;
+    }
+    int32_t len = endPos - (startPos + 1);
+    aInfo.filename.Assign(Substring(fileContent, startPos + 1, len));
+
+    // now we can use the tokenizer for the rest of the file
+    nsWhitespaceTokenizer tokenizer(Substring(fileContent, endPos + 2));
+    int32_t index = 2;  // starting at third field
+    while (tokenizer.hasMoreTokens() && index < mMaxIndex) {
+      const nsAString& token = tokenizer.nextToken();
+      rv = UseToken(index, token, aInfo);
+      NS_ENSURE_SUCCESS(rv, rv);
+      index++;
+    }
+    return NS_OK;
+  }
+
+ protected:
+  // Called for each token found in the stat file.
+  nsresult UseToken(int32_t aIndex, const nsAString& aToken, ProcInfo& aInfo) {
+    // We're using a subset of what stat has to offer for now.
+    nsresult rv = NS_OK;
+    // see the proc documentation for fields index references.
+    switch (aIndex) {
+      case 15:
+        // Amount of time that this process has been scheduled
+        // in user mode, measured in clock ticks
+        aInfo.cpuUser = GetCPUTime(aToken, &rv);
+        NS_ENSURE_SUCCESS(rv, rv);
+        break;
+      case 16:
+        // Amount of time that this process has been scheduled
+        // in kernel mode, measured in clock ticks
+        aInfo.cpuKernel = GetCPUTime(aToken, &rv);
+        NS_ENSURE_SUCCESS(rv, rv);
+        break;
+      case 24:
+        // Virtual memory size in bytes.
+        aInfo.virtualMemorySize = Get64Value(aToken, &rv);
+        NS_ENSURE_SUCCESS(rv, rv);
+        break;
+      case 25:
+        // Resident Set Size: number of pages the process has
+        // in real memory.
+        aInfo.residentSetSize = Get64Value(aToken, &rv);
+        NS_ENSURE_SUCCESS(rv, rv);
+        break;
+    }
+    return rv;
+  }
+
+  // Converts a token into a int64_t
+  uint64_t Get64Value(const nsAString& aToken, nsresult* aRv) {
+    // We can't use aToken.ToInteger64() since it returns a signed 64.
+    // and that can result into an overflow.
+    nsresult rv = NS_OK;
+    uint64_t out = 0;
+    if (sscanf(NS_ConvertUTF16toUTF8(aToken).get(), "%" PRIu64, &out) == 0) {
+      rv = NS_ERROR_FAILURE;
+    }
+    *aRv = rv;
+    return out;
+  }
+
+  // Converts a token into CPU time in nanoseconds.
+  uint64_t GetCPUTime(const nsAString& aToken, nsresult* aRv) {
+    nsresult rv;
+    uint64_t value = Get64Value(aToken, &rv);
+    *aRv = rv;
+    if (NS_FAILED(rv)) {
+      return 0;
+    }
+    if (value) {
+      value = (value * NANOPERSEC) / mTicksPerSec;
+    }
+    return value;
+  }
+
+  base::ProcessId mPid;
+  int32_t mMaxIndex;
+  nsCString mFilepath;
+  ProcInfo mProcInfo;
+
+ private:
+  // Reads the stat file and puts its content in a nsString.
+  nsresult ReadFile(nsAutoString& aFileContent) {
+    RefPtr<nsLocalFile> file = new nsLocalFile(mFilepath);
+    bool exists;
+    nsresult rv = file->Exists(&exists);
+    NS_ENSURE_SUCCESS(rv, rv);
+    if (!exists) {
+      return NS_ERROR_FAILURE;
+    }
+    // /proc is a virtual file system and all files are
+    // of size 0, so GetFileSize() and related functions will
+    // return 0 - so the way to read the file is to fill a buffer
+    // of an arbitrary big size and look for the end of line char.
+    FILE* fstat;
+    if (NS_FAILED(file->OpenANSIFileDesc("r", &fstat)) || !fstat) {
+      return NS_ERROR_FAILURE;
+    }
+    char buffer[2048];
+    char* end;
+    char* start = fgets(buffer, 2048, fstat);
+    fclose(fstat);
+    if (start == nullptr) {
+      return NS_ERROR_FAILURE;
+    }
+    // let's find the end
+    end = strchr(buffer, '\n');
+    if (!end) {
+      return NS_ERROR_FAILURE;
+    }
+    aFileContent.AssignASCII(buffer, size_t(end - start));
+    return NS_OK;
+  }
+
+  int64_t mTicksPerSec;
+};
+
+// Threads have the same stat file. The only difference is its path
+// and we're getting less info in the ThreadInfo structure.
+class ThreadInfoReader final : public StatReader {
+ public:
+  ThreadInfoReader(const base::ProcessId aPid, const base::ProcessId aTid)
+      : StatReader(aPid), mTid(aTid) {
+    // Adding the thread path
+    mFilepath.Truncate();
+    mFilepath.AppendPrintf("/proc/%u/task/%u/stat", aPid, mTid);
+    mMaxIndex = 17;
+  }
+
+  nsresult ParseThread(ThreadInfo& aInfo) {
+    ProcInfo info;
+    nsresult rv = StatReader::ParseProc(info);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    aInfo.tid = mTid;
+    // Copying over the data we got from StatReader::ParseProc()
+    aInfo.cpuKernel = info.cpuKernel;
+    aInfo.cpuUser = info.cpuUser;
+    aInfo.name.Assign(info.filename);
+    return NS_OK;
+  }
+
+ private:
+  base::ProcessId mTid;
+};
+
+RefPtr<ProcInfoPromise> GetProcInfo(base::ProcessId pid, int32_t childId,
+                                    const ProcType& type) {
+  auto holder = MakeUnique<MozPromiseHolder<ProcInfoPromise>>();
+  RefPtr<ProcInfoPromise> promise = holder->Ensure(__func__);
+  nsresult rv = NS_OK;
+  nsCOMPtr<nsIEventTarget> target =
+      do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID, &rv);
+  if (NS_FAILED(rv)) {
+    NS_WARNING("Failed to get stream transport service");
+    holder->Reject(rv, __func__);
+    return promise;
+  }
+
+  RefPtr<nsIRunnable> r = NS_NewRunnableFunction(
+      __func__, [holder = std::move(holder), pid, type, childId]() {
+        // opening the stat file and reading its content
+        StatReader reader(pid);
+        ProcInfo info;
+        nsresult rv = reader.ParseProc(info);
+        if (NS_FAILED(rv)) {
+          holder->Reject(rv, __func__);
+          return;
+        }
+        // Extra info
+        info.childId = childId;
+        info.type = type;
+
+        // Let's look at the threads
+        nsCString taskPath;
+        taskPath.AppendPrintf("/proc/%u/task", pid);
+        nsAutoRef<DIR> dirHandle(opendir(taskPath.get()));
+        if (!dirHandle) {
+          // No threads ? Let's stop here and ignore the problem.
+          holder->Resolve(info, __func__);
+          return;
+        }
+
+        // If we can't read some thread info, we ignore that thread.
+        dirent* entry;
+        while ((entry = readdir(dirHandle)) != nullptr) {
+          if (entry->d_name[0] == '.') {
+            continue;
+          }
+          // Threads have a stat file, like processes.
+          nsAutoCString entryName(entry->d_name);
+          int32_t tid = entryName.ToInteger(&rv);
+          if (NS_FAILED(rv)) {
+            continue;
+          }
+          ThreadInfoReader reader(pid, tid);
+          ThreadInfo threadInfo;
+          rv = reader.ParseThread(threadInfo);
+          if (NS_FAILED(rv)) {
+            continue;
+          }
+          info.threads.AppendElement(threadInfo);
+        }
+        holder->Resolve(info, __func__);
+      });
+
+  rv = target->Dispatch(r.forget(), NS_DISPATCH_NORMAL);
+  if (NS_FAILED(rv)) {
+    NS_WARNING("Failed to dispatch the LoadDataRunnable.");
+  }
+  return promise;
+}
+
+}  // namespace mozilla
--- a/widget/gtk/moz.build
+++ b/widget/gtk/moz.build
@@ -39,16 +39,17 @@ UNIFIED_SOURCES += [
     'nsFilePicker.cpp',
     'nsGtkKeyUtils.cpp',
     'nsImageToPixbuf.cpp',
     'nsLookAndFeel.cpp',
     'nsNativeThemeGTK.cpp',
     'nsSound.cpp',
     'nsToolkit.cpp',
     'nsWidgetFactory.cpp',
+    'ProcInfo.cpp',
     'ScreenHelperGTK.cpp',
     'TaskbarProgress.cpp',
     'WakeLockListener.cpp',
     'WidgetTraceEvent.cpp',
     'WidgetUtilsGtk.cpp',
 ]
 
 SOURCES += [
--- a/widget/moz.build
+++ b/widget/moz.build
@@ -152,16 +152,17 @@ EXPORTS.mozilla += [
     'ContentEvents.h',
     'EventClassList.h',
     'EventForwards.h',
     'EventMessageList.h',
     'FontRange.h',
     'LookAndFeel.h',
     'MiscEvents.h',
     'MouseEvents.h',
+    'ProcInfo.h',
     'TextEventDispatcher.h',
     'TextEventDispatcherListener.h',
     'TextEvents.h',
     'TextRange.h',
     'TouchEvents.h',
     'VsyncDispatcher.h',
     'WidgetUtils.h',
 ]
new file mode 100644
--- /dev/null
+++ b/widget/tests/browser/.eslintrc.js
@@ -0,0 +1,7 @@
+"use strict";
+
+module.exports = {
+  "extends": [
+    "plugin:mozilla/browser-test"
+  ],
+};
new file mode 100644
--- /dev/null
+++ b/widget/tests/browser/browser.ini
@@ -0,0 +1,9 @@
+[DEFAULT]
+prefs=
+  media.rdd-process.enabled=true
+
+support-files =
+  dummy.html
+
+[browser_test_procinfo.js]
+skip-if = os == "android"
new file mode 100644
--- /dev/null
+++ b/widget/tests/browser/browser_test_procinfo.js
@@ -0,0 +1,39 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
+const ROOT_URL = "http://example.com/browser/widget/tests/browser";
+const DUMMY_URL = ROOT_URL + "/dummy.html";
+const { AppConstants } = ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
+const MAC = AppConstants.platform == "macosx";
+
+
+add_task(async function test_proc_info() {
+  waitForExplicitFinish();
+  await BrowserTestUtils.withNewTab({ gBrowser, url: DUMMY_URL},
+    async function(browser) {
+      let cpuThreads = 0;
+      let cpuUser = 0;
+      for (let z = 0; z < 10; z++) {
+        let parentProc = await ChromeUtils.requestProcInfo();
+        cpuUser += parentProc.cpuUser;
+
+        for (var x = 0; x < parentProc.threads.length; x++) {
+          cpuThreads += parentProc.threads[x].cpuUser;
+        }
+
+        for (var i = 0; i < parentProc.children.length; i++) {
+          let childProc = parentProc.children[i];
+          for (var y = 0; y < childProc.threads.length; y++) {
+            cpuThreads += childProc.threads[y].cpuUser;
+          }
+          cpuUser += childProc.cpuUser;
+        }
+      }
+      // see https://bugzilla.mozilla.org/show_bug.cgi?id=1529023
+      if (!MAC) {
+        Assert.ok(cpuThreads > 0, "Got some cpu time in the threads");
+      }
+      Assert.ok(cpuUser > 0, "Got some cpu time");
+    });
+});
new file mode 100644
--- /dev/null
+++ b/widget/tests/browser/dummy.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<html>
+<head>
+<title>Dummy test page</title>
+<meta http-equiv="Content-Type" content="text/html;charset=utf-8"></meta>
+</head>
+<body>
+<p>Dummy test page</p>
+<div id="holder" class="">Holder</div>
+<script>
+  let text = "";
+  for (let i = 0; i < 1000; i++) {
+    text += "more";
+    // eslint-disable-next-line no-unsanitized/property
+    document.getElementById("holder").innerHTML = text;
+  }
+  document.getElementById("holder").classList.add("loaded");
+</script>
+</body>
+</html>
--- a/widget/tests/moz.build
+++ b/widget/tests/moz.build
@@ -117,14 +117,15 @@ with Files("*taskbar_progress*"):
 
 with Files("*wheeltransaction*"):
     BUG_COMPONENT = ("Core", "Event Handling")
 
 
 XPCSHELL_TESTS_MANIFESTS += ['unit/xpcshell.ini']
 MOCHITEST_MANIFESTS += ['mochitest.ini']
 MOCHITEST_CHROME_MANIFESTS += ['chrome.ini']
+BROWSER_CHROME_MANIFESTS += ['browser/browser.ini']
 
 # if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
 #
 #     Test disabled because it requires the internal API. Re-enabling this test
 #     is bug 652123.
 #     CPP_UNIT_TESTS += ['TestChromeMargin']
new file mode 100644
--- /dev/null
+++ b/widget/windows/ProcInfo.cpp
@@ -0,0 +1,137 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/ProcInfo.h"
+#include <windows.h>
+#include <psapi.h>
+#include <tlhelp32.h>
+
+typedef HRESULT(WINAPI *GETTHREADDESCRIPTION)(HANDLE hThread,
+                                              PWSTR *threadDescription);
+
+namespace mozilla {
+
+uint64_t ToNanoSeconds(const FILETIME &aFileTime) {
+  // FILETIME values are 100-nanoseconds units, converting
+  ULARGE_INTEGER usec = {{aFileTime.dwLowDateTime, aFileTime.dwHighDateTime}};
+  return usec.QuadPart * 100;
+}
+
+void AppendThreads(ProcInfo *info) {
+  THREADENTRY32 te32;
+  auto getThreadDescription =
+      reinterpret_cast<GETTHREADDESCRIPTION>(::GetProcAddress(
+          ::GetModuleHandleW(L"Kernel32.dll"), "GetThreadDescription"));
+
+  // Take a snapshot of all running threads, system-wide.
+  nsAutoHandle hThreadSnap(CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0));
+  if (!hThreadSnap) {
+    return;
+  }
+  te32.dwSize = sizeof(THREADENTRY32);
+
+  // Retrieve information about the first thread,
+  // and exit if unsuccessful
+  if (!Thread32First(hThreadSnap.get(), &te32)) {
+    return;
+  }
+
+  do {
+    if (te32.th32OwnerProcessID == info->pid) {
+      nsAutoHandle hThread(
+          OpenThread(THREAD_QUERY_INFORMATION, TRUE, te32.th32ThreadID));
+      if (!hThread) {
+        continue;
+      }
+
+      FILETIME createTime, exitTime, kernelTime, userTime;
+      if (!GetThreadTimes(hThread.get(), &createTime, &exitTime, &kernelTime,
+                          &userTime)) {
+        continue;
+      }
+
+      ThreadInfo thread;
+      if (getThreadDescription) {
+        PWSTR threadName = nullptr;
+        if (getThreadDescription(hThread.get(), &threadName) && threadName) {
+          thread.name = threadName;
+        }
+        if (threadName) {
+          LocalFree(threadName);
+        }
+      }
+      thread.tid = te32.th32ThreadID;
+      thread.cpuKernel = ToNanoSeconds(kernelTime);
+      thread.cpuUser = ToNanoSeconds(userTime);
+      info->threads.AppendElement(thread);
+    }
+  } while (Thread32Next(hThreadSnap.get(), &te32));
+}
+
+RefPtr<ProcInfoPromise> GetProcInfo(base::ProcessId pid, int32_t childId,
+                                    const ProcType &type) {
+  auto holder = MakeUnique<MozPromiseHolder<ProcInfoPromise>>();
+  RefPtr<ProcInfoPromise> promise = holder->Ensure(__func__);
+
+  nsresult rv = NS_OK;
+  nsCOMPtr<nsIEventTarget> target =
+      do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID, &rv);
+  if (NS_FAILED(rv)) {
+    NS_WARNING("Failed to get stream transport service");
+    holder->Reject(rv, __func__);
+    return promise;
+  }
+
+  RefPtr<nsIRunnable> r = NS_NewRunnableFunction(
+      __func__, [holder = std::move(holder), pid, type, childId]() -> void {
+        nsAutoHandle handle(OpenProcess(
+            PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid));
+
+        if (!handle) {
+          holder->Reject(NS_ERROR_FAILURE, __func__);
+          return;
+        }
+
+        wchar_t filename[MAX_PATH];
+        if (GetProcessImageFileNameW(handle.get(), filename, MAX_PATH) == 0) {
+          holder->Reject(NS_ERROR_FAILURE, __func__);
+          return;
+        }
+        FILETIME createTime, exitTime, kernelTime, userTime;
+        if (!GetProcessTimes(handle.get(), &createTime, &exitTime, &kernelTime,
+                             &userTime)) {
+          holder->Reject(NS_ERROR_FAILURE, __func__);
+          return;
+        }
+        PROCESS_MEMORY_COUNTERS memoryCounters;
+        if (!GetProcessMemoryInfo(handle.get(),
+                                  (PPROCESS_MEMORY_COUNTERS)&memoryCounters,
+                                  sizeof(memoryCounters))) {
+          holder->Reject(NS_ERROR_FAILURE, __func__);
+          return;
+        }
+        ProcInfo info;
+        info.pid = pid;
+        info.childId = childId;
+        info.type = type;
+        info.filename.Assign(filename);
+        info.cpuKernel = ToNanoSeconds(kernelTime);
+        info.cpuUser = ToNanoSeconds(userTime);
+        info.residentSetSize = memoryCounters.WorkingSetSize;
+        info.virtualMemorySize = memoryCounters.PagefileUsage;
+        AppendThreads(&info);
+        holder->Resolve(info, __func__);
+      });
+
+  rv = target->Dispatch(r.forget(), NS_DISPATCH_NORMAL);
+  if (NS_FAILED(rv)) {
+    NS_WARNING("Failed to dispatch the LoadDataRunnable.");
+  }
+
+  return promise;
+}
+
+}  // namespace mozilla
--- a/widget/windows/moz.build
+++ b/widget/windows/moz.build
@@ -61,16 +61,17 @@ UNIFIED_SOURCES += [
     'nsSound.cpp',
     'nsToolkit.cpp',
     'nsUXThemeData.cpp',
     'nsWindow.cpp',
     'nsWindowBase.cpp',
     'nsWindowDbg.cpp',
     'nsWindowGfx.cpp',
     'nsWinGesture.cpp',
+    'ProcInfo.cpp',
     'ScreenHelperWin.cpp',
     'TaskbarPreview.cpp',
     'TaskbarPreviewButton.cpp',
     'TaskbarTabPreview.cpp',
     'TaskbarWindowPreview.cpp',
     'WidgetTraceEvent.cpp',
     'WinCompositorWindowThread.cpp',
     'WindowHook.cpp',