// Copyright (c) 2012 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/browser/profiler_controller_impl.h"

#include "base/bind.h"
#include "base/process/process_handle.h"
#include "base/tracked_objects.h"
#include "content/common/child_process_messages.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/profiler_subscriber.h"
#include "content/public/browser/render_process_host.h"

namespace content {

ProfilerController* ProfilerController::GetInstance() {
  return ProfilerControllerImpl::GetInstance();
}

ProfilerControllerImpl* ProfilerControllerImpl::GetInstance() {
  return base::Singleton<ProfilerControllerImpl>::get();
}

ProfilerControllerImpl::ProfilerControllerImpl() : subscriber_(NULL) {
}

ProfilerControllerImpl::~ProfilerControllerImpl() {
}

void ProfilerControllerImpl::OnPendingProcesses(int sequence_number,
                                                int pending_processes,
                                                bool end) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (subscriber_)
    subscriber_->OnPendingProcesses(sequence_number, pending_processes, end);
}

void ProfilerControllerImpl::OnProfilerDataCollected(
    int sequence_number,
    const tracked_objects::ProcessDataSnapshot& profiler_data,
    content::ProcessType process_type) {
  if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
    BrowserThread::PostTask(
        BrowserThread::UI, FROM_HERE,
        base::Bind(&ProfilerControllerImpl::OnProfilerDataCollected,
                   base::Unretained(this),
                   sequence_number,
                   profiler_data,
                   process_type));
    return;
  }

  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if (subscriber_) {
    subscriber_->OnProfilerDataCollected(sequence_number, profiler_data,
                                         process_type);
  }
}

void ProfilerControllerImpl::Register(ProfilerSubscriber* subscriber) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(!subscriber_);
  subscriber_ = subscriber;
}

void ProfilerControllerImpl::Unregister(const ProfilerSubscriber* subscriber) {
  DCHECK_EQ(subscriber_, subscriber);
  subscriber_ = NULL;
}

void ProfilerControllerImpl::GetProfilerDataFromChildProcesses(
    int sequence_number,
    int current_profiling_phase) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  int pending_processes = 0;
  for (BrowserChildProcessHostIterator iter; !iter.Done(); ++iter) {
    // In some cases, there may be no child process of the given type (for
    // example, the GPU process may not exist and there may instead just be a
    // GPU thread in the browser process). If that's the case, then the process
    // handle will be base::kNullProcessHandle and we shouldn't ask it for data.
    if (iter.GetData().handle == base::kNullProcessHandle)
      continue;

    ++pending_processes;
    if (!iter.Send(new ChildProcessMsg_GetChildProfilerData(
            sequence_number, current_profiling_phase))) {
      --pending_processes;
    }
  }

  BrowserThread::PostTask(
      BrowserThread::UI,
      FROM_HERE,
      base::Bind(
          &ProfilerControllerImpl::OnPendingProcesses,
          base::Unretained(this),
          sequence_number,
          pending_processes,
          true));
}

// static
void ProfilerControllerImpl::NotifyChildProcessesOfProfilingPhaseCompletion(
    int profiling_phase) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  for (BrowserChildProcessHostIterator iter; !iter.Done(); ++iter) {
    // In some cases, there may be no child process of the given type (for
    // example, the GPU process may not exist and there may instead just be a
    // GPU thread in the browser process). If that's the case, then the process
    // handle will be base::kNullProcessHandle and we shouldn't send it a
    // message.
    if (iter.GetData().handle == base::kNullProcessHandle)
      continue;

    iter.Send(new ChildProcessMsg_ProfilingPhaseCompleted(profiling_phase));
  }
}

void ProfilerControllerImpl::GetProfilerData(int sequence_number,
                                             int current_profiling_phase) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  // Iterates through renderers in UI thread, and through other child processes
  // in IO thread, and send them GetChildProfilerData message. Renderers have to
  // be contacted from UI thread, and other processes - from IO thread.
  int pending_processes = 0;
  for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator());
       !it.IsAtEnd(); it.Advance()) {
    ++pending_processes;
    if (!it.GetCurrentValue()->Send(new ChildProcessMsg_GetChildProfilerData(
            sequence_number, current_profiling_phase))) {
      --pending_processes;
    }
  }
  OnPendingProcesses(sequence_number, pending_processes, false);

  BrowserThread::PostTask(
      BrowserThread::IO, FROM_HERE,
      base::Bind(&ProfilerControllerImpl::GetProfilerDataFromChildProcesses,
                 base::Unretained(this), sequence_number,
                 current_profiling_phase));
}

void ProfilerControllerImpl::OnProfilingPhaseCompleted(int profiling_phase) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  // Iterates through renderers in UI thread, and through other child processes
  // in IO thread, and send them OnProfilingPhase message. Renderers have to be
  // contacted from UI thread, and other processes - from IO thread.
  for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator());
       !it.IsAtEnd(); it.Advance()) {
    it.GetCurrentValue()->Send(
        new ChildProcessMsg_ProfilingPhaseCompleted(profiling_phase));
  }

  BrowserThread::PostTask(
      BrowserThread::IO, FROM_HERE,
      base::Bind(&ProfilerControllerImpl::
                     NotifyChildProcessesOfProfilingPhaseCompletion,
                 profiling_phase));
}

}  // namespace content
