summaryrefslogtreecommitdiffstats
path: root/tools/code-coverage/nsCodeCoverage.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/code-coverage/nsCodeCoverage.cpp')
-rw-r--r--tools/code-coverage/nsCodeCoverage.cpp96
1 files changed, 96 insertions, 0 deletions
diff --git a/tools/code-coverage/nsCodeCoverage.cpp b/tools/code-coverage/nsCodeCoverage.cpp
new file mode 100644
index 0000000000..5d7ed1927c
--- /dev/null
+++ b/tools/code-coverage/nsCodeCoverage.cpp
@@ -0,0 +1,96 @@
+/* -*- Mode: C++; tab-width: 2; 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/. */
+
+#include "nsCodeCoverage.h"
+#include "mozilla/CodeCoverageHandler.h"
+#include "mozilla/Unused.h"
+#include "mozilla/dom/ContentParent.h"
+#include "mozilla/dom/Promise.h"
+
+using mozilla::dom::ContentParent;
+using mozilla::dom::Promise;
+
+NS_IMPL_ISUPPORTS(nsCodeCoverage, nsICodeCoverage)
+
+nsCodeCoverage::nsCodeCoverage() {}
+
+nsCodeCoverage::~nsCodeCoverage() {}
+
+enum RequestType { Flush };
+
+class ProcessCount final {
+ NS_INLINE_DECL_REFCOUNTING(ProcessCount);
+
+ public:
+ explicit ProcessCount(uint32_t c) : mCount(c) {}
+ operator uint32_t() const { return mCount; }
+ ProcessCount& operator--() {
+ mCount--;
+ return *this;
+ }
+
+ private:
+ ~ProcessCount() {}
+ uint32_t mCount;
+};
+
+namespace {
+
+nsresult Request(JSContext* cx, Promise** aPromise, RequestType requestType) {
+ MOZ_ASSERT(XRE_IsParentProcess());
+ MOZ_ASSERT(NS_IsMainThread());
+
+ nsIGlobalObject* global = xpc::CurrentNativeGlobal(cx);
+ if (NS_WARN_IF(!global)) {
+ return NS_ERROR_FAILURE;
+ }
+
+ mozilla::ErrorResult result;
+ RefPtr<Promise> promise = Promise::Create(global, result);
+ if (NS_WARN_IF(result.Failed())) {
+ return result.StealNSResult();
+ }
+
+ uint32_t processCount = 0;
+ for (auto* cp : ContentParent::AllProcesses(ContentParent::eLive)) {
+ mozilla::Unused << cp;
+ ++processCount;
+ }
+
+ if (requestType == RequestType::Flush) {
+ mozilla::CodeCoverageHandler::FlushCounters();
+ }
+
+ if (processCount == 0) {
+ promise->MaybeResolveWithUndefined();
+ } else {
+ RefPtr<ProcessCount> processCountHolder(new ProcessCount(processCount));
+
+ auto resolve = [processCountHolder, promise](bool unused) {
+ if (--(*processCountHolder) == 0) {
+ promise->MaybeResolveWithUndefined();
+ }
+ };
+
+ auto reject = [promise](mozilla::ipc::ResponseRejectReason&& aReason) {
+ promise->MaybeReject(NS_ERROR_FAILURE);
+ };
+
+ for (auto* cp : ContentParent::AllProcesses(ContentParent::eLive)) {
+ if (requestType == RequestType::Flush) {
+ cp->SendFlushCodeCoverageCounters(resolve, reject);
+ }
+ }
+ }
+
+ promise.forget(aPromise);
+ return NS_OK;
+}
+
+} // anonymous namespace
+
+NS_IMETHODIMP nsCodeCoverage::FlushCounters(JSContext* cx, Promise** aPromise) {
+ return Request(cx, aPromise, RequestType::Flush);
+}