// 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/browser_thread_impl.h"

#include <string>
#include <utility>

#include "base/atomicops.h"
#include "base/bind.h"
#include "base/compiler_specific.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/platform_thread.h"
#include "build/build_config.h"
#include "content/public/browser/browser_thread_delegate.h"
#include "content/public/browser/content_browser_client.h"
#include "net/disk_cache/simple/simple_backend_impl.h"

#if defined(OS_ANDROID)
#include "base/android/jni_android.h"
#endif

namespace content {

namespace {

// Friendly names for the well-known threads.
static const char* const g_browser_thread_names[BrowserThread::ID_COUNT] = {
  "",  // UI (name assembled in browser_main.cc).
  "Chrome_ProcessLauncherThread",  // PROCESS_LAUNCHER
  "Chrome_IOThread",  // IO
};

static const char* GetThreadName(BrowserThread::ID thread) {
  if (BrowserThread::UI < thread && thread < BrowserThread::ID_COUNT)
    return g_browser_thread_names[thread];
  if (thread == BrowserThread::UI)
    return "Chrome_UIThread";
  return "Unknown Thread";
}

// An implementation of SingleThreadTaskRunner to be used in conjunction
// with BrowserThread.
// TODO(gab): Consider replacing this with |g_globals->task_runners| -- only
// works if none are requested before starting the threads.
class BrowserThreadTaskRunner : public base::SingleThreadTaskRunner {
 public:
  explicit BrowserThreadTaskRunner(BrowserThread::ID identifier)
      : id_(identifier) {}

  // SingleThreadTaskRunner implementation.
  bool PostDelayedTask(const base::Location& from_here,
                       base::OnceClosure task,
                       base::TimeDelta delay) override {
    return BrowserThread::PostDelayedTask(id_, from_here, std::move(task),
                                          delay);
  }

  bool PostNonNestableDelayedTask(const base::Location& from_here,
                                  base::OnceClosure task,
                                  base::TimeDelta delay) override {
    return BrowserThread::PostNonNestableDelayedTask(id_, from_here,
                                                     std::move(task), delay);
  }

  bool RunsTasksInCurrentSequence() const override {
    return BrowserThread::CurrentlyOn(id_);
  }

 protected:
  ~BrowserThreadTaskRunner() override {}

 private:
  BrowserThread::ID id_;
  DISALLOW_COPY_AND_ASSIGN(BrowserThreadTaskRunner);
};

// A separate helper is used just for the task runners, in order to avoid
// needing to initialize the globals to create a task runner.
struct BrowserThreadTaskRunners {
  BrowserThreadTaskRunners() {
    for (int i = 0; i < BrowserThread::ID_COUNT; ++i) {
      proxies[i] =
          new BrowserThreadTaskRunner(static_cast<BrowserThread::ID>(i));
    }
  }

  scoped_refptr<base::SingleThreadTaskRunner> proxies[BrowserThread::ID_COUNT];
};

base::LazyInstance<BrowserThreadTaskRunners>::Leaky g_task_runners =
    LAZY_INSTANCE_INITIALIZER;

// State of a given BrowserThread::ID in chronological order throughout the
// browser process' lifetime.
enum BrowserThreadState {
  // BrowserThread::ID isn't associated with anything yet.
  UNINITIALIZED = 0,
  // BrowserThread::ID is associated with a BrowserThreadImpl instance but the
  // underlying thread hasn't started yet.
  INITIALIZED,
  // BrowserThread::ID is associated to a TaskRunner and is accepting tasks.
  RUNNING,
  // BrowserThread::ID no longer accepts tasks.
  SHUTDOWN
};

using BrowserThreadDelegateAtomicPtr = base::subtle::AtomicWord;

struct BrowserThreadGlobals {
  // This lock protects |task_runners| and |states|. Do not read or modify those
  // arrays without holding this lock. Do not block while holding this lock.
  base::Lock lock;

  // This array is filled either as the underlying threads start and invoke
  // Init() or in RedirectThreadIDToTaskRunner() for threads that are being
  // redirected. It is not emptied during shutdown in order to support
  // RunsTasksInCurrentSequence() until the very end.
  scoped_refptr<base::SingleThreadTaskRunner>
      task_runners[BrowserThread::ID_COUNT];

  // Holds the state of each BrowserThread::ID.
  BrowserThreadState states[BrowserThread::ID_COUNT] = {};

