// Copyright (c) 2018 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 "tests/cefclient/browser/main_message_loop_multithreaded_gtk.h"

#include <X11/Xlib.h>
#include <gtk/gtkmain.h>

#include "include/base/cef_bind.h"
#include "include/base/cef_logging.h"
#include "include/wrapper/cef_closure_task.h"

namespace client {

namespace {

base::Lock g_global_lock;
base::PlatformThreadId g_global_lock_thread = kInvalidPlatformThreadId;

void lock_enter() {
  // The GDK lock is not reentrant, so check that we're using it correctly.
  // See comments on ScopedGdkThreadsEnter.
  base::PlatformThreadId current_thread = base::PlatformThread::CurrentId();
  CHECK(current_thread != g_global_lock_thread);

  g_global_lock.Acquire();
  g_global_lock_thread = current_thread;
}

void lock_leave() {
  g_global_lock_thread = kInvalidPlatformThreadId;
  g_global_lock.Release();
}

// Same as g_idle_add() but specifying the GMainContext.
guint idle_add(GMainContext* main_context,
               GSourceFunc function,
               gpointer data) {
  GSource* source = g_idle_source_new();
  g_source_set_callback(source, function, data, nullptr);
  guint id = g_source_attach(source, main_context);
  g_source_unref(source);
  return id;
}

// Same as g_timeout_add() but specifying the GMainContext.
guint timeout_add(GMainContext* main_context,
                  guint interval,
                  GSourceFunc function,
                  gpointer data) {
  GSource* source = g_timeout_source_new(interval);
  g_source_set_callback(source, function, data, nullptr);
  guint id = g_source_attach(source, main_context);
  g_source_unref(source);
  return id;
}

}  // namespace

MainMessageLoopMultithreadedGtk::MainMessageLoopMultithreadedGtk()
    : thread_id_(base::PlatformThread::CurrentId()) {
  // Initialize Xlib support for concurrent threads. This function must be the
  // first Xlib function a multi-threaded program calls, and it must complete
  // before any other Xlib call is made.
  CHECK(XInitThreads() != 0);

  // Initialize GDK thread support. See comments on ScopedGdkThreadsEnter.
  gdk_threads_set_lock_functions(lock_enter, lock_leave);
  gdk_threads_init();
}

MainMessageLoopMultithreadedGtk::~MainMessageLoopMultithreadedGtk() {
  DCHECK(RunsTasksOnCurrentThread());
  DCHECK(queued_tasks_.empty());
}

int MainMessageLoopMultithreadedGtk::Run() {
  DCHECK(RunsTasksOnCurrentThread());

  // Chromium uses the default GLib context so we create our own context and
  // make it the default for this thread.
  main_context_ = g_main_context_new();
  g_main_context_push_thread_default(main_context_);

  main_loop_ = g_main_loop_new(main_context_, TRUE);

  // Check the queue when GTK is idle, or at least every 100ms.
  // TODO(cef): It might be more efficient to use input functions
  // (gdk_input_add) and trigger by writing to an fd.
  idle_add(main_context_, MainMessageLoopMultithreadedGtk::TriggerRunTasks,
           this);
  timeout_add(main_context_, 100,
              MainMessageLoopMultithreadedGtk::TriggerRunTasks, this);

  // Block until g_main_loop_quit().
  g_main_loop_run(main_loop_);

  // Release GLib resources.
  g_main_loop_unref(main_loop_);
  main_loop_ = nullptr;

  g_main_context_pop_thread_default(main_context_);
  g_main_context_unref(main_context_);
  main_context_ = nullptr;

  return 0;
}

void MainMessageLoopMultithreadedGtk::Quit() {
  PostTask(CefCreateClosureTask(base::Bind(
      &MainMessageLoopMultithreadedGtk::DoQuit, base::Unretained(this))));
}

void MainMessageLoopMultithreadedGtk::PostTask(CefRefPtr<CefTask> task) {
  base::AutoLock lock_scope(lock_);

  // Queue the task.
  queued_tasks_.push(task);
}

bool MainMessageLoopMultithreadedGtk::RunsTasksOnCurrentThread() const {
  return (thread_id_ == base::PlatformThread::CurrentId());
}

// static
int MainMessageLoopMultithreadedGtk::TriggerRunTasks(void* self) {
  static_cast<MainMessageLoopMultithreadedGtk*>(self)->RunTasks();
  return G_SOURCE_CONTINUE;
}

void MainMessageLoopMultithreadedGtk::RunTasks() {
  DCHECK(RunsTasksOnCurrentThread());

  std::queue<CefRefPtr<CefTask>> tasks;

  {
    base::AutoLock lock_scope(lock_);
    tasks.swap(queued_tasks_);
  }

  // Execute all queued tasks.
  while (!tasks.empty()) {
    CefRefPtr<CefTask> task = tasks.front();
    tasks.pop();
    task->Execute();
  }
}

void MainMessageLoopMultithreadedGtk::DoQuit() {
  DCHECK(RunsTasksOnCurrentThread());
  g_main_loop_quit(main_loop_);
}

}  // namespace client
