Bug 1362800 - Add a way to get the profile as an array buffer. r?njn draft
authorMarkus Stange <mstange@themasta.com>
Wed, 10 May 2017 17:08:46 -0400
changeset 575783 63295ae352ae7b918fe1703c3140774b16034587
parent 575782 cb9739e2b1c50d579b7620c7d59c34fd3c62f3b4
child 575784 5985c1d1e736ca2d4797cec19660860c96f6c1c4
child 575980 dcc76faa07776e893ce8c02ac849c2ed2288a192
push id58166
push userbmo:mstange@themasta.com
push dateWed, 10 May 2017 21:13:53 +0000
reviewersnjn
bugs1362800
milestone55.0a1
Bug 1362800 - Add a way to get the profile as an array buffer. r?njn MozReview-Commit-ID: 6qpcm3LQn1r
tools/profiler/gecko/nsIProfiler.idl
tools/profiler/gecko/nsProfiler.cpp
--- a/tools/profiler/gecko/nsIProfiler.idl
+++ b/tools/profiler/gecko/nsIProfiler.idl
@@ -52,16 +52,19 @@ interface nsIProfiler : nsISupports
    * samples taken at >= aSinceTime.
    */
   [implicit_jscontext]
   jsval getProfileData([optional] in double aSinceTime);
 
   [implicit_jscontext]
   nsISupports getProfileDataAsync([optional] in double aSinceTime);
 
+  [implicit_jscontext]
+  nsISupports getProfileDataAsArrayBuffer([optional] in double aSinceTime);
+
   void dumpProfileToFileAsync(in ACString aFilename,
                               [optional] in double aSinceTime);
 
   boolean IsActive();
   void GetFeatures(out uint32_t aCount, [retval, array, size_is(aCount)] out string aFeatures);
 
   /**
    * The starting parameters that were sent to the profiler for sampling.
--- a/tools/profiler/gecko/nsProfiler.cpp
+++ b/tools/profiler/gecko/nsProfiler.cpp
@@ -17,16 +17,17 @@
 #include "nsIInterfaceRequestor.h"
 #include "nsILoadContext.h"
 #include "nsIWebNavigation.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "shared-libraries.h"
 #include "js/Value.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/dom/Promise.h"
+#include "mozilla/dom/TypedArray.h"
 #include "ProfileGatherer.h"
 #include "nsLocalFile.h"
 #include "platform.h"
 
 using namespace mozilla;
 
 using dom::AutoJSAPI;
 using dom::Promise;
@@ -255,24 +256,25 @@ nsProfiler::GetProfileDataAsync(double a
   if (!mGatherer) {
     return NS_ERROR_FAILURE;
   }
 
   if (NS_WARN_IF(!aCx)) {
     return NS_ERROR_FAILURE;
   }
 
-  nsIGlobalObject* go = xpc::NativeGlobal(JS::CurrentGlobalOrNull(aCx));
+  nsIGlobalObject* globalObject =
+    xpc::NativeGlobal(JS::CurrentGlobalOrNull(aCx));
 
-  if (NS_WARN_IF(!go)) {
+  if (NS_WARN_IF(!globalObject)) {
     return NS_ERROR_FAILURE;
   }
 
   ErrorResult result;
-  RefPtr<Promise> promise = Promise::Create(go, result);
+  RefPtr<Promise> promise = Promise::Create(globalObject, result);
   if (NS_WARN_IF(result.Failed())) {
     return result.StealNSResult();
   }
 
   mGatherer->Start(aSinceTime)->Then(
     AbstractThread::MainThread(), __func__,
     [promise](nsCString aResult) {
       AutoJSAPI jsapi;
@@ -309,16 +311,72 @@ nsProfiler::GetProfileDataAsync(double a
       promise->MaybeReject(aRv);
     });
 
   promise.forget(aPromise);
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsProfiler::GetProfileDataAsArrayBuffer(double aSinceTime, JSContext* aCx,
+                                        nsISupports** aPromise)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  if (!mGatherer) {
+    return NS_ERROR_FAILURE;
+  }
+
+  if (NS_WARN_IF(!aCx)) {
+    return NS_ERROR_FAILURE;
+  }
+
+  nsIGlobalObject* globalObject =
+    xpc::NativeGlobal(JS::CurrentGlobalOrNull(aCx));
+
+  if (NS_WARN_IF(!globalObject)) {
+    return NS_ERROR_FAILURE;
+  }
+
+  ErrorResult result;
+  RefPtr<Promise> promise = Promise::Create(globalObject, result);
+  if (NS_WARN_IF(result.Failed())) {
+    return result.StealNSResult();
+  }
+
+  mGatherer->Start(aSinceTime)->Then(
+    AbstractThread::MainThread(), __func__,
+    [promise](nsCString aResult) {
+      AutoJSAPI jsapi;
+      if (NS_WARN_IF(!jsapi.Init(promise->GlobalJSObject()))) {
+        // We're really hosed if we can't get a JS context for some reason.
+        promise->MaybeReject(NS_ERROR_DOM_UNKNOWN_ERR);
+        return;
+      }
+
+      JSContext* cx = jsapi.cx();
+      JSObject* typedArray =
+        dom::ArrayBuffer::Create(cx, aResult.Length(),
+                                 reinterpret_cast<const uint8_t*>(aResult.Data()));
+      if (typedArray) {
+        JS::RootedValue val(cx, JS::ObjectValue(*typedArray));
+        promise->MaybeResolve(val);
+      } else {
+        promise->MaybeReject(NS_ERROR_OUT_OF_MEMORY);
+      }
+    },
+    [promise](nsresult aRv) {
+      promise->MaybeReject(aRv);
+    });
+
+  promise.forget(aPromise);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsProfiler::DumpProfileToFileAsync(const nsACString& aFilename,
                                    double aSinceTime)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (!mGatherer) {
     return NS_ERROR_FAILURE;
   }