// Copyright (c) 2013 The Chromium Embedded Framework 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 "libcef/common/task_runner_impl.h"
#include "libcef/browser/content_browser_client.h"
#include "libcef/common/content_client.h"
#include "libcef/renderer/content_renderer_client.h"

#include "base/bind.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_launcher_utils.h"

using content::BrowserThread;

// CefTaskRunner

// static
CefRefPtr<CefTaskRunner> CefTaskRunner::GetForCurrentThread() {
  scoped_refptr<base::SingleThreadTaskRunner> task_runner =
      CefTaskRunnerImpl::GetCurrentTaskRunner();
  if (task_runner.get())
    return new CefTaskRunnerImpl(task_runner);
  return nullptr;
}

// static
CefRefPtr<CefTaskRunner> CefTaskRunner::GetForThread(CefThreadId threadId) {
  scoped_refptr<base::SingleThreadTaskRunner> task_runner =
      CefTaskRunnerImpl::GetTaskRunner(threadId);
  if (task_runner.get())
    return new CefTaskRunnerImpl(task_runner);

  LOG(WARNING) << "Invalid thread id " << threadId;
  return nullptr;
}

// CefTaskRunnerImpl

CefTaskRunnerImpl::CefTaskRunnerImpl(
    scoped_refptr<base::SingleThreadTaskRunner> task_runner)
    : task_runner_(task_runner) {
  DCHECK(task_runner_.get());
}

// static
scoped_refptr<base::SingleThreadTaskRunner> CefTaskRunnerImpl::GetTaskRunner(
    CefThreadId threadId) {
  // Render process.
  if (threadId == TID_RENDERER) {
    CefContentRendererClient* client = CefContentRendererClient::Get();
    if (client)
      return client->render_task_runner();
    return nullptr;
  }

  // Browser process.
  CefContentBrowserClient* client = CefContentBrowserClient::Get();
  if (!client)
    return nullptr;

  int id = -1;
  switch (threadId) {
    case TID_UI:
      id = BrowserThread::UI;
      break;
    case TID_FILE_BACKGROUND:
      return client->background_task_runner();
    case TID_FILE_USER_VISIBLE:
      return client->user_visible_task_runner();
    case TID_FILE_USER_BLOCKING:
      return client->user_blocking_task_runner();
    case TID_PROCESS_LAUNCHER:
      return content::GetProcessLauncherTaskRunner();
    case TID_IO:
      id = BrowserThread::IO;
      break;
    default:
      break;
  };

  if (id >= 0 &&
      BrowserThread::IsThreadInitialized(static_cast<BrowserThread::ID>(id))) {
    // Specify USER_BLOCKING so that BrowserTaskExecutor::GetTaskRunner always
    // gives us the same TaskRunner object.
    return base::CreateSingleThreadTaskRunner(
        {static_cast<BrowserThread::ID>(id),
         base::TaskPriority::USER_BLOCKING});
  }

  return nullptr;
}

// static
scoped_refptr<base::SingleThreadTaskRunner>
CefTaskRunnerImpl::GetCurrentTaskRunner() {
  scoped_refptr<base::SingleThreadTaskRunner> task_runner;

  // For named browser process threads return the same TaskRunner as
  // GetTaskRunner(). Otherwise BelongsToThread() will return incorrect results.
  BrowserThread::ID current_id;
  if (BrowserThread::GetCurrentThreadIdentifier(&current_id) &&
      BrowserThread::IsThreadInitialized(current_id)) {
    // Specify USER_BLOCKING so that BrowserTaskExecutor::GetTaskRunner always
    // gives us the same TaskRunner object.
    task_runner = base::CreateSingleThreadTaskRunner(
        {current_id, base::TaskPriority::USER_BLOCKING});
  }

  if (!task_runner.get()) {
    // Check for a MessageLoopProxy. This covers all of the named browser and
    // render process threads, plus a few extra.
    task_runner = base::ThreadTaskRunnerHandle::Get();
  }

  if (!task_runner.get()) {
    // Check for a WebWorker thread.
    CefContentRendererClient* client = CefContentRendererClient::Get();
    if (client)
      task_runner = client->GetCurrentTaskRunner();
  }

  return task_runner;
}

bool CefTaskRunnerImpl::IsSame(CefRefPtr<CefTaskRunner> that) {
  CefTaskRunnerImpl* impl = static_cast<CefTaskRunnerImpl*>(that.get());
  return (impl && task_runner_ == impl->task_runner_);
}

bool CefTaskRunnerImpl::BelongsToCurrentThread() {
  return task_runner_->RunsTasksInCurrentSequence();
}

bool CefTaskRunnerImpl::BelongsToThread(CefThreadId threadId) {
  scoped_refptr<base::SingleThreadTaskRunner> task_runner =
      GetTaskRunner(threadId);
  return (task_runner_ == task_runner);
}

bool CefTaskRunnerImpl::PostTask(CefRefPtr<CefTask> task) {
  return task_runner_->PostTask(FROM_HERE,
                                base::Bind(&CefTask::Execute, task.get()));
}

bool CefTaskRunnerImpl::PostDelayedTask(CefRefPtr<CefTask> task,
                                        int64 delay_ms) {
  return task_runner_->PostDelayedTask(
      FROM_HERE, base::Bind(&CefTask::Execute, task.get()),
      base::TimeDelta::FromMilliseconds(delay_ms));
}
