chromium/chrome/browser/feedback/android/process_id_feedback_source.cc

// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/40285824): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif

#include "chrome/browser/feedback/android/process_id_feedback_source.h"

#include "base/android/jni_array.h"
#include "base/functional/bind.h"
#include "base/types/fixed_array.h"
#include "content/public/browser/browser_child_process_host_iterator.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_data.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/content_features.h"
#include "content/public/common/process_type.h"

// Must come after all headers that specialize FromJniType() / ToJniType().
#include "chrome/browser/feedback/android/jni_headers/ProcessIdFeedbackSource_jni.h"

using base::android::AttachCurrentThread;
using base::android::JavaParamRef;
using base::android::ScopedJavaLocalRef;
using content::BrowserThread;

namespace chrome {
namespace android {

int64_t JNI_ProcessIdFeedbackSource_GetCurrentPid(JNIEnv* env) {
  return base::GetCurrentProcId();
}

void JNI_ProcessIdFeedbackSource_Start(JNIEnv* env,
                                       const JavaParamRef<jobject>& obj) {
  scoped_refptr<ProcessIdFeedbackSource> source =
      new ProcessIdFeedbackSource(env, obj);
  source->PrepareProcessIds();
}

ProcessIdFeedbackSource::ProcessIdFeedbackSource(
    JNIEnv* env,
    const JavaParamRef<jobject>& obj)
    : java_ref_(env, obj) {}

ProcessIdFeedbackSource::~ProcessIdFeedbackSource() {}

void ProcessIdFeedbackSource::PrepareProcessIds() {
  // Browser child process info needs accessing on IO thread, while renderer
  // process info on UI thread.
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  for (content::RenderProcessHost::iterator it(
           content::RenderProcessHost::AllHostsIterator());
       !it.IsAtEnd(); it.Advance()) {
    content::RenderProcessHost* host = it.GetCurrentValue();
    process_ids_[content::PROCESS_TYPE_RENDERER].push_back(
        host->GetProcess().Pid());
  }

  for (content::BrowserChildProcessHostIterator iter; !iter.Done(); ++iter)
    process_ids_[iter.GetData().process_type].push_back(
        iter.GetData().GetProcess().Handle());

  JNIEnv* env = AttachCurrentThread();
  ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
  DCHECK(!obj.is_null());
  Java_ProcessIdFeedbackSource_prepareCompleted(
      env, obj, reinterpret_cast<intptr_t>(this));
}

ScopedJavaLocalRef<jlongArray> ProcessIdFeedbackSource::GetProcessIdsForType(
    JNIEnv* env,
    const JavaParamRef<jobject>& obj,
    jint process_type) {
  switch (process_type) {
    case content::PROCESS_TYPE_RENDERER:
    case content::PROCESS_TYPE_UTILITY:
    case content::PROCESS_TYPE_GPU:
      break;
    default:
      NOTREACHED_IN_MIGRATION() << "Unsupported process type.";
  }
  size_t size = process_ids_[process_type].size();

  base::FixedArray<jlong> pids(size);
  for (size_t i = 0; i < size; i++)
    pids[i] = process_ids_[process_type][i];

  return base::android::ToJavaLongArray(env, pids.data(), size);
}

}  // namespace android
}  // namespace chrome