Inject coverage output file into sandboxed processes.

The browser opens a file and sends it to the child process so that the
child can write its coverage data to the file.

This code is only enabled in coverage builds, which are not used in
production.

Bug: 972232
Change-Id: Ib5d0bd7de9e5bd8c41faed71ad25a7456ada73b5
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1725128
Commit-Queue: Sajjad Mirza <[email protected]>
Reviewed-by: Alex Moshchuk <[email protected]>
Reviewed-by: Ken Rockot <[email protected]>
Reviewed-by: Daniel Cheng <[email protected]>
Cr-Commit-Position: refs/heads/master@{#687101}
diff --git a/content/common/coverage_utils.cc b/content/common/coverage_utils.cc
new file mode 100644
index 0000000..00794b2
--- /dev/null
+++ b/content/common/coverage_utils.cc
@@ -0,0 +1,53 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/coverage_utils.h"
+
+#include <memory>
+
+#include "base/base_paths.h"
+#include "base/environment.h"
+#include "base/files/file.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/logging.h"
+#include "base/path_service.h"
+#include "base/rand_util.h"
+#include "base/strings/strcat.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/threading/thread_restrictions.h"
+
+namespace content {
+
+base::File OpenCoverageFile() {
+  base::ScopedAllowBlockingForTesting allows_blocking;
+  std::unique_ptr<base::Environment> env(base::Environment::Create());
+  std::string prof_template;
+  base::FilePath path;
+  if (env->GetVar("LLVM_PROFILE_FILE", &prof_template)) {
+    path = base::FilePath(prof_template).DirName();
+    base::CreateDirectory(path);
+  } else {
+    base::PathService::Get(base::DIR_CURRENT, &path);
+  }
+
+  // sajjadm@ and liaoyuke@ experimentally determined that a size 4 pool works
+  // well for the coverage builder.
+  int pool_index = base::RandInt(0, 3);
+  std::string filename = base::StrCat(
+      {"child_pool-", base::NumberToString(pool_index), ".profraw"});
+  path = path.Append(filename);
+  uint32_t flags = base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ |
+                   base::File::FLAG_WRITE;
+
+  base::File file(path, flags);
+  if (!file.IsValid()) {
+    LOG(ERROR) << "Opening file: " << path << " failed with "
+               << file.error_details();
+  }
+
+  return file;
+}
+
+}  // namespace content