  // Only atomic operations are used on this pointer. The delegate isn't owned
  // by BrowserThreadGlobals, rather by whoever calls
  // BrowserThread::SetIOThreadDelegate.
  BrowserThreadDelegateAtomicPtr io_thread_delegate = 0;
};

base::LazyInstance<BrowserThreadGlobals>::Leaky
    g_globals = LAZY_INSTANCE_INITIALIZER;

}  // namespace

BrowserThreadImpl::BrowserThreadImpl(ID identifier)
    : Thread(GetThreadName(identifier)), identifier_(identifier) {
  Initialize();
}

BrowserThreadImpl::BrowserThreadImpl(ID identifier,
                                     base::MessageLoop* message_loop)
    : Thread(GetThreadName(identifier)), identifier_(identifier) {
  SetMessageLoop(message_loop);
  Initialize();

  // If constructed with an explicit message loop, this is a fake
  // BrowserThread which runs on the current thread.
  BrowserThreadGlobals& globals = g_globals.Get();
  base::AutoLock lock(globals.lock);

  DCHECK(!globals.task_runners[identifier_]);
  globals.task_runners[identifier_] = task_runner();

  DCHECK_EQ(globals.states[identifier_], BrowserThreadState::INITIALIZED);
  globals.states[identifier_] = BrowserThreadState::RUNNING;
}

void BrowserThreadImpl::Init() {
  BrowserThreadGlobals& globals = g_globals.Get();

#if DCHECK_IS_ON()
  {
    base::AutoLock lock(globals.lock);
    // |globals| should already have been initialized for |identifier_| in
    // BrowserThreadImpl::StartWithOptions(). If this isn't the case it's likely
    // because this BrowserThreadImpl's owner incorrectly used Thread::Start.*()
    // instead of BrowserThreadImpl::Start.*().
    DCHECK_EQ(globals.states[identifier_], BrowserThreadState::RUNNING);
    DCHECK(globals.task_runners[identifier_]);
    DCHECK(globals.task_runners[identifier_]->RunsTasksInCurrentSequence());
  }
#endif  // DCHECK_IS_ON()

  if (identifier_ == BrowserThread::PROCESS_LAUNCHER) {
    // Nesting and task observers are not allowed on redirected threads.
    base::RunLoop::DisallowNestingOnCurrentThread();
    message_loop()->DisallowTaskObservers();
  }

  if (identifier_ == BrowserThread::IO) {
    BrowserThreadDelegateAtomicPtr delegate =
        base::subtle::NoBarrier_Load(&globals.io_thread_delegate);
    if (delegate)
      reinterpret_cast<BrowserThreadDelegate*>(delegate)->Init();
  }
}

// We disable optimizations for this block of functions so the compiler doesn't
// merge them all together.
MSVC_DISABLE_OPTIMIZE()
MSVC_PUSH_DISABLE_WARNING(4748)

NOINLINE void BrowserThreadImpl::UIThreadRun(base::RunLoop* run_loop) {
  volatile int line_number = __LINE__;
  Thread::Run(run_loop);
  CHECK_GT(line_number, 0);
}

NOINLINE void BrowserThreadImpl::ProcessLauncherThreadRun(
    base::RunLoop* run_loop) {
  volatile int line_number = __LINE__;
  Thread::Run(run_loop);
  CHECK_GT(line_number, 0);
}

NOINLINE void BrowserThreadImpl::IOThreadRun(base::RunLoop* run_loop) {
  volatile int line_number = __LINE__;
  Thread::Run(run_loop);
  CHECK_GT(line_number, 0);
}

MSVC_POP_WARNING()
MSVC_ENABLE_OPTIMIZE();

void BrowserThreadImpl::Run(base::RunLoop* run_loop) {
#if defined(OS_ANDROID)
  // Not to reset thread name to "Thread-???" by VM, attach VM with thread name.
  // Though it may create unnecessary VM thread objects, keeping thread name
  // gives more benefit in debugging in the platform.
  if (!thread_name().empty()) {
    base::android::AttachCurrentThreadWithName(thread_name());
  }
#endif

  BrowserThread::ID thread_id = ID_COUNT;
  CHECK(GetCurrentThreadIdentifier(&thread_id));
  CHECK_EQ(identifier_, thread_id);

  switch (identifier_) {
    case BrowserThread::UI:
      return UIThreadRun(run_loop);
    case BrowserThread::PROCESS_LAUNCHER:
      return ProcessLauncherThreadRun(run_loop);
    case BrowserThread::IO:
      return IOThreadRun(run_loop);
    case BrowserThread::ID_COUNT:
      CHECK(false);  // This shouldn't actually be reached!
      break;
  }

  // |identifier_| must be set to a valid enum value in the constructor, so it
  // should be impossible to reach here.
  CHECK(false);
}

void BrowserThreadImpl::CleanUp() {
  BrowserThreadGlobals& globals = g_globals.Get();

  if (identifier_ == BrowserThread::IO) {
    BrowserThreadDelegateAtomicPtr delegate =
        base::subtle::NoBarrier_Load(&globals.io_thread_delegate);
    if (delegate)
      reinterpret_cast<BrowserThreadDelegate*>(delegate)->CleanUp();
  }

  // Change the state to SHUTDOWN so that PostTaskHelper stops accepting tasks
  // for this thread. Do not clear globals.task_runners[identifier_] so that
  // BrowserThread::CurrentlyOn() works from the MessageLoop's
  // DestructionObservers.
  base::AutoLock lock(globals.lock);
  DCHECK_EQ(globals.states[identifier_], BrowserThreadState::RUNNING);
  globals.states[identifier_] = BrowserThreadState::SHUTDOWN;
}

void BrowserThreadImpl::Initialize() {
  BrowserThreadGlobals& globals = g_globals.Get();

  base::AutoLock lock(globals.lock);
  DCHECK_GE(identifier_, 0);
  DCHECK_LT(identifier_, ID_COUNT);
  DCHECK_EQ(globals.states[identifier_], BrowserThreadState::UNINITIALIZED);
  globals.states[identifier_] = BrowserThreadState::INITIALIZED;
}

// static
void BrowserThreadImpl::ResetGlobalsForTesting(BrowserThread::ID identifier) {
  BrowserThreadGlobals& globals = g_globals.Get();

  base::AutoLock lock(globals.lock);
  DCHECK_EQ(globals.states[identifier], BrowserThreadState::SHUTDOWN);
  globals.states[identifier] = BrowserThreadState::UNINITIALIZED;
  globals.task_runners[identifier] = nullptr;
  if (identifier == BrowserThread::IO)
    SetIOThreadDelegate(nullptr);
}

BrowserThreadImpl::~BrowserThreadImpl() {
  // All Thread subclasses must call Stop() in the destructor. This is
  // doubly important here as various bits of code check they are on
  // the right BrowserThread.
  Stop();

  BrowserThreadGlobals& globals = g_globals.Get();
  base::AutoLock lock(globals.lock);
  // This thread should have gone through Cleanup() as part of Stop() and be in
  // the SHUTDOWN state already (unless it uses an externally provided
  // MessageLoop instead of a real underlying thread and thus doesn't go through
  // Cleanup()).
  if (using_external_message_loop()) {
    DCHECK_EQ(globals.states[identifier_], BrowserThreadState::RUNNING);
    globals.states[identifier_] = BrowserThreadState::SHUTDOWN;
  } else {
    DCHECK_EQ(globals.states[identifier_], BrowserThreadState::SHUTDOWN);
  }
#if DCHECK_IS_ON()
  // Double check that the threads are ordered correctly in the enumeration.
  for (int i = identifier_ + 1; i < ID_COUNT; ++i) {
    DCHECK(globals.states[i] == BrowserThreadState::SHUTDOWN ||
           globals.states[i] == BrowserThreadState::UNINITIALIZED)
        << "Threads must be listed in the reverse order that they die";
  }
#endif
}

bool BrowserThreadImpl::Start() {
  return StartWithOptions(base::Thread::Options());
}

bool BrowserThreadImpl::StartWithOptions(const Options& options) {
  BrowserThreadGlobals& globals = g_globals.Get();

  // Holding the lock is necessary when kicking off the thread to ensure
  // |states| and |task_runners| are updated before it gets to query them.
  base::AutoLock lock(globals.lock);

  bool result = Thread::StartWithOptions(options);

  // Although the thread is starting asynchronously, the MessageLoop is already
  // ready to accept tasks and as such this BrowserThreadImpl is considered as
  // "running".
  DCHECK(!globals.task_runners[identifier_]);
  globals.task_runners[identifier_] = task_runner();
  DCHECK(globals.task_runners[identifier_]);

  DCHECK_EQ(globals.states[identifier_], BrowserThreadState::INITIALIZED);
  globals.states[identifier_] = BrowserThreadState::RUNNING;

  return result;
}

bool BrowserThreadImpl::StartAndWaitForTesting() {
  if (!Start())
    return false;
  WaitUntilThreadStarted();
  return true;
}

// static
void BrowserThreadImpl::RedirectThreadIDToTaskRunner(
    BrowserThread::ID identifier,
    scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
  DCHECK(task_runner);

  BrowserThreadGlobals& globals = g_globals.Get();
  base::AutoLock lock(globals.lock);

  DCHECK(!globals.task_runners[identifier]);
  DCHECK_EQ(globals.states[identifier], BrowserThreadState::UNINITIALIZED);

  globals.task_runners[identifier] = std::move(task_runner);
  globals.states[identifier] = BrowserThreadState::RUNNING;
}

// static
void BrowserThreadImpl::StopRedirectionOfThreadID(
    BrowserThread::ID identifier) {
  BrowserThreadGlobals& globals = g_globals.Get();
  base::AutoLock auto_lock(globals.lock);

  DCHECK(globals.task_runners[identifier]);

  // Change the state to SHUTDOWN to stop accepting new tasks. Note: this is
  // different from non-redirected threads which continue accepting tasks while
  // being joined and only quit when idle. However, any tasks for which this
  // difference matters was already racy as any thread posting a task after the
  // Signal task below can't be synchronized with the joining thread. Therefore,
  // that task could already come in before or after the join had completed in
  // the non-redirection world. Entering SHUTDOWN early merely skews this race
  // towards making it less likely such a task is accepted by the joined thread
  // which is fine.
  DCHECK_EQ(globals.states[identifier], BrowserThreadState::RUNNING);
  globals.states[identifier] = BrowserThreadState::SHUTDOWN;

  // Wait for all pending tasks to complete.
  base::WaitableEvent flushed(base::WaitableEvent::ResetPolicy::MANUAL,
                              base::WaitableEvent::InitialState::NOT_SIGNALED);
  globals.task_runners[identifier]->PostTask(
      FROM_HERE,
      base::BindOnce(&base::WaitableEvent::Signal, base::Unretained(&flushed)));
  {
    base::AutoUnlock auto_lock(globals.lock);
    flushed.Wait();
  }

  // Only reset the task runner after running pending tasks so that
  // BrowserThread::CurrentlyOn() works in their scope.
  globals.task_runners[identifier] = nullptr;

  // Note: it's still possible for tasks to be posted to that task runner after
  // this point (e.g. through a previously obtained ThreadTaskRunnerHandle or by
  // one of the last tasks re-posting to its ThreadTaskRunnerHandle) but the
  // BrowserThread API itself won't accept tasks. Such tasks are ultimately
  // guaranteed to run before TaskScheduler::Shutdown() returns but may break
  // the assumption in PostTaskHelper that BrowserThread::ID A > B will always
  // succeed to post to B. This is pretty much the only observable difference
  // between a redirected thread and a real one and is one we're willing to live
  // with for this experiment. TODO(gab): fix this before enabling the
  // experiment by default on trunk, http://crbug.com/653916.
}

// static
bool BrowserThreadImpl::PostTaskHelper(BrowserThread::ID identifier,
                                       const base::Location& from_here,
                                       base::OnceClosure task,
                                       base::TimeDelta delay,
                                       bool nestable) {
  DCHECK_GE(identifier, 0);
  DCHECK_LT(identifier, ID_COUNT);
  // Optimization: to avoid unnecessary locks, we listed the ID enumeration in
  // order of lifetime.  So no need to lock if we know that the target thread
  // outlives current thread as that implies the current thread only ever sees
  // the target thread in its RUNNING state.
  // Note: since the array is so small, ok to loop instead of creating a map,
  // which would require a lock because std::map isn't thread safe, defeating
  // the whole purpose of this optimization.
  BrowserThread::ID current_thread = ID_COUNT;
  bool target_thread_outlives_current =
      GetCurrentThreadIdentifier(&current_thread) &&
      current_thread >= identifier;

  BrowserThreadGlobals& globals = g_globals.Get();
  if (!target_thread_outlives_current)
    globals.lock.Acquire();

  const bool accepting_tasks =
      globals.states[identifier] == BrowserThreadState::RUNNING;
  if (accepting_tasks) {
    base::SingleThreadTaskRunner* task_runner =
        globals.task_runners[identifier].get();
    DCHECK(task_runner);
    if (nestable) {
      task_runner->PostDelayedTask(from_here, std::move(task), delay);
    } else {
      task_runner->PostNonNestableDelayedTask(from_here, std::move(task),
                                              delay);
    }
  }

  if (!target_thread_outlives_current)
    globals.lock.Release();

  return accepting_tasks;
}

// static
void BrowserThread::PostAfterStartupTask(
    const base::Location& from_here,
    const scoped_refptr<base::TaskRunner>& task_runner,
    base::OnceClosure task) {
  GetContentClient()->browser()->PostAfterStartupTask(from_here, task_runner,
                                                      std::move(task));
}

// static
bool BrowserThread::IsThreadInitialized(ID identifier) {
  if (!g_globals.IsCreated())
    return false;

  BrowserThreadGlobals& globals = g_globals.Get();
  base::AutoLock lock(globals.lock);
  DCHECK_GE(identifier, 0);
  DCHECK_LT(identifier, ID_COUNT);
  return globals.states[identifier] == BrowserThreadState::INITIALIZED ||
         globals.states[identifier] == BrowserThreadState::RUNNING;
}

// static
bool BrowserThread::CurrentlyOn(ID identifier) {
  BrowserThreadGlobals& globals = g_globals.Get();
  base::AutoLock lock(globals.lock);
  DCHECK_GE(identifier, 0);
  DCHECK_LT(identifier, ID_COUNT);
  return globals.task_runners[identifier] &&
         globals.task_runners[identifier]->RunsTasksInCurrentSequence();
}

// static
std::string BrowserThread::GetDCheckCurrentlyOnErrorMessage(ID expected) {
  std::string actual_name = base::PlatformThread::GetName();
  if (actual_name.empty())
    actual_name = "Unknown Thread";

  std::string result = "Must be called on ";
  result += GetThreadName(expected);
  result += "; actually called on ";
  result += actual_name;
  result += ".";
  return result;
}

// static
bool BrowserThread::IsMessageLoopValid(ID identifier) {
  if (!g_globals.IsCreated())
    return false;

  BrowserThreadGlobals& globals = g_globals.Get();
  base::AutoLock lock(globals.lock);
  DCHECK_GE(identifier, 0);
  DCHECK_LT(identifier, ID_COUNT);
  return globals.states[identifier] == BrowserThreadState::RUNNING;
}

// static
bool BrowserThread::PostTask(ID identifier,
                             const base::Location& from_here,
                             base::OnceClosure task) {
  return BrowserThreadImpl::PostTaskHelper(
      identifier, from_here, std::move(task), base::TimeDelta(), true);
}

// static
bool BrowserThread::PostDelayedTask(ID identifier,
                                    const base::Location& from_here,
                                    base::OnceClosure task,
                                    base::TimeDelta delay) {
  return BrowserThreadImpl::PostTaskHelper(identifier, from_here,
                                           std::move(task), delay, true);
}

// static
bool BrowserThread::PostNonNestableTask(ID identifier,
                                        const base::Location& from_here,
                                        base::OnceClosure task) {
  return BrowserThreadImpl::PostTaskHelper(
      identifier, from_here, std::move(task), base::TimeDelta(), false);
}

// static
bool BrowserThread::PostNonNestableDelayedTask(ID identifier,
                                               const base::Location& from_here,
                                               base::OnceClosure task,
                                               base::TimeDelta delay) {
  return BrowserThreadImpl::PostTaskHelper(identifier, from_here,
                                           std::move(task), delay, false);
}

// static
bool BrowserThread::PostTaskAndReply(ID identifier,
                                     const base::Location& from_here,
                                     base::OnceClosure task,
                                     base::OnceClosure reply) {
  return GetTaskRunnerForThread(identifier)
      ->PostTaskAndReply(from_here, std::move(task), std::move(reply));
}

// static
bool BrowserThread::GetCurrentThreadIdentifier(ID* identifier) {
  if (!g_globals.IsCreated())
    return false;

  BrowserThreadGlobals& globals = g_globals.Get();
  // Profiler to track potential contention on |globals.lock|. This only does
  // real work on canary and local dev builds, so the cost of having this here
  // should be minimal.
  base::AutoLock lock(globals.lock);
  for (int i = 0; i < ID_COUNT; ++i) {
    if (globals.task_runners[i] &&
        globals.task_runners[i]->RunsTasksInCurrentSequence()) {
      *identifier = static_cast<ID>(i);
      return true;
    }
  }

  return false;
}

// static
scoped_refptr<base::SingleThreadTaskRunner>
BrowserThread::GetTaskRunnerForThread(ID identifier) {
  return g_task_runners.Get().proxies[identifier];
}

// static
void BrowserThread::SetIOThreadDelegate(BrowserThreadDelegate* delegate) {
  BrowserThreadGlobals& globals = g_globals.Get();
  BrowserThreadDelegateAtomicPtr old_delegate =
      base::subtle::NoBarrier_AtomicExchange(
          &globals.io_thread_delegate,
          reinterpret_cast<BrowserThreadDelegateAtomicPtr>(delegate));

  // This catches registration when previously registered.
  DCHECK(!delegate || !old_delegate);
}

}  // namespace content
