Add most of base/ build/ buildtools/ testing/ third_party/googletest/

Enough to make ./tools/gn/bootstrap/bootstrap.py work on Linux.

Change-Id: I94de95f1ce87dd3672d1a99c62254edee8be45bd
Reviewed-on: https://gn-review.googlesource.com/1100
Reviewed-by: Petr Hosek <phosek@google.com>
Commit-Queue: Scott Graham <scottmg@chromium.org>
diff --git a/base/threading/OWNERS b/base/threading/OWNERS
new file mode 100644
index 0000000..4198e99
--- /dev/null
+++ b/base/threading/OWNERS
@@ -0,0 +1,2 @@
+# For thread_resrictions.*
+jam@chromium.org
diff --git a/base/threading/platform_thread.h b/base/threading/platform_thread.h
new file mode 100644
index 0000000..faeb858
--- /dev/null
+++ b/base/threading/platform_thread.h
@@ -0,0 +1,240 @@
+// 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.
+
+// WARNING: You should *NOT* be using this class directly.  PlatformThread is
+// the low-level platform-specific abstraction to the OS's threading interface.
+// You should instead be using a message-loop driven Thread, see thread.h.
+
+#ifndef BASE_THREADING_PLATFORM_THREAD_H_
+#define BASE_THREADING_PLATFORM_THREAD_H_
+
+#include <stddef.h>
+
+#include "base/base_export.h"
+#include "base/macros.h"
+#include "base/time/time.h"
+#include "build/build_config.h"
+
+#if defined(OS_WIN)
+#include "base/win/windows_types.h"
+#elif defined(OS_FUCHSIA)
+#include <zircon/types.h>
+#elif defined(OS_MACOSX)
+#include <mach/mach_types.h>
+#elif defined(OS_POSIX)
+#include <pthread.h>
+#include <unistd.h>
+#endif
+
+namespace base {
+
+// Used for logging. Always an integer value.
+#if defined(OS_WIN)
+typedef DWORD PlatformThreadId;
+#elif defined(OS_FUCHSIA)
+typedef zx_handle_t PlatformThreadId;
+#elif defined(OS_MACOSX)
+typedef mach_port_t PlatformThreadId;
+#elif defined(OS_POSIX)
+typedef pid_t PlatformThreadId;
+#endif
+
+// Used for thread checking and debugging.
+// Meant to be as fast as possible.
+// These are produced by PlatformThread::CurrentRef(), and used to later
+// check if we are on the same thread or not by using ==. These are safe
+// to copy between threads, but can't be copied to another process as they
+// have no meaning there. Also, the internal identifier can be re-used
+// after a thread dies, so a PlatformThreadRef cannot be reliably used
+// to distinguish a new thread from an old, dead thread.
+class PlatformThreadRef {
+ public:
+#if defined(OS_WIN)
+  typedef DWORD RefType;
+#else  //  OS_POSIX
+  typedef pthread_t RefType;
+#endif
+  constexpr PlatformThreadRef() : id_(0) {}
+
+  explicit constexpr PlatformThreadRef(RefType id) : id_(id) {}
+
+  bool operator==(PlatformThreadRef other) const {
+    return id_ == other.id_;
+  }
+
+  bool operator!=(PlatformThreadRef other) const { return id_ != other.id_; }
+
+  bool is_null() const {
+    return id_ == 0;
+  }
+ private:
+  RefType id_;
+};
+
+// Used to operate on threads.
+class PlatformThreadHandle {
+ public:
+#if defined(OS_WIN)
+  typedef void* Handle;
+#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
+  typedef pthread_t Handle;
+#endif
+
+  constexpr PlatformThreadHandle() : handle_(0) {}
+
+  explicit constexpr PlatformThreadHandle(Handle handle) : handle_(handle) {}
+
+  bool is_equal(const PlatformThreadHandle& other) const {
+    return handle_ == other.handle_;
+  }
+
+  bool is_null() const {
+    return !handle_;
+  }
+
+  Handle platform_handle() const {
+    return handle_;
+  }
+
+ private:
+  Handle handle_;
+};
+
+const PlatformThreadId kInvalidThreadId(0);
+
+// Valid values for priority of Thread::Options and SimpleThread::Options, and
+// SetCurrentThreadPriority(), listed in increasing order of importance.
+enum class ThreadPriority : int {
+  // Suitable for threads that shouldn't disrupt high priority work.
+  BACKGROUND,
+  // Default priority level.
+  NORMAL,
+  // Suitable for threads which generate data for the display (at ~60Hz).
+  DISPLAY,
+  // Suitable for low-latency, glitch-resistant audio.
+  REALTIME_AUDIO,
+};
+
+// A namespace for low-level thread functions.
+class BASE_EXPORT PlatformThread {
+ public:
+  // Implement this interface to run code on a background thread.  Your
+  // ThreadMain method will be called on the newly created thread.
+  class BASE_EXPORT Delegate {
+   public:
+    virtual void ThreadMain() = 0;
+
+   protected:
+    virtual ~Delegate() = default;
+  };
+
+  // Gets the current thread id, which may be useful for logging purposes.
+  static PlatformThreadId CurrentId();
+
+  // Gets the current thread reference, which can be used to check if
+  // we're on the right thread quickly.
+  static PlatformThreadRef CurrentRef();
+
+  // Get the handle representing the current thread. On Windows, this is a
+  // pseudo handle constant which will always represent the thread using it and
+  // hence should not be shared with other threads nor be used to differentiate
+  // the current thread from another.
+  static PlatformThreadHandle CurrentHandle();
+
+  // Yield the current thread so another thread can be scheduled.
+  static void YieldCurrentThread();
+
+  // Sleeps for the specified duration.
+  static void Sleep(base::TimeDelta duration);
+
+  // Sets the thread name visible to debuggers/tools. This will try to
+  // initialize the context for current thread unless it's a WorkerThread.
+  static void SetName(const std::string& name);
+
+  // Gets the thread name, if previously set by SetName.
+  static const char* GetName();
+
+  // Creates a new thread.  The |stack_size| parameter can be 0 to indicate
+  // that the default stack size should be used.  Upon success,
+  // |*thread_handle| will be assigned a handle to the newly created thread,
+  // and |delegate|'s ThreadMain method will be executed on the newly created
+  // thread.
+  // NOTE: When you are done with the thread handle, you must call Join to
+  // release system resources associated with the thread.  You must ensure that
+  // the Delegate object outlives the thread.
+  static bool Create(size_t stack_size,
+                     Delegate* delegate,
+                     PlatformThreadHandle* thread_handle) {
+    return CreateWithPriority(stack_size, delegate, thread_handle,
+                              ThreadPriority::NORMAL);
+  }
+
+  // CreateWithPriority() does the same thing as Create() except the priority of
+  // the thread is set based on |priority|.
+  static bool CreateWithPriority(size_t stack_size, Delegate* delegate,
+                                 PlatformThreadHandle* thread_handle,
+                                 ThreadPriority priority);
+
+  // CreateNonJoinable() does the same thing as Create() except the thread
+  // cannot be Join()'d.  Therefore, it also does not output a
+  // PlatformThreadHandle.
+  static bool CreateNonJoinable(size_t stack_size, Delegate* delegate);
+
+  // CreateNonJoinableWithPriority() does the same thing as CreateNonJoinable()
+  // except the priority of the thread is set based on |priority|.
+  static bool CreateNonJoinableWithPriority(size_t stack_size,
+                                            Delegate* delegate,
+                                            ThreadPriority priority);
+
+  // Joins with a thread created via the Create function.  This function blocks
+  // the caller until the designated thread exits.  This will invalidate
+  // |thread_handle|.
+  static void Join(PlatformThreadHandle thread_handle);
+
+  // Detaches and releases the thread handle. The thread is no longer joinable
+  // and |thread_handle| is invalidated after this call.
+  static void Detach(PlatformThreadHandle thread_handle);
+
+  // Returns true if SetCurrentThreadPriority() can be used to increase the
+  // priority of the current thread.
+  static bool CanIncreaseCurrentThreadPriority();
+
+  // Toggles the current thread's priority at runtime.
+  //
+  // A thread may not be able to raise its priority back up after lowering it if
+  // the process does not have a proper permission, e.g. CAP_SYS_NICE on Linux.
+  // A thread may not be able to lower its priority back down after raising it
+  // to REALTIME_AUDIO.
+  //
+  // This function must not be called from the main thread on Mac. This is to
+  // avoid performance regressions (https://crbug.com/601270).
+  //
+  // Since changing other threads' priority is not permitted in favor of
+  // security, this interface is restricted to change only the current thread
+  // priority (https://crbug.com/399473).
+  static void SetCurrentThreadPriority(ThreadPriority priority);
+
+  static ThreadPriority GetCurrentThreadPriority();
+
+#if defined(OS_LINUX)
+  // Toggles a specific thread's priority at runtime. This can be used to
+  // change the priority of a thread in a different process and will fail
+  // if the calling process does not have proper permissions. The
+  // SetCurrentThreadPriority() function above is preferred in favor of
+  // security but on platforms where sandboxed processes are not allowed to
+  // change priority this function exists to allow a non-sandboxed process
+  // to change the priority of sandboxed threads for improved performance.
+  // Warning: Don't use this for a main thread because that will change the
+  // whole thread group's (i.e. process) priority.
+  static void SetThreadPriority(PlatformThreadId thread_id,
+                                ThreadPriority priority);
+#endif
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(PlatformThread);
+};
+
+}  // namespace base
+
+#endif  // BASE_THREADING_PLATFORM_THREAD_H_
diff --git a/base/threading/platform_thread_android.cc b/base/threading/platform_thread_android.cc
new file mode 100644
index 0000000..fd90d35
--- /dev/null
+++ b/base/threading/platform_thread_android.cc
@@ -0,0 +1,96 @@
+// 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 "base/threading/platform_thread.h"
+
+#include <errno.h>
+#include <stddef.h>
+#include <sys/prctl.h>
+#include <sys/resource.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "base/android/jni_android.h"
+#include "base/lazy_instance.h"
+#include "base/logging.h"
+#include "base/threading/platform_thread_internal_posix.h"
+#include "base/threading/thread_id_name_manager.h"
+#include "jni/ThreadUtils_jni.h"
+
+namespace base {
+
+namespace internal {
+
+// - BACKGROUND corresponds to Android's PRIORITY_BACKGROUND = 10 value and can
+// result in heavy throttling and force the thread onto a little core on
+// big.LITTLE devices.
+// - DISPLAY corresponds to Android's PRIORITY_DISPLAY = -4 value.
+// - REALTIME_AUDIO corresponds to Android's PRIORITY_AUDIO = -16 value.
+const ThreadPriorityToNiceValuePair kThreadPriorityToNiceValueMap[4] = {
+    {ThreadPriority::BACKGROUND, 10},
+    {ThreadPriority::NORMAL, 0},
+    {ThreadPriority::DISPLAY, -4},
+    {ThreadPriority::REALTIME_AUDIO, -16},
+};
+
+bool SetCurrentThreadPriorityForPlatform(ThreadPriority priority) {
+  // On Android, we set the Audio priority through JNI as Audio priority
+  // will also allow the process to run while it is backgrounded.
+  if (priority == ThreadPriority::REALTIME_AUDIO) {
+    JNIEnv* env = base::android::AttachCurrentThread();
+    Java_ThreadUtils_setThreadPriorityAudio(env, PlatformThread::CurrentId());
+    return true;
+  }
+  return false;
+}
+
+bool GetCurrentThreadPriorityForPlatform(ThreadPriority* priority) {
+  DCHECK(priority);
+  *priority = ThreadPriority::NORMAL;
+  JNIEnv* env = base::android::AttachCurrentThread();
+  if (Java_ThreadUtils_isThreadPriorityAudio(
+      env, PlatformThread::CurrentId())) {
+    *priority = ThreadPriority::REALTIME_AUDIO;
+    return true;
+  }
+  return false;
+}
+
+}  // namespace internal
+
+void PlatformThread::SetName(const std::string& name) {
+  ThreadIdNameManager::GetInstance()->SetName(name);
+
+  // Like linux, on android we can get the thread names to show up in the
+  // debugger by setting the process name for the LWP.
+  // We don't want to do this for the main thread because that would rename
+  // the process, causing tools like killall to stop working.
+  if (PlatformThread::CurrentId() == getpid())
+    return;
+
+  // Set the name for the LWP (which gets truncated to 15 characters).
+  int err = prctl(PR_SET_NAME, name.c_str());
+  if (err < 0 && errno != EPERM)
+    DPLOG(ERROR) << "prctl(PR_SET_NAME)";
+}
+
+
+void InitThreading() {
+}
+
+void TerminateOnThread() {
+  base::android::DetachFromVM();
+}
+
+size_t GetDefaultThreadStackSize(const pthread_attr_t& attributes) {
+#if !defined(ADDRESS_SANITIZER)
+  return 0;
+#else
+  // AddressSanitizer bloats the stack approximately 2x. Default stack size of
+  // 1Mb is not enough for some tests (see http://crbug.com/263749 for example).
+  return 2 * (1 << 20);  // 2Mb
+#endif
+}
+
+}  // namespace base
diff --git a/base/threading/platform_thread_fuchsia.cc b/base/threading/platform_thread_fuchsia.cc
new file mode 100644
index 0000000..eb06795
--- /dev/null
+++ b/base/threading/platform_thread_fuchsia.cc
@@ -0,0 +1,50 @@
+// Copyright 2017 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 "base/threading/platform_thread.h"
+
+#include <pthread.h>
+#include <sched.h>
+#include <zircon/syscalls.h>
+
+#include "base/threading/platform_thread_internal_posix.h"
+#include "base/threading/thread_id_name_manager.h"
+
+namespace base {
+
+void InitThreading() {}
+
+void TerminateOnThread() {}
+
+size_t GetDefaultThreadStackSize(const pthread_attr_t& attributes) {
+  return 0;
+}
+
+// static
+void PlatformThread::SetName(const std::string& name) {
+  zx_status_t status = zx_object_set_property(CurrentId(), ZX_PROP_NAME,
+                                              name.data(), name.size());
+  DCHECK_EQ(status, ZX_OK);
+
+  ThreadIdNameManager::GetInstance()->SetName(name);
+}
+
+// static
+bool PlatformThread::CanIncreaseCurrentThreadPriority() {
+  return false;
+}
+
+// static
+void PlatformThread::SetCurrentThreadPriority(ThreadPriority priority) {
+  if (priority != ThreadPriority::NORMAL) {
+    NOTIMPLEMENTED() << "setting ThreadPriority " << static_cast<int>(priority);
+  }
+}
+
+// static
+ThreadPriority PlatformThread::GetCurrentThreadPriority() {
+  return ThreadPriority::NORMAL;
+}
+
+}  // namespace base
diff --git a/base/threading/platform_thread_internal_posix.cc b/base/threading/platform_thread_internal_posix.cc
new file mode 100644
index 0000000..378a24d
--- /dev/null
+++ b/base/threading/platform_thread_internal_posix.cc
@@ -0,0 +1,39 @@
+// Copyright 2015 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 "base/threading/platform_thread_internal_posix.h"
+
+#include "base/containers/adapters.h"
+#include "base/logging.h"
+
+namespace base {
+
+namespace internal {
+
+int ThreadPriorityToNiceValue(ThreadPriority priority) {
+  for (const auto& pair : kThreadPriorityToNiceValueMap) {
+    if (pair.priority == priority)
+      return pair.nice_value;
+  }
+  NOTREACHED() << "Unknown ThreadPriority";
+  return 0;
+}
+
+ThreadPriority NiceValueToThreadPriority(int nice_value) {
+  // Try to find a priority that best describes |nice_value|. If there isn't
+  // an exact match, this method returns the closest priority whose nice value
+  // is higher (lower priority) than |nice_value|.
+  for (const auto& pair : Reversed(kThreadPriorityToNiceValueMap)) {
+    if (pair.nice_value >= nice_value)
+      return pair.priority;
+  }
+
+  // Reaching here means |nice_value| is more than any of the defined
+  // priorities. The lowest priority is suitable in this case.
+  return ThreadPriority::BACKGROUND;
+}
+
+}  // namespace internal
+
+}  // namespace base
diff --git a/base/threading/platform_thread_internal_posix.h b/base/threading/platform_thread_internal_posix.h
new file mode 100644
index 0000000..5f4a215
--- /dev/null
+++ b/base/threading/platform_thread_internal_posix.h
@@ -0,0 +1,48 @@
+// Copyright 2015 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.
+
+#ifndef BASE_THREADING_PLATFORM_THREAD_INTERNAL_POSIX_H_
+#define BASE_THREADING_PLATFORM_THREAD_INTERNAL_POSIX_H_
+
+#include "base/base_export.h"
+#include "base/threading/platform_thread.h"
+
+namespace base {
+
+namespace internal {
+
+struct ThreadPriorityToNiceValuePair {
+  ThreadPriority priority;
+  int nice_value;
+};
+// The elements must be listed in the order of increasing priority (lowest
+// priority first), that is, in the order of decreasing nice values (highest
+// nice value first).
+BASE_EXPORT extern
+const ThreadPriorityToNiceValuePair kThreadPriorityToNiceValueMap[4];
+
+// Returns the nice value matching |priority| based on the platform-specific
+// implementation of kThreadPriorityToNiceValueMap.
+int ThreadPriorityToNiceValue(ThreadPriority priority);
+
+// Returns the ThreadPrioirty matching |nice_value| based on the platform-
+// specific implementation of kThreadPriorityToNiceValueMap.
+BASE_EXPORT ThreadPriority NiceValueToThreadPriority(int nice_value);
+
+// Allows platform specific tweaks to the generic POSIX solution for
+// SetCurrentThreadPriority. Returns true if the platform-specific
+// implementation handled this |priority| change, false if the generic
+// implementation should instead proceed.
+bool SetCurrentThreadPriorityForPlatform(ThreadPriority priority);
+
+// Returns true if there is a platform-specific ThreadPriority set on the
+// current thread (and returns the actual ThreadPriority via |priority|).
+// Returns false otherwise, leaving |priority| untouched.
+bool GetCurrentThreadPriorityForPlatform(ThreadPriority* priority);
+
+}  // namespace internal
+
+}  // namespace base
+
+#endif  // BASE_THREADING_PLATFORM_THREAD_INTERNAL_POSIX_H_
diff --git a/base/threading/platform_thread_linux.cc b/base/threading/platform_thread_linux.cc
new file mode 100644
index 0000000..190aced
--- /dev/null
+++ b/base/threading/platform_thread_linux.cc
@@ -0,0 +1,184 @@
+// 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 "base/threading/platform_thread.h"
+
+#include <errno.h>
+#include <sched.h>
+#include <stddef.h>
+
+#include "base/files/file_util.h"
+#include "base/lazy_instance.h"
+#include "base/logging.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/threading/platform_thread_internal_posix.h"
+#include "base/threading/thread_id_name_manager.h"
+#include "build/build_config.h"
+
+#if !defined(OS_NACL) && !defined(OS_AIX)
+#include <pthread.h>
+#include <sys/prctl.h>
+#include <sys/resource.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#endif
+
+namespace base {
+namespace {
+#if !defined(OS_NACL)
+const FilePath::CharType kCgroupDirectory[] =
+    FILE_PATH_LITERAL("/sys/fs/cgroup");
+
+FilePath ThreadPriorityToCgroupDirectory(const FilePath& cgroup_filepath,
+                                         ThreadPriority priority) {
+  switch (priority) {
+    case ThreadPriority::NORMAL:
+      return cgroup_filepath;
+    case ThreadPriority::BACKGROUND:
+      return cgroup_filepath.Append(FILE_PATH_LITERAL("non-urgent"));
+    case ThreadPriority::DISPLAY:
+    case ThreadPriority::REALTIME_AUDIO:
+      return cgroup_filepath.Append(FILE_PATH_LITERAL("urgent"));
+  }
+  NOTREACHED();
+  return FilePath();
+}
+
+void SetThreadCgroup(PlatformThreadId thread_id,
+                     const FilePath& cgroup_directory) {
+  FilePath tasks_filepath = cgroup_directory.Append(FILE_PATH_LITERAL("tasks"));
+  std::string tid = IntToString(thread_id);
+  int bytes_written = WriteFile(tasks_filepath, tid.c_str(), tid.size());
+  if (bytes_written != static_cast<int>(tid.size())) {
+    DVLOG(1) << "Failed to add " << tid << " to " << tasks_filepath.value();
+  }
+}
+
+void SetThreadCgroupForThreadPriority(PlatformThreadId thread_id,
+                                      const FilePath& cgroup_filepath,
+                                      ThreadPriority priority) {
+  // Append "chrome" suffix.
+  FilePath cgroup_directory = ThreadPriorityToCgroupDirectory(
+      cgroup_filepath.Append(FILE_PATH_LITERAL("chrome")), priority);
+
+  // Silently ignore request if cgroup directory doesn't exist.
+  if (!DirectoryExists(cgroup_directory))
+    return;
+
+  SetThreadCgroup(thread_id, cgroup_directory);
+}
+
+void SetThreadCgroupsForThreadPriority(PlatformThreadId thread_id,
+                                       ThreadPriority priority) {
+  FilePath cgroup_filepath(kCgroupDirectory);
+  SetThreadCgroupForThreadPriority(
+      thread_id, cgroup_filepath.Append(FILE_PATH_LITERAL("cpuset")), priority);
+  SetThreadCgroupForThreadPriority(
+      thread_id, cgroup_filepath.Append(FILE_PATH_LITERAL("schedtune")),
+      priority);
+}
+#endif
+}  // namespace
+
+namespace internal {
+
+namespace {
+#if !defined(OS_NACL)
+const struct sched_param kRealTimePrio = {8};
+#endif
+}  // namespace
+
+const ThreadPriorityToNiceValuePair kThreadPriorityToNiceValueMap[4] = {
+    {ThreadPriority::BACKGROUND, 10},
+    {ThreadPriority::NORMAL, 0},
+    {ThreadPriority::DISPLAY, -8},
+    {ThreadPriority::REALTIME_AUDIO, -10},
+};
+
+bool SetCurrentThreadPriorityForPlatform(ThreadPriority priority) {
+#if !defined(OS_NACL)
+  SetThreadCgroupsForThreadPriority(PlatformThread::CurrentId(), priority);
+  return priority == ThreadPriority::REALTIME_AUDIO &&
+         pthread_setschedparam(pthread_self(), SCHED_RR, &kRealTimePrio) == 0;
+#else
+  return false;
+#endif
+}
+
+bool GetCurrentThreadPriorityForPlatform(ThreadPriority* priority) {
+#if !defined(OS_NACL)
+  int maybe_sched_rr = 0;
+  struct sched_param maybe_realtime_prio = {0};
+  if (pthread_getschedparam(pthread_self(), &maybe_sched_rr,
+                            &maybe_realtime_prio) == 0 &&
+      maybe_sched_rr == SCHED_RR &&
+      maybe_realtime_prio.sched_priority == kRealTimePrio.sched_priority) {
+    *priority = ThreadPriority::REALTIME_AUDIO;
+    return true;
+  }
+#endif
+  return false;
+}
+
+}  // namespace internal
+
+// static
+void PlatformThread::SetName(const std::string& name) {
+  ThreadIdNameManager::GetInstance()->SetName(name);
+
+#if !defined(OS_NACL) && !defined(OS_AIX)
+  // On linux we can get the thread names to show up in the debugger by setting
+  // the process name for the LWP.  We don't want to do this for the main
+  // thread because that would rename the process, causing tools like killall
+  // to stop working.
+  if (PlatformThread::CurrentId() == getpid())
+    return;
+
+  // http://0pointer.de/blog/projects/name-your-threads.html
+  // Set the name for the LWP (which gets truncated to 15 characters).
+  // Note that glibc also has a 'pthread_setname_np' api, but it may not be
+  // available everywhere and it's only benefit over using prctl directly is
+  // that it can set the name of threads other than the current thread.
+  int err = prctl(PR_SET_NAME, name.c_str());
+  // We expect EPERM failures in sandboxed processes, just ignore those.
+  if (err < 0 && errno != EPERM)
+    DPLOG(ERROR) << "prctl(PR_SET_NAME)";
+#endif  //  !defined(OS_NACL) && !defined(OS_AIX)
+}
+
+#if !defined(OS_NACL) && !defined(OS_AIX)
+// static
+void PlatformThread::SetThreadPriority(PlatformThreadId thread_id,
+                                       ThreadPriority priority) {
+  // Changing current main threads' priority is not permitted in favor of
+  // security, this interface is restricted to change only non-main thread
+  // priority.
+  CHECK_NE(thread_id, getpid());
+
+  SetThreadCgroupsForThreadPriority(thread_id, priority);
+
+  const int nice_setting = internal::ThreadPriorityToNiceValue(priority);
+  if (setpriority(PRIO_PROCESS, thread_id, nice_setting)) {
+    DVPLOG(1) << "Failed to set nice value of thread (" << thread_id << ") to "
+              << nice_setting;
+  }
+}
+#endif  //  !defined(OS_NACL) && !defined(OS_AIX)
+
+void InitThreading() {}
+
+void TerminateOnThread() {}
+
+size_t GetDefaultThreadStackSize(const pthread_attr_t& attributes) {
+#if !defined(THREAD_SANITIZER)
+  return 0;
+#else
+  // ThreadSanitizer bloats the stack heavily. Evidence has been that the
+  // default stack size isn't enough for some browser tests.
+  return 2 * (1 << 23);  // 2 times 8192K (the default stack size on Linux).
+#endif
+}
+
+}  // namespace base
diff --git a/base/threading/platform_thread_mac.mm b/base/threading/platform_thread_mac.mm
new file mode 100644
index 0000000..39d979d
--- /dev/null
+++ b/base/threading/platform_thread_mac.mm
@@ -0,0 +1,240 @@
+// 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 "base/threading/platform_thread.h"
+
+#import <Foundation/Foundation.h>
+#include <mach/mach.h>
+#include <mach/mach_time.h>
+#include <mach/thread_policy.h>
+#include <stddef.h>
+#include <sys/resource.h>
+
+#include <algorithm>
+
+#include "base/lazy_instance.h"
+#include "base/logging.h"
+#include "base/mac/foundation_util.h"
+#include "base/mac/mach_logging.h"
+#include "base/threading/thread_id_name_manager.h"
+#include "build/build_config.h"
+
+namespace base {
+
+namespace {
+NSString* const kThreadPriorityKey = @"CrThreadPriorityKey";
+}  // namespace
+
+// If Cocoa is to be used on more than one thread, it must know that the
+// application is multithreaded.  Since it's possible to enter Cocoa code
+// from threads created by pthread_thread_create, Cocoa won't necessarily
+// be aware that the application is multithreaded.  Spawning an NSThread is
+// enough to get Cocoa to set up for multithreaded operation, so this is done
+// if necessary before pthread_thread_create spawns any threads.
+//
+// http://developer.apple.com/documentation/Cocoa/Conceptual/Multithreading/CreatingThreads/chapter_4_section_4.html
+void InitThreading() {
+  static BOOL multithreaded = [NSThread isMultiThreaded];
+  if (!multithreaded) {
+    // +[NSObject class] is idempotent.
+    [NSThread detachNewThreadSelector:@selector(class)
+                             toTarget:[NSObject class]
+                           withObject:nil];
+    multithreaded = YES;
+
+    DCHECK([NSThread isMultiThreaded]);
+  }
+}
+
+// static
+void PlatformThread::SetName(const std::string& name) {
+  ThreadIdNameManager::GetInstance()->SetName(name);
+
+  // Mac OS X does not expose the length limit of the name, so
+  // hardcode it.
+  const int kMaxNameLength = 63;
+  std::string shortened_name = name.substr(0, kMaxNameLength);
+  // pthread_setname() fails (harmlessly) in the sandbox, ignore when it does.
+  // See http://crbug.com/47058
+  pthread_setname_np(shortened_name.c_str());
+}
+
+namespace {
+
+// Enables time-contraint policy and priority suitable for low-latency,
+// glitch-resistant audio.
+void SetPriorityRealtimeAudio() {
+  // Increase thread priority to real-time.
+
+  // Please note that the thread_policy_set() calls may fail in
+  // rare cases if the kernel decides the system is under heavy load
+  // and is unable to handle boosting the thread priority.
+  // In these cases we just return early and go on with life.
+
+  mach_port_t mach_thread_id =
+      pthread_mach_thread_np(PlatformThread::CurrentHandle().platform_handle());
+
+  // Make thread fixed priority.
+  thread_extended_policy_data_t policy;
+  policy.timeshare = 0;  // Set to 1 for a non-fixed thread.
+  kern_return_t result =
+      thread_policy_set(mach_thread_id,
+                        THREAD_EXTENDED_POLICY,
+                        reinterpret_cast<thread_policy_t>(&policy),
+                        THREAD_EXTENDED_POLICY_COUNT);
+  if (result != KERN_SUCCESS) {
+    MACH_DVLOG(1, result) << "thread_policy_set";
+    return;
+  }
+
+  // Set to relatively high priority.
+  thread_precedence_policy_data_t precedence;
+  precedence.importance = 63;
+  result = thread_policy_set(mach_thread_id,
+                             THREAD_PRECEDENCE_POLICY,
+                             reinterpret_cast<thread_policy_t>(&precedence),
+                             THREAD_PRECEDENCE_POLICY_COUNT);
+  if (result != KERN_SUCCESS) {
+    MACH_DVLOG(1, result) << "thread_policy_set";
+    return;
+  }
+
+  // Most important, set real-time constraints.
+
+  // Define the guaranteed and max fraction of time for the audio thread.
+  // These "duty cycle" values can range from 0 to 1.  A value of 0.5
+  // means the scheduler would give half the time to the thread.
+  // These values have empirically been found to yield good behavior.
+  // Good means that audio performance is high and other threads won't starve.
+  const double kGuaranteedAudioDutyCycle = 0.75;
+  const double kMaxAudioDutyCycle = 0.85;
+
+  // Define constants determining how much time the audio thread can
+  // use in a given time quantum.  All times are in milliseconds.
+
+  // About 128 frames @44.1KHz
+  const double kTimeQuantum = 2.9;
+
+  // Time guaranteed each quantum.
+  const double kAudioTimeNeeded = kGuaranteedAudioDutyCycle * kTimeQuantum;
+
+  // Maximum time each quantum.
+  const double kMaxTimeAllowed = kMaxAudioDutyCycle * kTimeQuantum;
+
+  // Get the conversion factor from milliseconds to absolute time
+  // which is what the time-constraints call needs.
+  mach_timebase_info_data_t tb_info;
+  mach_timebase_info(&tb_info);
+  double ms_to_abs_time =
+      (static_cast<double>(tb_info.denom) / tb_info.numer) * 1000000;
+
+  thread_time_constraint_policy_data_t time_constraints;
+  time_constraints.period = kTimeQuantum * ms_to_abs_time;
+  time_constraints.computation = kAudioTimeNeeded * ms_to_abs_time;
+  time_constraints.constraint = kMaxTimeAllowed * ms_to_abs_time;
+  time_constraints.preemptible = 0;
+
+  result =
+      thread_policy_set(mach_thread_id,
+                        THREAD_TIME_CONSTRAINT_POLICY,
+                        reinterpret_cast<thread_policy_t>(&time_constraints),
+                        THREAD_TIME_CONSTRAINT_POLICY_COUNT);
+  MACH_DVLOG_IF(1, result != KERN_SUCCESS, result) << "thread_policy_set";
+
+  return;
+}
+
+}  // anonymous namespace
+
+// static
+bool PlatformThread::CanIncreaseCurrentThreadPriority() {
+  return true;
+}
+
+// static
+void PlatformThread::SetCurrentThreadPriority(ThreadPriority priority) {
+  // Changing the priority of the main thread causes performance regressions.
+  // https://crbug.com/601270
+  DCHECK(![[NSThread currentThread] isMainThread]);
+
+  switch (priority) {
+    case ThreadPriority::BACKGROUND:
+      [[NSThread currentThread] setThreadPriority:0];
+      break;
+    case ThreadPriority::NORMAL:
+    case ThreadPriority::DISPLAY:
+      [[NSThread currentThread] setThreadPriority:0.5];
+      break;
+    case ThreadPriority::REALTIME_AUDIO:
+      SetPriorityRealtimeAudio();
+      DCHECK_EQ([[NSThread currentThread] threadPriority], 1.0);
+      break;
+  }
+
+  [[[NSThread currentThread] threadDictionary]
+      setObject:@(static_cast<int>(priority))
+         forKey:kThreadPriorityKey];
+}
+
+// static
+ThreadPriority PlatformThread::GetCurrentThreadPriority() {
+  NSNumber* priority = base::mac::ObjCCast<NSNumber>([[[NSThread currentThread]
+      threadDictionary] objectForKey:kThreadPriorityKey]);
+
+  if (!priority)
+    return ThreadPriority::NORMAL;
+
+  ThreadPriority thread_priority =
+      static_cast<ThreadPriority>(priority.intValue);
+  switch (thread_priority) {
+    case ThreadPriority::BACKGROUND:
+    case ThreadPriority::NORMAL:
+    case ThreadPriority::DISPLAY:
+    case ThreadPriority::REALTIME_AUDIO:
+      return thread_priority;
+    default:
+      NOTREACHED() << "Unknown priority.";
+      return ThreadPriority::NORMAL;
+  }
+}
+
+size_t GetDefaultThreadStackSize(const pthread_attr_t& attributes) {
+#if defined(OS_IOS)
+  return 0;
+#else
+  // The Mac OS X default for a pthread stack size is 512kB.
+  // Libc-594.1.4/pthreads/pthread.c's pthread_attr_init uses
+  // DEFAULT_STACK_SIZE for this purpose.
+  //
+  // 512kB isn't quite generous enough for some deeply recursive threads that
+  // otherwise request the default stack size by specifying 0. Here, adopt
+  // glibc's behavior as on Linux, which is to use the current stack size
+  // limit (ulimit -s) as the default stack size. See
+  // glibc-2.11.1/nptl/nptl-init.c's __pthread_initialize_minimal_internal. To
+  // avoid setting the limit below the Mac OS X default or the minimum usable
+  // stack size, these values are also considered. If any of these values
+  // can't be determined, or if stack size is unlimited (ulimit -s unlimited),
+  // stack_size is left at 0 to get the system default.
+  //
+  // Mac OS X normally only applies ulimit -s to the main thread stack. On
+  // contemporary OS X and Linux systems alike, this value is generally 8MB
+  // or in that neighborhood.
+  size_t default_stack_size = 0;
+  struct rlimit stack_rlimit;
+  if (pthread_attr_getstacksize(&attributes, &default_stack_size) == 0 &&
+      getrlimit(RLIMIT_STACK, &stack_rlimit) == 0 &&
+      stack_rlimit.rlim_cur != RLIM_INFINITY) {
+    default_stack_size =
+        std::max(std::max(default_stack_size,
+                          static_cast<size_t>(PTHREAD_STACK_MIN)),
+                 static_cast<size_t>(stack_rlimit.rlim_cur));
+  }
+  return default_stack_size;
+#endif
+}
+
+void TerminateOnThread() {
+}
+
+}  // namespace base
diff --git a/base/threading/platform_thread_posix.cc b/base/threading/platform_thread_posix.cc
new file mode 100644
index 0000000..2466b78
--- /dev/null
+++ b/base/threading/platform_thread_posix.cc
@@ -0,0 +1,305 @@
+// 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 "base/threading/platform_thread.h"
+
+#include <errno.h>
+#include <pthread.h>
+#include <sched.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <memory>
+
+#include "base/debug/activity_tracker.h"
+#include "base/lazy_instance.h"
+#include "base/logging.h"
+#include "base/threading/platform_thread_internal_posix.h"
+#include "base/threading/thread_id_name_manager.h"
+#include "base/threading/thread_restrictions.h"
+#include "build/build_config.h"
+
+#if defined(OS_LINUX)
+#include <sys/syscall.h>
+#endif
+
+#if defined(OS_FUCHSIA)
+#include <zircon/process.h>
+#else
+#include <sys/resource.h>
+#endif
+
+namespace base {
+
+void InitThreading();
+void TerminateOnThread();
+size_t GetDefaultThreadStackSize(const pthread_attr_t& attributes);
+
+namespace {
+
+struct ThreadParams {
+  ThreadParams()
+      : delegate(nullptr), joinable(false), priority(ThreadPriority::NORMAL) {}
+
+  PlatformThread::Delegate* delegate;
+  bool joinable;
+  ThreadPriority priority;
+};
+
+void* ThreadFunc(void* params) {
+  PlatformThread::Delegate* delegate = nullptr;
+
+  {
+    std::unique_ptr<ThreadParams> thread_params(
+        static_cast<ThreadParams*>(params));
+
+    delegate = thread_params->delegate;
+    if (!thread_params->joinable)
+      base::ThreadRestrictions::SetSingletonAllowed(false);
+
+#if !defined(OS_NACL)
+    // Threads on linux/android may inherit their priority from the thread
+    // where they were created. This explicitly sets the priority of all new
+    // threads.
+    PlatformThread::SetCurrentThreadPriority(thread_params->priority);
+#endif
+  }
+
+  ThreadIdNameManager::GetInstance()->RegisterThread(
+      PlatformThread::CurrentHandle().platform_handle(),
+      PlatformThread::CurrentId());
+
+  delegate->ThreadMain();
+
+  ThreadIdNameManager::GetInstance()->RemoveName(
+      PlatformThread::CurrentHandle().platform_handle(),
+      PlatformThread::CurrentId());
+
+  base::TerminateOnThread();
+  return nullptr;
+}
+
+bool CreateThread(size_t stack_size,
+                  bool joinable,
+                  PlatformThread::Delegate* delegate,
+                  PlatformThreadHandle* thread_handle,
+                  ThreadPriority priority) {
+  DCHECK(thread_handle);
+  base::InitThreading();
+
+  pthread_attr_t attributes;
+  pthread_attr_init(&attributes);
+
+  // Pthreads are joinable by default, so only specify the detached
+  // attribute if the thread should be non-joinable.
+  if (!joinable)
+    pthread_attr_setdetachstate(&attributes, PTHREAD_CREATE_DETACHED);
+
+  // Get a better default if available.
+  if (stack_size == 0)
+    stack_size = base::GetDefaultThreadStackSize(attributes);
+
+  if (stack_size > 0)
+    pthread_attr_setstacksize(&attributes, stack_size);
+
+  std::unique_ptr<ThreadParams> params(new ThreadParams);
+  params->delegate = delegate;
+  params->joinable = joinable;
+  params->priority = priority;
+
+  pthread_t handle;
+  int err = pthread_create(&handle, &attributes, ThreadFunc, params.get());
+  bool success = !err;
+  if (success) {
+    // ThreadParams should be deleted on the created thread after used.
+    ignore_result(params.release());
+  } else {
+    // Value of |handle| is undefined if pthread_create fails.
+    handle = 0;
+    errno = err;
+    PLOG(ERROR) << "pthread_create";
+  }
+  *thread_handle = PlatformThreadHandle(handle);
+
+  pthread_attr_destroy(&attributes);
+
+  return success;
+}
+
+}  // namespace
+
+// static
+PlatformThreadId PlatformThread::CurrentId() {
+  // Pthreads doesn't have the concept of a thread ID, so we have to reach down
+  // into the kernel.
+#if defined(OS_MACOSX)
+  return pthread_mach_thread_np(pthread_self());
+#elif defined(OS_LINUX)
+  return syscall(__NR_gettid);
+#elif defined(OS_ANDROID)
+  return gettid();
+#elif defined(OS_FUCHSIA)
+  return zx_thread_self();
+#elif defined(OS_SOLARIS) || defined(OS_QNX)
+  return pthread_self();
+#elif defined(OS_NACL) && defined(__GLIBC__)
+  return pthread_self();
+#elif defined(OS_NACL) && !defined(__GLIBC__)
+  // Pointers are 32-bits in NaCl.
+  return reinterpret_cast<int32_t>(pthread_self());
+#elif defined(OS_POSIX) && defined(OS_AIX)
+  return pthread_self();
+#elif defined(OS_POSIX) && !defined(OS_AIX)
+  return reinterpret_cast<int64_t>(pthread_self());
+#endif
+}
+
+// static
+PlatformThreadRef PlatformThread::CurrentRef() {
+  return PlatformThreadRef(pthread_self());
+}
+
+// static
+PlatformThreadHandle PlatformThread::CurrentHandle() {
+  return PlatformThreadHandle(pthread_self());
+}
+
+// static
+void PlatformThread::YieldCurrentThread() {
+  sched_yield();
+}
+
+// static
+void PlatformThread::Sleep(TimeDelta duration) {
+  struct timespec sleep_time, remaining;
+
+  // Break the duration into seconds and nanoseconds.
+  // NOTE: TimeDelta's microseconds are int64s while timespec's
+  // nanoseconds are longs, so this unpacking must prevent overflow.
+  sleep_time.tv_sec = duration.InSeconds();
+  duration -= TimeDelta::FromSeconds(sleep_time.tv_sec);
+  sleep_time.tv_nsec = duration.InMicroseconds() * 1000;  // nanoseconds
+
+  while (nanosleep(&sleep_time, &remaining) == -1 && errno == EINTR)
+    sleep_time = remaining;
+}
+
+// static
+const char* PlatformThread::GetName() {
+  return ThreadIdNameManager::GetInstance()->GetName(CurrentId());
+}
+
+// static
+bool PlatformThread::CreateWithPriority(size_t stack_size, Delegate* delegate,
+                                        PlatformThreadHandle* thread_handle,
+                                        ThreadPriority priority) {
+  return CreateThread(stack_size, true /* joinable thread */, delegate,
+                      thread_handle, priority);
+}
+
+// static
+bool PlatformThread::CreateNonJoinable(size_t stack_size, Delegate* delegate) {
+  return CreateNonJoinableWithPriority(stack_size, delegate,
+                                       ThreadPriority::NORMAL);
+}
+
+// static
+bool PlatformThread::CreateNonJoinableWithPriority(size_t stack_size,
+                                                   Delegate* delegate,
+                                                   ThreadPriority priority) {
+  PlatformThreadHandle unused;
+
+  bool result = CreateThread(stack_size, false /* non-joinable thread */,
+                             delegate, &unused, priority);
+  return result;
+}
+
+// static
+void PlatformThread::Join(PlatformThreadHandle thread_handle) {
+  // Record the event that this thread is blocking upon (for hang diagnosis).
+  base::debug::ScopedThreadJoinActivity thread_activity(&thread_handle);
+
+  // Joining another thread may block the current thread for a long time, since
+  // the thread referred to by |thread_handle| may still be running long-lived /
+  // blocking tasks.
+  AssertBlockingAllowed();
+  CHECK_EQ(0, pthread_join(thread_handle.platform_handle(), nullptr));
+}
+
+// static
+void PlatformThread::Detach(PlatformThreadHandle thread_handle) {
+  CHECK_EQ(0, pthread_detach(thread_handle.platform_handle()));
+}
+
+// Mac and Fuchsia have their own Set/GetCurrentThreadPriority()
+// implementations.
+#if !defined(OS_MACOSX) && !defined(OS_FUCHSIA)
+
+// static
+bool PlatformThread::CanIncreaseCurrentThreadPriority() {
+#if defined(OS_NACL)
+  return false;
+#else
+  // Only root can raise thread priority on POSIX environment. On Linux, users
+  // who have CAP_SYS_NICE permission also can raise the thread priority, but
+  // libcap.so would be needed to check the capability.
+  return geteuid() == 0;
+#endif  // defined(OS_NACL)
+}
+
+// static
+void PlatformThread::SetCurrentThreadPriority(ThreadPriority priority) {
+#if defined(OS_NACL)
+  NOTIMPLEMENTED();
+#else
+  if (internal::SetCurrentThreadPriorityForPlatform(priority))
+    return;
+
+  // setpriority(2) should change the whole thread group's (i.e. process)
+  // priority. However, as stated in the bugs section of
+  // http://man7.org/linux/man-pages/man2/getpriority.2.html: "under the current
+  // Linux/NPTL implementation of POSIX threads, the nice value is a per-thread
+  // attribute". Also, 0 is prefered to the current thread id since it is
+  // equivalent but makes sandboxing easier (https://crbug.com/399473).
+  const int nice_setting = internal::ThreadPriorityToNiceValue(priority);
+  if (setpriority(PRIO_PROCESS, 0, nice_setting)) {
+    DVPLOG(1) << "Failed to set nice value of thread ("
+              << PlatformThread::CurrentId() << ") to " << nice_setting;
+  }
+#endif  // defined(OS_NACL)
+}
+
+// static
+ThreadPriority PlatformThread::GetCurrentThreadPriority() {
+#if defined(OS_NACL)
+  NOTIMPLEMENTED();
+  return ThreadPriority::NORMAL;
+#else
+  // Mirrors SetCurrentThreadPriority()'s implementation.
+  ThreadPriority platform_specific_priority;
+  if (internal::GetCurrentThreadPriorityForPlatform(
+          &platform_specific_priority)) {
+    return platform_specific_priority;
+  }
+
+  // Need to clear errno before calling getpriority():
+  // http://man7.org/linux/man-pages/man2/getpriority.2.html
+  errno = 0;
+  int nice_value = getpriority(PRIO_PROCESS, 0);
+  if (errno != 0) {
+    DVPLOG(1) << "Failed to get nice value of thread ("
+              << PlatformThread::CurrentId() << ")";
+    return ThreadPriority::NORMAL;
+  }
+
+  return internal::NiceValueToThreadPriority(nice_value);
+#endif  // !defined(OS_NACL)
+}
+
+#endif  // !defined(OS_MACOSX) && !defined(OS_FUCHSIA)
+
+}  // namespace base
diff --git a/base/threading/platform_thread_unittest.cc b/base/threading/platform_thread_unittest.cc
new file mode 100644
index 0000000..7eea22e
--- /dev/null
+++ b/base/threading/platform_thread_unittest.cc
@@ -0,0 +1,367 @@
+// 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 <stddef.h>
+
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/threading/platform_thread.h"
+#include "build/build_config.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#if defined(OS_POSIX)
+#include "base/threading/platform_thread_internal_posix.h"
+#elif defined(OS_WIN)
+#include <windows.h>
+#endif
+
+namespace base {
+
+// Trivial tests that thread runs and doesn't crash on create, join, or detach -
+
+namespace {
+
+class TrivialThread : public PlatformThread::Delegate {
+ public:
+  TrivialThread() : run_event_(WaitableEvent::ResetPolicy::MANUAL,
+                               WaitableEvent::InitialState::NOT_SIGNALED) {}
+
+  void ThreadMain() override { run_event_.Signal(); }
+
+  WaitableEvent& run_event() { return run_event_; }
+
+ private:
+  WaitableEvent run_event_;
+
+  DISALLOW_COPY_AND_ASSIGN(TrivialThread);
+};
+
+}  // namespace
+
+TEST(PlatformThreadTest, TrivialJoin) {
+  TrivialThread thread;
+  PlatformThreadHandle handle;
+
+  ASSERT_FALSE(thread.run_event().IsSignaled());
+  ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
+  PlatformThread::Join(handle);
+  ASSERT_TRUE(thread.run_event().IsSignaled());
+}
+
+TEST(PlatformThreadTest, TrivialJoinTimesTen) {
+  TrivialThread thread[10];
+  PlatformThreadHandle handle[arraysize(thread)];
+
+  for (size_t n = 0; n < arraysize(thread); n++)
+    ASSERT_FALSE(thread[n].run_event().IsSignaled());
+  for (size_t n = 0; n < arraysize(thread); n++)
+    ASSERT_TRUE(PlatformThread::Create(0, &thread[n], &handle[n]));
+  for (size_t n = 0; n < arraysize(thread); n++)
+    PlatformThread::Join(handle[n]);
+  for (size_t n = 0; n < arraysize(thread); n++)
+    ASSERT_TRUE(thread[n].run_event().IsSignaled());
+}
+
+// The following detach tests are by nature racy. The run_event approximates the
+// end and termination of the thread, but threads could persist shortly after
+// the test completes.
+TEST(PlatformThreadTest, TrivialDetach) {
+  TrivialThread thread;
+  PlatformThreadHandle handle;
+
+  ASSERT_FALSE(thread.run_event().IsSignaled());
+  ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
+  PlatformThread::Detach(handle);
+  thread.run_event().Wait();
+}
+
+TEST(PlatformThreadTest, TrivialDetachTimesTen) {
+  TrivialThread thread[10];
+  PlatformThreadHandle handle[arraysize(thread)];
+
+  for (size_t n = 0; n < arraysize(thread); n++)
+    ASSERT_FALSE(thread[n].run_event().IsSignaled());
+  for (size_t n = 0; n < arraysize(thread); n++) {
+    ASSERT_TRUE(PlatformThread::Create(0, &thread[n], &handle[n]));
+    PlatformThread::Detach(handle[n]);
+  }
+  for (size_t n = 0; n < arraysize(thread); n++)
+    thread[n].run_event().Wait();
+}
+
+// Tests of basic thread functions ---------------------------------------------
+
+namespace {
+
+class FunctionTestThread : public PlatformThread::Delegate {
+ public:
+  FunctionTestThread()
+      : thread_id_(kInvalidThreadId),
+        termination_ready_(WaitableEvent::ResetPolicy::MANUAL,
+                           WaitableEvent::InitialState::NOT_SIGNALED),
+        terminate_thread_(WaitableEvent::ResetPolicy::MANUAL,
+                          WaitableEvent::InitialState::NOT_SIGNALED),
+        done_(false) {}
+  ~FunctionTestThread() override {
+    EXPECT_TRUE(terminate_thread_.IsSignaled())
+        << "Need to mark thread for termination and join the underlying thread "
+        << "before destroying a FunctionTestThread as it owns the "
+        << "WaitableEvent blocking the underlying thread's main.";
+  }
+
+  // Grabs |thread_id_|, runs an optional test on that thread, signals
+  // |termination_ready_|, and then waits for |terminate_thread_| to be
+  // signaled before exiting.
+  void ThreadMain() override {
+    thread_id_ = PlatformThread::CurrentId();
+    EXPECT_NE(thread_id_, kInvalidThreadId);
+
+    // Make sure that the thread ID is the same across calls.
+    EXPECT_EQ(thread_id_, PlatformThread::CurrentId());
+
+    // Run extra tests.
+    RunTest();
+
+    termination_ready_.Signal();
+    terminate_thread_.Wait();
+
+    done_ = true;
+  }
+
+  PlatformThreadId thread_id() const {
+    EXPECT_TRUE(termination_ready_.IsSignaled()) << "Thread ID still unknown";
+    return thread_id_;
+  }
+
+  bool IsRunning() const {
+    return termination_ready_.IsSignaled() && !done_;
+  }
+
+  // Blocks until this thread is started and ready to be terminated.
+  void WaitForTerminationReady() { termination_ready_.Wait(); }
+
+  // Marks this thread for termination (callers must then join this thread to be
+  // guaranteed of termination).
+  void MarkForTermination() { terminate_thread_.Signal(); }
+
+ private:
+  // Runs an optional test on the newly created thread.
+  virtual void RunTest() {}
+
+  PlatformThreadId thread_id_;
+
+  mutable WaitableEvent termination_ready_;
+  WaitableEvent terminate_thread_;
+  bool done_;
+
+  DISALLOW_COPY_AND_ASSIGN(FunctionTestThread);
+};
+
+}  // namespace
+
+TEST(PlatformThreadTest, Function) {
+  PlatformThreadId main_thread_id = PlatformThread::CurrentId();
+
+  FunctionTestThread thread;
+  PlatformThreadHandle handle;
+
+  ASSERT_FALSE(thread.IsRunning());
+  ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
+  thread.WaitForTerminationReady();
+  ASSERT_TRUE(thread.IsRunning());
+  EXPECT_NE(thread.thread_id(), main_thread_id);
+
+  thread.MarkForTermination();
+  PlatformThread::Join(handle);
+  ASSERT_FALSE(thread.IsRunning());
+
+  // Make sure that the thread ID is the same across calls.
+  EXPECT_EQ(main_thread_id, PlatformThread::CurrentId());
+}
+
+TEST(PlatformThreadTest, FunctionTimesTen) {
+  PlatformThreadId main_thread_id = PlatformThread::CurrentId();
+
+  FunctionTestThread thread[10];
+  PlatformThreadHandle handle[arraysize(thread)];
+
+  for (size_t n = 0; n < arraysize(thread); n++)
+    ASSERT_FALSE(thread[n].IsRunning());
+
+  for (size_t n = 0; n < arraysize(thread); n++)
+    ASSERT_TRUE(PlatformThread::Create(0, &thread[n], &handle[n]));
+  for (size_t n = 0; n < arraysize(thread); n++)
+    thread[n].WaitForTerminationReady();
+
+  for (size_t n = 0; n < arraysize(thread); n++) {
+    ASSERT_TRUE(thread[n].IsRunning());
+    EXPECT_NE(thread[n].thread_id(), main_thread_id);
+
+    // Make sure no two threads get the same ID.
+    for (size_t i = 0; i < n; ++i) {
+      EXPECT_NE(thread[i].thread_id(), thread[n].thread_id());
+    }
+  }
+
+  for (size_t n = 0; n < arraysize(thread); n++)
+    thread[n].MarkForTermination();
+  for (size_t n = 0; n < arraysize(thread); n++)
+    PlatformThread::Join(handle[n]);
+  for (size_t n = 0; n < arraysize(thread); n++)
+    ASSERT_FALSE(thread[n].IsRunning());
+
+  // Make sure that the thread ID is the same across calls.
+  EXPECT_EQ(main_thread_id, PlatformThread::CurrentId());
+}
+
+namespace {
+
+const ThreadPriority kThreadPriorityTestValues[] = {
+// The order should be higher to lower to cover as much cases as possible on
+// Linux trybots running without CAP_SYS_NICE permission.
+#if !defined(OS_ANDROID)
+    // PlatformThread::GetCurrentThreadPriority() on Android does not support
+    // REALTIME_AUDIO case. See http://crbug.com/505474.
+    ThreadPriority::REALTIME_AUDIO,
+#endif
+    ThreadPriority::DISPLAY,
+    // This redundant BACKGROUND priority is to test backgrounding from other
+    // priorities, and unbackgrounding.
+    ThreadPriority::BACKGROUND,
+    ThreadPriority::NORMAL,
+    ThreadPriority::BACKGROUND};
+
+class ThreadPriorityTestThread : public FunctionTestThread {
+ public:
+  explicit ThreadPriorityTestThread(ThreadPriority priority)
+      : priority_(priority) {}
+  ~ThreadPriorityTestThread() override = default;
+
+ private:
+  void RunTest() override {
+    // Confirm that the current thread's priority is as expected.
+    EXPECT_EQ(ThreadPriority::NORMAL,
+              PlatformThread::GetCurrentThreadPriority());
+
+    // Alter and verify the current thread's priority.
+    PlatformThread::SetCurrentThreadPriority(priority_);
+    EXPECT_EQ(priority_, PlatformThread::GetCurrentThreadPriority());
+  }
+
+  const ThreadPriority priority_;
+
+  DISALLOW_COPY_AND_ASSIGN(ThreadPriorityTestThread);
+};
+
+}  // namespace
+
+// Test changing a created thread's priority (which has different semantics on
+// some platforms).
+TEST(PlatformThreadTest, ThreadPriorityCurrentThread) {
+  const bool increase_priority_allowed =
+      PlatformThread::CanIncreaseCurrentThreadPriority();
+
+// Bump the priority in order to verify that new threads are started with normal
+// priority. Skip this on Mac since this platform doesn't allow changing the
+// priority of the main thread. Also skip this on platforms that don't allow
+// increasing the priority of a thread.
+#if !defined(OS_MACOSX)
+  if (increase_priority_allowed)
+    PlatformThread::SetCurrentThreadPriority(ThreadPriority::DISPLAY);
+#endif
+
+  // Toggle each supported priority on the thread and confirm it affects it.
+  for (size_t i = 0; i < arraysize(kThreadPriorityTestValues); ++i) {
+    if (!increase_priority_allowed &&
+        kThreadPriorityTestValues[i] >
+            PlatformThread::GetCurrentThreadPriority()) {
+      continue;
+    }
+
+    ThreadPriorityTestThread thread(kThreadPriorityTestValues[i]);
+    PlatformThreadHandle handle;
+
+    ASSERT_FALSE(thread.IsRunning());
+    ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
+    thread.WaitForTerminationReady();
+    ASSERT_TRUE(thread.IsRunning());
+
+    thread.MarkForTermination();
+    PlatformThread::Join(handle);
+    ASSERT_FALSE(thread.IsRunning());
+  }
+}
+
+// This tests internal PlatformThread APIs used under some POSIX platforms,
+// with the exception of Mac OS X, iOS and Fuchsia.
+#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_IOS) && \
+    !defined(OS_FUCHSIA)
+TEST(PlatformThreadTest, GetNiceValueToThreadPriority) {
+  using internal::NiceValueToThreadPriority;
+  using internal::kThreadPriorityToNiceValueMap;
+
+  EXPECT_EQ(ThreadPriority::BACKGROUND,
+            kThreadPriorityToNiceValueMap[0].priority);
+  EXPECT_EQ(ThreadPriority::NORMAL,
+            kThreadPriorityToNiceValueMap[1].priority);
+  EXPECT_EQ(ThreadPriority::DISPLAY,
+            kThreadPriorityToNiceValueMap[2].priority);
+  EXPECT_EQ(ThreadPriority::REALTIME_AUDIO,
+            kThreadPriorityToNiceValueMap[3].priority);
+
+  static const int kBackgroundNiceValue =
+      kThreadPriorityToNiceValueMap[0].nice_value;
+  static const int kNormalNiceValue =
+      kThreadPriorityToNiceValueMap[1].nice_value;
+  static const int kDisplayNiceValue =
+      kThreadPriorityToNiceValueMap[2].nice_value;
+  static const int kRealtimeAudioNiceValue =
+      kThreadPriorityToNiceValueMap[3].nice_value;
+
+  // The tests below assume the nice values specified in the map are within
+  // the range below (both ends exclusive).
+  static const int kHighestNiceValue = 19;
+  static const int kLowestNiceValue = -20;
+
+  EXPECT_GT(kHighestNiceValue, kBackgroundNiceValue);
+  EXPECT_GT(kBackgroundNiceValue, kNormalNiceValue);
+  EXPECT_GT(kNormalNiceValue, kDisplayNiceValue);
+  EXPECT_GT(kDisplayNiceValue, kRealtimeAudioNiceValue);
+  EXPECT_GT(kRealtimeAudioNiceValue, kLowestNiceValue);
+
+  EXPECT_EQ(ThreadPriority::BACKGROUND,
+            NiceValueToThreadPriority(kHighestNiceValue));
+  EXPECT_EQ(ThreadPriority::BACKGROUND,
+            NiceValueToThreadPriority(kBackgroundNiceValue + 1));
+  EXPECT_EQ(ThreadPriority::BACKGROUND,
+            NiceValueToThreadPriority(kBackgroundNiceValue));
+  EXPECT_EQ(ThreadPriority::BACKGROUND,
+            NiceValueToThreadPriority(kNormalNiceValue + 1));
+  EXPECT_EQ(ThreadPriority::NORMAL,
+            NiceValueToThreadPriority(kNormalNiceValue));
+  EXPECT_EQ(ThreadPriority::NORMAL,
+            NiceValueToThreadPriority(kDisplayNiceValue + 1));
+  EXPECT_EQ(ThreadPriority::DISPLAY,
+            NiceValueToThreadPriority(kDisplayNiceValue));
+  EXPECT_EQ(ThreadPriority::DISPLAY,
+            NiceValueToThreadPriority(kRealtimeAudioNiceValue + 1));
+  EXPECT_EQ(ThreadPriority::REALTIME_AUDIO,
+            NiceValueToThreadPriority(kRealtimeAudioNiceValue));
+  EXPECT_EQ(ThreadPriority::REALTIME_AUDIO,
+            NiceValueToThreadPriority(kLowestNiceValue));
+}
+#endif  // defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_IOS) &&
+        // !defined(OS_FUCHSIA)
+
+TEST(PlatformThreadTest, SetHugeThreadName) {
+  // Construct an excessively long thread name.
+  std::string long_name(1024, 'a');
+
+  // SetName has no return code, so just verify that implementations
+  // don't [D]CHECK().
+  PlatformThread::SetName(long_name);
+}
+
+}  // namespace base
diff --git a/base/threading/platform_thread_win.cc b/base/threading/platform_thread_win.cc
new file mode 100644
index 0000000..daccc0e
--- /dev/null
+++ b/base/threading/platform_thread_win.cc
@@ -0,0 +1,317 @@
+// 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 "base/threading/platform_thread.h"
+
+#include <stddef.h>
+
+#include "base/debug/activity_tracker.h"
+#include "base/debug/alias.h"
+#include "base/debug/profiler.h"
+#include "base/logging.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/threading/thread_id_name_manager.h"
+#include "base/threading/thread_restrictions.h"
+#include "base/win/scoped_handle.h"
+
+#include <windows.h>
+
+namespace base {
+
+namespace {
+
+// The information on how to set the thread name comes from
+// a MSDN article: http://msdn2.microsoft.com/en-us/library/xcb2z8hs.aspx
+const DWORD kVCThreadNameException = 0x406D1388;
+
+typedef struct tagTHREADNAME_INFO {
+  DWORD dwType;  // Must be 0x1000.
+  LPCSTR szName;  // Pointer to name (in user addr space).
+  DWORD dwThreadID;  // Thread ID (-1=caller thread).
+  DWORD dwFlags;  // Reserved for future use, must be zero.
+} THREADNAME_INFO;
+
+// The SetThreadDescription API was brought in version 1607 of Windows 10.
+typedef HRESULT(WINAPI* SetThreadDescription)(HANDLE hThread,
+                                              PCWSTR lpThreadDescription);
+
+// This function has try handling, so it is separated out of its caller.
+void SetNameInternal(PlatformThreadId thread_id, const char* name) {
+  THREADNAME_INFO info;
+  info.dwType = 0x1000;
+  info.szName = name;
+  info.dwThreadID = thread_id;
+  info.dwFlags = 0;
+
+  __try {
+    RaiseException(kVCThreadNameException, 0, sizeof(info)/sizeof(DWORD),
+                   reinterpret_cast<DWORD_PTR*>(&info));
+  } __except(EXCEPTION_CONTINUE_EXECUTION) {
+  }
+}
+
+struct ThreadParams {
+  PlatformThread::Delegate* delegate;
+  bool joinable;
+  ThreadPriority priority;
+};
+
+DWORD __stdcall ThreadFunc(void* params) {
+  ThreadParams* thread_params = static_cast<ThreadParams*>(params);
+  PlatformThread::Delegate* delegate = thread_params->delegate;
+  if (!thread_params->joinable)
+    base::ThreadRestrictions::SetSingletonAllowed(false);
+
+  if (thread_params->priority != ThreadPriority::NORMAL)
+    PlatformThread::SetCurrentThreadPriority(thread_params->priority);
+
+  // Retrieve a copy of the thread handle to use as the key in the
+  // thread name mapping.
+  PlatformThreadHandle::Handle platform_handle;
+  BOOL did_dup = DuplicateHandle(GetCurrentProcess(),
+                                GetCurrentThread(),
+                                GetCurrentProcess(),
+                                &platform_handle,
+                                0,
+                                FALSE,
+                                DUPLICATE_SAME_ACCESS);
+
+  win::ScopedHandle scoped_platform_handle;
+
+  if (did_dup) {
+    scoped_platform_handle.Set(platform_handle);
+    ThreadIdNameManager::GetInstance()->RegisterThread(
+        scoped_platform_handle.Get(),
+        PlatformThread::CurrentId());
+  }
+
+  delete thread_params;
+  delegate->ThreadMain();
+
+  if (did_dup) {
+    ThreadIdNameManager::GetInstance()->RemoveName(
+        scoped_platform_handle.Get(),
+        PlatformThread::CurrentId());
+  }
+
+  return 0;
+}
+
+// CreateThreadInternal() matches PlatformThread::CreateWithPriority(), except
+// that |out_thread_handle| may be nullptr, in which case a non-joinable thread
+// is created.
+bool CreateThreadInternal(size_t stack_size,
+                          PlatformThread::Delegate* delegate,
+                          PlatformThreadHandle* out_thread_handle,
+                          ThreadPriority priority) {
+  unsigned int flags = 0;
+  if (stack_size > 0) {
+    flags = STACK_SIZE_PARAM_IS_A_RESERVATION;
+  }
+
+  ThreadParams* params = new ThreadParams;
+  params->delegate = delegate;
+  params->joinable = out_thread_handle != nullptr;
+  params->priority = priority;
+
+  void* thread_handle;
+  {
+    SCOPED_UMA_HISTOGRAM_TIMER("Windows.CreateThreadTime");
+
+    // Using CreateThread here vs _beginthreadex makes thread creation a bit
+    // faster and doesn't require the loader lock to be available.  Our code
+    // will  have to work running on CreateThread() threads anyway, since we run
+    // code on the Windows thread pool, etc.  For some background on the
+    // difference:
+    //   http://www.microsoft.com/msj/1099/win32/win321099.aspx
+    thread_handle =
+        ::CreateThread(nullptr, stack_size, ThreadFunc, params, flags, nullptr);
+  }
+
+  if (!thread_handle) {
+    delete params;
+    return false;
+  }
+
+  if (out_thread_handle)
+    *out_thread_handle = PlatformThreadHandle(thread_handle);
+  else
+    CloseHandle(thread_handle);
+  return true;
+}
+
+}  // namespace
+
+// static
+PlatformThreadId PlatformThread::CurrentId() {
+  return ::GetCurrentThreadId();
+}
+
+// static
+PlatformThreadRef PlatformThread::CurrentRef() {
+  return PlatformThreadRef(::GetCurrentThreadId());
+}
+
+// static
+PlatformThreadHandle PlatformThread::CurrentHandle() {
+  return PlatformThreadHandle(::GetCurrentThread());
+}
+
+// static
+void PlatformThread::YieldCurrentThread() {
+  ::Sleep(0);
+}
+
+// static
+void PlatformThread::Sleep(TimeDelta duration) {
+  // When measured with a high resolution clock, Sleep() sometimes returns much
+  // too early. We may need to call it repeatedly to get the desired duration.
+  TimeTicks end = TimeTicks::Now() + duration;
+  for (TimeTicks now = TimeTicks::Now(); now < end; now = TimeTicks::Now())
+    ::Sleep(static_cast<DWORD>((end - now).InMillisecondsRoundedUp()));
+}
+
+// static
+void PlatformThread::SetName(const std::string& name) {
+  ThreadIdNameManager::GetInstance()->SetName(name);
+
+  // The SetThreadDescription API works even if no debugger is attached.
+  auto set_thread_description_func =
+      reinterpret_cast<SetThreadDescription>(::GetProcAddress(
+          ::GetModuleHandle(L"Kernel32.dll"), "SetThreadDescription"));
+  if (set_thread_description_func) {
+    set_thread_description_func(::GetCurrentThread(),
+                                base::UTF8ToWide(name).c_str());
+  }
+
+  // The debugger needs to be around to catch the name in the exception.  If
+  // there isn't a debugger, we are just needlessly throwing an exception.
+  if (!::IsDebuggerPresent())
+    return;
+
+  SetNameInternal(CurrentId(), name.c_str());
+}
+
+// static
+const char* PlatformThread::GetName() {
+  return ThreadIdNameManager::GetInstance()->GetName(CurrentId());
+}
+
+// static
+bool PlatformThread::CreateWithPriority(size_t stack_size, Delegate* delegate,
+                                        PlatformThreadHandle* thread_handle,
+                                        ThreadPriority priority) {
+  DCHECK(thread_handle);
+  return CreateThreadInternal(stack_size, delegate, thread_handle, priority);
+}
+
+// static
+bool PlatformThread::CreateNonJoinable(size_t stack_size, Delegate* delegate) {
+  return CreateNonJoinableWithPriority(stack_size, delegate,
+                                       ThreadPriority::NORMAL);
+}
+
+// static
+bool PlatformThread::CreateNonJoinableWithPriority(size_t stack_size,
+                                                   Delegate* delegate,
+                                                   ThreadPriority priority) {
+  return CreateThreadInternal(stack_size, delegate, nullptr /* non-joinable */,
+                              priority);
+}
+
+// static
+void PlatformThread::Join(PlatformThreadHandle thread_handle) {
+  DCHECK(thread_handle.platform_handle());
+  // TODO(willchan): Enable this check once I can get it to work for Windows
+  // shutdown.
+  // Joining another thread may block the current thread for a long time, since
+  // the thread referred to by |thread_handle| may still be running long-lived /
+  // blocking tasks.
+  // AssertBlockingAllowed();
+
+  DWORD thread_id = 0;
+  thread_id = ::GetThreadId(thread_handle.platform_handle());
+  DWORD last_error = 0;
+  if (!thread_id)
+    last_error = ::GetLastError();
+
+  // Record information about the exiting thread in case joining hangs.
+  base::debug::Alias(&thread_id);
+  base::debug::Alias(&last_error);
+
+  // Record the event that this thread is blocking upon (for hang diagnosis).
+  base::debug::ScopedThreadJoinActivity thread_activity(&thread_handle);
+
+  // Wait for the thread to exit.  It should already have terminated but make
+  // sure this assumption is valid.
+  CHECK_EQ(WAIT_OBJECT_0,
+           WaitForSingleObject(thread_handle.platform_handle(), INFINITE));
+  CloseHandle(thread_handle.platform_handle());
+}
+
+// static
+void PlatformThread::Detach(PlatformThreadHandle thread_handle) {
+  CloseHandle(thread_handle.platform_handle());
+}
+
+// static
+bool PlatformThread::CanIncreaseCurrentThreadPriority() {
+  return true;
+}
+
+// static
+void PlatformThread::SetCurrentThreadPriority(ThreadPriority priority) {
+  int desired_priority = THREAD_PRIORITY_ERROR_RETURN;
+  switch (priority) {
+    case ThreadPriority::BACKGROUND:
+      desired_priority = THREAD_PRIORITY_LOWEST;
+      break;
+    case ThreadPriority::NORMAL:
+      desired_priority = THREAD_PRIORITY_NORMAL;
+      break;
+    case ThreadPriority::DISPLAY:
+      desired_priority = THREAD_PRIORITY_ABOVE_NORMAL;
+      break;
+    case ThreadPriority::REALTIME_AUDIO:
+      desired_priority = THREAD_PRIORITY_TIME_CRITICAL;
+      break;
+    default:
+      NOTREACHED() << "Unknown priority.";
+      break;
+  }
+  DCHECK_NE(desired_priority, THREAD_PRIORITY_ERROR_RETURN);
+
+#if DCHECK_IS_ON()
+  const BOOL success =
+#endif
+      ::SetThreadPriority(PlatformThread::CurrentHandle().platform_handle(),
+                          desired_priority);
+  DPLOG_IF(ERROR, !success) << "Failed to set thread priority to "
+                            << desired_priority;
+}
+
+// static
+ThreadPriority PlatformThread::GetCurrentThreadPriority() {
+  int priority =
+      ::GetThreadPriority(PlatformThread::CurrentHandle().platform_handle());
+  switch (priority) {
+    case THREAD_PRIORITY_LOWEST:
+      return ThreadPriority::BACKGROUND;
+    case THREAD_PRIORITY_NORMAL:
+      return ThreadPriority::NORMAL;
+    case THREAD_PRIORITY_ABOVE_NORMAL:
+      return ThreadPriority::DISPLAY;
+    case THREAD_PRIORITY_TIME_CRITICAL:
+      return ThreadPriority::REALTIME_AUDIO;
+    case THREAD_PRIORITY_ERROR_RETURN:
+      DPCHECK(false) << "GetThreadPriority error";
+      FALLTHROUGH;
+    default:
+      NOTREACHED() << "Unexpected priority: " << priority;
+      return ThreadPriority::NORMAL;
+  }
+}
+
+}  // namespace base
diff --git a/base/threading/post_task_and_reply_impl.cc b/base/threading/post_task_and_reply_impl.cc
new file mode 100644
index 0000000..5aacdad
--- /dev/null
+++ b/base/threading/post_task_and_reply_impl.cc
@@ -0,0 +1,127 @@
+// Copyright (c) 2011 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 "base/threading/post_task_and_reply_impl.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/debug/leak_annotations.h"
+#include "base/logging.h"
+#include "base/memory/ref_counted.h"
+#include "base/sequenced_task_runner.h"
+#include "base/threading/sequenced_task_runner_handle.h"
+
+namespace base {
+
+namespace {
+
+class PostTaskAndReplyRelay {
+ public:
+  PostTaskAndReplyRelay(const Location& from_here,
+                        OnceClosure task,
+                        OnceClosure reply)
+      : from_here_(from_here),
+        task_(std::move(task)),
+        reply_(std::move(reply)) {}
+  PostTaskAndReplyRelay(PostTaskAndReplyRelay&&) = default;
+
+  ~PostTaskAndReplyRelay() {
+    if (reply_) {
+      // This can run:
+      // 1) On origin sequence, when:
+      //    1a) Posting |task_| fails.
+      //    1b) |reply_| is cancelled before running.
+      //    1c) The DeleteSoon() below is scheduled.
+      // 2) On destination sequence, when:
+      //    2a) |task_| is cancelled before running.
+      //    2b) Posting |reply_| fails.
+
+      if (!reply_task_runner_->RunsTasksInCurrentSequence()) {
+        // Case 2a) or 2b).
+        //
+        // Destroy callbacks asynchronously on |reply_task_runner| since their
+        // destructors can rightfully be affine to it. As always, DeleteSoon()
+        // might leak its argument if the target execution environment is
+        // shutdown (e.g. MessageLoop deleted, TaskScheduler shutdown).
+        //
+        // Note: while it's obvious why |reply_| can be affine to
+        // |reply_task_runner|, the reason that |task_| can also be affine to it
+        // is that it if neither tasks ran, |task_| may still hold an object
+        // which was intended to be moved to |reply_| when |task_| ran (such an
+        // object's destruction can be affine to |reply_task_runner_| -- e.g.
+        // https://crbug.com/829122).
+        auto relay_to_delete =
+            std::make_unique<PostTaskAndReplyRelay>(std::move(*this));
+        ANNOTATE_LEAKING_OBJECT_PTR(relay_to_delete.get());
+        reply_task_runner_->DeleteSoon(from_here_, std::move(relay_to_delete));
+      }
+
+      // Case 1a), 1b), 1c).
+      //
+      // Callbacks will be destroyed synchronously at the end of this scope.
+    } else {
+      // This can run when both callbacks have run or have been moved to another
+      // PostTaskAndReplyRelay instance. If |reply_| is null, |task_| must be
+      // null too.
+      DCHECK(!task_);
+    }
+  }
+
+  // No assignment operator because of const members.
+  PostTaskAndReplyRelay& operator=(PostTaskAndReplyRelay&&) = delete;
+
+  // Static function is used because it is not possible to bind a method call to
+  // a non-pointer type.
+  static void RunTaskAndPostReply(PostTaskAndReplyRelay relay) {
+    DCHECK(relay.task_);
+    std::move(relay.task_).Run();
+
+    // Keep a reference to the reply TaskRunner for the PostTask() call before
+    // |relay| is moved into a callback.
+    scoped_refptr<SequencedTaskRunner> reply_task_runner =
+        relay.reply_task_runner_;
+
+    reply_task_runner->PostTask(
+        relay.from_here_,
+        BindOnce(&PostTaskAndReplyRelay::RunReply, std::move(relay)));
+  }
+
+ private:
+  // Static function is used because it is not possible to bind a method call to
+  // a non-pointer type.
+  static void RunReply(PostTaskAndReplyRelay relay) {
+    DCHECK(!relay.task_);
+    DCHECK(relay.reply_);
+    std::move(relay.reply_).Run();
+  }
+
+  const Location from_here_;
+  OnceClosure task_;
+  OnceClosure reply_;
+  const scoped_refptr<SequencedTaskRunner> reply_task_runner_ =
+      SequencedTaskRunnerHandle::Get();
+
+  DISALLOW_COPY_AND_ASSIGN(PostTaskAndReplyRelay);
+};
+
+}  // namespace
+
+namespace internal {
+
+bool PostTaskAndReplyImpl::PostTaskAndReply(const Location& from_here,
+                                            OnceClosure task,
+                                            OnceClosure reply) {
+  DCHECK(task) << from_here.ToString();
+  DCHECK(reply) << from_here.ToString();
+
+  return PostTask(from_here,
+                  BindOnce(&PostTaskAndReplyRelay::RunTaskAndPostReply,
+                           PostTaskAndReplyRelay(from_here, std::move(task),
+                                                 std::move(reply))));
+}
+
+}  // namespace internal
+
+}  // namespace base
diff --git a/base/threading/post_task_and_reply_impl.h b/base/threading/post_task_and_reply_impl.h
new file mode 100644
index 0000000..54038ce
--- /dev/null
+++ b/base/threading/post_task_and_reply_impl.h
@@ -0,0 +1,46 @@
+// Copyright (c) 2011 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.
+
+// This file contains the implementation for TaskRunner::PostTaskAndReply.
+
+#ifndef BASE_THREADING_POST_TASK_AND_REPLY_IMPL_H_
+#define BASE_THREADING_POST_TASK_AND_REPLY_IMPL_H_
+
+#include "base/base_export.h"
+#include "base/callback.h"
+#include "base/location.h"
+
+namespace base {
+namespace internal {
+
+// Inherit from this in a class that implements PostTask to send a task to a
+// custom execution context.
+//
+// If you're looking for a concrete implementation of PostTaskAndReply, you
+// probably want base::TaskRunner or base/task_scheduler/post_task.h
+class BASE_EXPORT PostTaskAndReplyImpl {
+ public:
+  virtual ~PostTaskAndReplyImpl() = default;
+
+  // Posts |task| by calling PostTask(). On completion, posts |reply| to the
+  // origin sequence. Can only be called when
+  // SequencedTaskRunnerHandle::IsSet(). Each callback is deleted synchronously
+  // after running, or scheduled for asynchronous deletion on the origin
+  // sequence if it can't run (e.g. if a TaskRunner skips it on shutdown). See
+  // SequencedTaskRunner::DeleteSoon() for when objects scheduled for
+  // asynchronous deletion can be leaked. Note: All //base task posting APIs
+  // require callbacks to support deletion on the posting sequence if they can't
+  // be scheduled.
+  bool PostTaskAndReply(const Location& from_here,
+                        OnceClosure task,
+                        OnceClosure reply);
+
+ private:
+  virtual bool PostTask(const Location& from_here, OnceClosure task) = 0;
+};
+
+}  // namespace internal
+}  // namespace base
+
+#endif  // BASE_THREADING_POST_TASK_AND_REPLY_IMPL_H_
diff --git a/base/threading/post_task_and_reply_impl_unittest.cc b/base/threading/post_task_and_reply_impl_unittest.cc
new file mode 100644
index 0000000..319327d
--- /dev/null
+++ b/base/threading/post_task_and_reply_impl_unittest.cc
@@ -0,0 +1,198 @@
+// Copyright 2016 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 "base/threading/post_task_and_reply_impl.h"
+
+#include <utility>
+
+#include "base/auto_reset.h"
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/test/test_mock_time_task_runner.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::_;
+
+namespace base {
+namespace internal {
+
+namespace {
+
+class PostTaskAndReplyTaskRunner : public internal::PostTaskAndReplyImpl {
+ public:
+  explicit PostTaskAndReplyTaskRunner(TaskRunner* destination)
+      : destination_(destination) {}
+
+ private:
+  bool PostTask(const Location& from_here, OnceClosure task) override {
+    return destination_->PostTask(from_here, std::move(task));
+  }
+
+  // Non-owning.
+  TaskRunner* const destination_;
+};
+
+class ObjectToDelete : public RefCounted<ObjectToDelete> {
+ public:
+  // |delete_flag| is set to true when this object is deleted
+  ObjectToDelete(bool* delete_flag) : delete_flag_(delete_flag) {
+    EXPECT_FALSE(*delete_flag_);
+  }
+
+ private:
+  friend class RefCounted<ObjectToDelete>;
+  ~ObjectToDelete() { *delete_flag_ = true; }
+
+  bool* const delete_flag_;
+
+  DISALLOW_COPY_AND_ASSIGN(ObjectToDelete);
+};
+
+class MockObject {
+ public:
+  MockObject() = default;
+
+  MOCK_METHOD1(Task, void(scoped_refptr<ObjectToDelete>));
+  MOCK_METHOD1(Reply, void(scoped_refptr<ObjectToDelete>));
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MockObject);
+};
+
+class MockRunsTasksInCurrentSequenceTaskRunner : public TestMockTimeTaskRunner {
+ public:
+  MockRunsTasksInCurrentSequenceTaskRunner(
+      TestMockTimeTaskRunner::Type type =
+          TestMockTimeTaskRunner::Type::kStandalone)
+      : TestMockTimeTaskRunner(type) {}
+
+  void RunUntilIdleWithRunsTasksInCurrentSequence() {
+    AutoReset<bool> reset(&runs_tasks_in_current_sequence_, true);
+    RunUntilIdle();
+  }
+
+  void ClearPendingTasksWithRunsTasksInCurrentSequence() {
+    AutoReset<bool> reset(&runs_tasks_in_current_sequence_, true);
+    ClearPendingTasks();
+  }
+
+  // TestMockTimeTaskRunner:
+  bool RunsTasksInCurrentSequence() const override {
+    return runs_tasks_in_current_sequence_;
+  }
+
+ private:
+  ~MockRunsTasksInCurrentSequenceTaskRunner() override = default;
+
+  bool runs_tasks_in_current_sequence_ = false;
+
+  DISALLOW_COPY_AND_ASSIGN(MockRunsTasksInCurrentSequenceTaskRunner);
+};
+
+class PostTaskAndReplyImplTest : public testing::Test {
+ protected:
+  PostTaskAndReplyImplTest() = default;
+
+  void PostTaskAndReplyToMockObject() {
+    // Expect the post to succeed.
+    EXPECT_TRUE(
+        PostTaskAndReplyTaskRunner(post_runner_.get())
+            .PostTaskAndReply(
+                FROM_HERE,
+                BindOnce(&MockObject::Task, Unretained(&mock_object_),
+                         MakeRefCounted<ObjectToDelete>(&delete_task_flag_)),
+                BindOnce(&MockObject::Reply, Unretained(&mock_object_),
+                         MakeRefCounted<ObjectToDelete>(&delete_reply_flag_))));
+
+    // Expect the first task to be posted to |post_runner_|.
+    EXPECT_TRUE(post_runner_->HasPendingTask());
+    EXPECT_FALSE(reply_runner_->HasPendingTask());
+    EXPECT_FALSE(delete_task_flag_);
+    EXPECT_FALSE(delete_reply_flag_);
+  }
+
+  scoped_refptr<MockRunsTasksInCurrentSequenceTaskRunner> post_runner_ =
+      MakeRefCounted<MockRunsTasksInCurrentSequenceTaskRunner>();
+  scoped_refptr<MockRunsTasksInCurrentSequenceTaskRunner> reply_runner_ =
+      MakeRefCounted<MockRunsTasksInCurrentSequenceTaskRunner>(
+          TestMockTimeTaskRunner::Type::kBoundToThread);
+  testing::StrictMock<MockObject> mock_object_;
+  bool delete_task_flag_ = false;
+  bool delete_reply_flag_ = false;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(PostTaskAndReplyImplTest);
+};
+
+}  // namespace
+
+TEST_F(PostTaskAndReplyImplTest, PostTaskAndReply) {
+  PostTaskAndReplyToMockObject();
+
+  EXPECT_CALL(mock_object_, Task(_));
+  post_runner_->RunUntilIdleWithRunsTasksInCurrentSequence();
+  testing::Mock::VerifyAndClear(&mock_object_);
+  // The task should have been deleted right after being run.
+  EXPECT_TRUE(delete_task_flag_);
+  EXPECT_FALSE(delete_reply_flag_);
+
+  // Expect the reply to be posted to |reply_runner_|.
+  EXPECT_FALSE(post_runner_->HasPendingTask());
+  EXPECT_TRUE(reply_runner_->HasPendingTask());
+
+  EXPECT_CALL(mock_object_, Reply(_));
+  reply_runner_->RunUntilIdleWithRunsTasksInCurrentSequence();
+  testing::Mock::VerifyAndClear(&mock_object_);
+  EXPECT_TRUE(delete_task_flag_);
+  // The reply should have been deleted right after being run.
+  EXPECT_TRUE(delete_reply_flag_);
+
+  // Expect no pending task in |post_runner_| and |reply_runner_|.
+  EXPECT_FALSE(post_runner_->HasPendingTask());
+  EXPECT_FALSE(reply_runner_->HasPendingTask());
+}
+
+TEST_F(PostTaskAndReplyImplTest, TaskDoesNotRun) {
+  PostTaskAndReplyToMockObject();
+
+  // Clear the |post_runner_|. Both callbacks should be scheduled for deletion
+  // on the |reply_runner_|.
+  post_runner_->ClearPendingTasksWithRunsTasksInCurrentSequence();
+  EXPECT_FALSE(post_runner_->HasPendingTask());
+  EXPECT_TRUE(reply_runner_->HasPendingTask());
+  EXPECT_FALSE(delete_task_flag_);
+  EXPECT_FALSE(delete_reply_flag_);
+
+  // Run the |reply_runner_|. Both callbacks should be deleted.
+  reply_runner_->RunUntilIdleWithRunsTasksInCurrentSequence();
+  EXPECT_TRUE(delete_task_flag_);
+  EXPECT_TRUE(delete_reply_flag_);
+}
+
+TEST_F(PostTaskAndReplyImplTest, ReplyDoesNotRun) {
+  PostTaskAndReplyToMockObject();
+
+  EXPECT_CALL(mock_object_, Task(_));
+  post_runner_->RunUntilIdleWithRunsTasksInCurrentSequence();
+  testing::Mock::VerifyAndClear(&mock_object_);
+  // The task should have been deleted right after being run.
+  EXPECT_TRUE(delete_task_flag_);
+  EXPECT_FALSE(delete_reply_flag_);
+
+  // Expect the reply to be posted to |reply_runner_|.
+  EXPECT_FALSE(post_runner_->HasPendingTask());
+  EXPECT_TRUE(reply_runner_->HasPendingTask());
+
+  // Clear the |reply_runner_| queue without running tasks. The reply callback
+  // should be deleted.
+  reply_runner_->ClearPendingTasksWithRunsTasksInCurrentSequence();
+  EXPECT_TRUE(delete_task_flag_);
+  EXPECT_TRUE(delete_reply_flag_);
+}
+
+}  // namespace internal
+}  // namespace base
diff --git a/base/threading/scoped_blocking_call.cc b/base/threading/scoped_blocking_call.cc
new file mode 100644
index 0000000..1d2931c
--- /dev/null
+++ b/base/threading/scoped_blocking_call.cc
@@ -0,0 +1,72 @@
+// Copyright 2017 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 "base/threading/scoped_blocking_call.h"
+
+#include "base/lazy_instance.h"
+#include "base/threading/thread_local.h"
+
+namespace base {
+
+namespace {
+
+LazyInstance<ThreadLocalPointer<internal::BlockingObserver>>::Leaky
+    tls_blocking_observer = LAZY_INSTANCE_INITIALIZER;
+
+// Last ScopedBlockingCall instantiated on this thread.
+LazyInstance<ThreadLocalPointer<ScopedBlockingCall>>::Leaky
+    tls_last_scoped_blocking_call = LAZY_INSTANCE_INITIALIZER;
+
+}  // namespace
+
+ScopedBlockingCall::ScopedBlockingCall(BlockingType blocking_type)
+    : blocking_observer_(tls_blocking_observer.Get().Get()),
+      previous_scoped_blocking_call_(tls_last_scoped_blocking_call.Get().Get()),
+      is_will_block_(blocking_type == BlockingType::WILL_BLOCK ||
+                     (previous_scoped_blocking_call_ &&
+                      previous_scoped_blocking_call_->is_will_block_)) {
+  tls_last_scoped_blocking_call.Get().Set(this);
+
+  if (blocking_observer_) {
+    if (!previous_scoped_blocking_call_) {
+      blocking_observer_->BlockingStarted(blocking_type);
+    } else if (blocking_type == BlockingType::WILL_BLOCK &&
+               !previous_scoped_blocking_call_->is_will_block_) {
+      blocking_observer_->BlockingTypeUpgraded();
+    }
+  }
+}
+
+ScopedBlockingCall::~ScopedBlockingCall() {
+  DCHECK_EQ(this, tls_last_scoped_blocking_call.Get().Get());
+  tls_last_scoped_blocking_call.Get().Set(previous_scoped_blocking_call_);
+  if (blocking_observer_ && !previous_scoped_blocking_call_)
+    blocking_observer_->BlockingEnded();
+}
+
+namespace internal {
+
+void SetBlockingObserverForCurrentThread(BlockingObserver* blocking_observer) {
+  DCHECK(!tls_blocking_observer.Get().Get());
+  tls_blocking_observer.Get().Set(blocking_observer);
+}
+
+void ClearBlockingObserverForTesting() {
+  tls_blocking_observer.Get().Set(nullptr);
+}
+
+ScopedClearBlockingObserverForTesting::ScopedClearBlockingObserverForTesting()
+    : blocking_observer_(tls_blocking_observer.Get().Get()) {
+  tls_blocking_observer.Get().Set(nullptr);
+}
+
+ScopedClearBlockingObserverForTesting::
+    ~ScopedClearBlockingObserverForTesting() {
+  DCHECK(!tls_blocking_observer.Get().Get());
+  tls_blocking_observer.Get().Set(blocking_observer_);
+}
+
+}  // namespace internal
+
+}  // namespace base
diff --git a/base/threading/scoped_blocking_call.h b/base/threading/scoped_blocking_call.h
new file mode 100644
index 0000000..e376c30
--- /dev/null
+++ b/base/threading/scoped_blocking_call.h
@@ -0,0 +1,140 @@
+// Copyright 2017 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.
+
+#ifndef BASE_THREADING_SCOPED_BLOCKING_CALL_H
+#define BASE_THREADING_SCOPED_BLOCKING_CALL_H
+
+#include "base/base_export.h"
+#include "base/logging.h"
+
+namespace base {
+
+// BlockingType indicates the likelihood that a blocking call will actually
+// block.
+enum class BlockingType {
+  // The call might block (e.g. file I/O that might hit in memory cache).
+  MAY_BLOCK,
+  // The call will definitely block (e.g. cache already checked and now pinging
+  // server synchronously).
+  WILL_BLOCK
+};
+
+namespace internal {
+class BlockingObserver;
+}
+
+// This class must be instantiated in every scope where a blocking call is made.
+// CPU usage should be minimal within that scope. //base APIs that block
+// instantiate their own ScopedBlockingCall; it is not necessary to instantiate
+// another ScopedBlockingCall in the scope where these APIs are used.
+//
+// Good:
+//   Data data;
+//   {
+//     ScopedBlockingCall scoped_blocking_call(BlockingType::WILL_BLOCK);
+//     data = GetDataFromNetwork();
+//   }
+//   CPUIntensiveProcessing(data);
+//
+// Bad:
+//   ScopedBlockingCall scoped_blocking_call(BlockingType::WILL_BLOCK);
+//   Data data = GetDataFromNetwork();
+//   CPUIntensiveProcessing(data);  // CPU usage within a ScopedBlockingCall.
+//
+// Good:
+//   Data a;
+//   Data b;
+//   {
+//     ScopedBlockingCall scoped_blocking_call(BlockingType::MAY_BLOCK);
+//     a = GetDataFromMemoryCacheOrNetwork();
+//     b = GetDataFromMemoryCacheOrNetwork();
+//   }
+//   CPUIntensiveProcessing(a);
+//   CPUIntensiveProcessing(b);
+//
+// Bad:
+//   ScopedBlockingCall scoped_blocking_call(BlockingType::MAY_BLOCK);
+//   Data a = GetDataFromMemoryCacheOrNetwork();
+//   Data b = GetDataFromMemoryCacheOrNetwork();
+//   CPUIntensiveProcessing(a);  // CPU usage within a ScopedBlockingCall.
+//   CPUIntensiveProcessing(b);  // CPU usage within a ScopedBlockingCall.
+//
+// Good:
+//   base::WaitableEvent waitable_event(...);
+//   waitable_event.Wait();
+//
+// Bad:
+//  base::WaitableEvent waitable_event(...);
+//  ScopedBlockingCall scoped_blocking_call(BlockingType::WILL_BLOCK);
+//  waitable_event.Wait();  // Wait() instantiates its own ScopedBlockingCall.
+//
+// When a ScopedBlockingCall is instantiated from a TaskScheduler parallel or
+// sequenced task, the thread pool size is incremented to compensate for the
+// blocked thread (more or less aggressively depending on BlockingType).
+class BASE_EXPORT ScopedBlockingCall {
+ public:
+  ScopedBlockingCall(BlockingType blocking_type);
+  ~ScopedBlockingCall();
+
+ private:
+  internal::BlockingObserver* const blocking_observer_;
+
+  // Previous ScopedBlockingCall instantiated on this thread.
+  ScopedBlockingCall* const previous_scoped_blocking_call_;
+
+  // Whether the BlockingType of the current thread was WILL_BLOCK after this
+  // ScopedBlockingCall was instantiated.
+  const bool is_will_block_;
+
+  DISALLOW_COPY_AND_ASSIGN(ScopedBlockingCall);
+};
+
+namespace internal {
+
+// Interface for an observer to be informed when a thread enters or exits
+// the scope of ScopedBlockingCall objects.
+class BASE_EXPORT BlockingObserver {
+ public:
+  virtual ~BlockingObserver() = default;
+
+  // Invoked when a ScopedBlockingCall is instantiated on the observed thread
+  // where there wasn't an existing ScopedBlockingCall.
+  virtual void BlockingStarted(BlockingType blocking_type) = 0;
+
+  // Invoked when a WILL_BLOCK ScopedBlockingCall is instantiated on the
+  // observed thread where there was a MAY_BLOCK ScopedBlockingCall but not a
+  // WILL_BLOCK ScopedBlockingCall.
+  virtual void BlockingTypeUpgraded() = 0;
+
+  // Invoked when the last ScopedBlockingCall on the observed thread is
+  // destroyed.
+  virtual void BlockingEnded() = 0;
+};
+
+// Registers |blocking_observer| on the current thread. It is invalid to call
+// this on a thread where there is an active ScopedBlockingCall.
+BASE_EXPORT void SetBlockingObserverForCurrentThread(
+    BlockingObserver* blocking_observer);
+
+BASE_EXPORT void ClearBlockingObserverForTesting();
+
+// Unregisters the |blocking_observer| on the current thread within its scope.
+// Used in TaskScheduler tests to prevent calls to //base sync primitives from
+// affecting the thread pool capacity.
+class BASE_EXPORT ScopedClearBlockingObserverForTesting {
+ public:
+  ScopedClearBlockingObserverForTesting();
+  ~ScopedClearBlockingObserverForTesting();
+
+ private:
+  BlockingObserver* const blocking_observer_;
+
+  DISALLOW_COPY_AND_ASSIGN(ScopedClearBlockingObserverForTesting);
+};
+
+}  // namespace internal
+
+}  // namespace base
+
+#endif  // BASE_THREADING_SCOPED_BLOCKING_CALL_H
diff --git a/base/threading/scoped_blocking_call_unittest.cc b/base/threading/scoped_blocking_call_unittest.cc
new file mode 100644
index 0000000..5e030f3
--- /dev/null
+++ b/base/threading/scoped_blocking_call_unittest.cc
@@ -0,0 +1,134 @@
+// Copyright 2017 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 "base/threading/scoped_blocking_call.h"
+
+#include <memory>
+
+#include "base/macros.h"
+#include "base/test/gtest_util.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+
+namespace {
+
+class MockBlockingObserver : public internal::BlockingObserver {
+ public:
+  MockBlockingObserver() = default;
+
+  MOCK_METHOD1(BlockingStarted, void(BlockingType));
+  MOCK_METHOD0(BlockingTypeUpgraded, void());
+  MOCK_METHOD0(BlockingEnded, void());
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MockBlockingObserver);
+};
+
+class ScopedBlockingCallTest : public testing::Test {
+ protected:
+  ScopedBlockingCallTest() {
+    internal::SetBlockingObserverForCurrentThread(&observer_);
+  }
+
+  ~ScopedBlockingCallTest() override {
+    internal::ClearBlockingObserverForTesting();
+  }
+
+  testing::StrictMock<MockBlockingObserver> observer_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ScopedBlockingCallTest);
+};
+
+}  // namespace
+
+TEST_F(ScopedBlockingCallTest, MayBlock) {
+  EXPECT_CALL(observer_, BlockingStarted(BlockingType::MAY_BLOCK));
+  ScopedBlockingCall scoped_blocking_call(BlockingType::MAY_BLOCK);
+  testing::Mock::VerifyAndClear(&observer_);
+  EXPECT_CALL(observer_, BlockingEnded());
+}
+
+TEST_F(ScopedBlockingCallTest, WillBlock) {
+  EXPECT_CALL(observer_, BlockingStarted(BlockingType::WILL_BLOCK));
+  ScopedBlockingCall scoped_blocking_call(BlockingType::WILL_BLOCK);
+  testing::Mock::VerifyAndClear(&observer_);
+  EXPECT_CALL(observer_, BlockingEnded());
+}
+
+TEST_F(ScopedBlockingCallTest, MayBlockWillBlock) {
+  EXPECT_CALL(observer_, BlockingStarted(BlockingType::MAY_BLOCK));
+  ScopedBlockingCall scoped_blocking_call_a(BlockingType::MAY_BLOCK);
+  testing::Mock::VerifyAndClear(&observer_);
+
+  {
+    EXPECT_CALL(observer_, BlockingTypeUpgraded());
+    ScopedBlockingCall scoped_blocking_call_b(BlockingType::WILL_BLOCK);
+    testing::Mock::VerifyAndClear(&observer_);
+  }
+
+  EXPECT_CALL(observer_, BlockingEnded());
+}
+
+TEST_F(ScopedBlockingCallTest, WillBlockMayBlock) {
+  EXPECT_CALL(observer_, BlockingStarted(BlockingType::WILL_BLOCK));
+  ScopedBlockingCall scoped_blocking_call_a(BlockingType::WILL_BLOCK);
+  testing::Mock::VerifyAndClear(&observer_);
+
+  { ScopedBlockingCall scoped_blocking_call_b(BlockingType::MAY_BLOCK); }
+
+  EXPECT_CALL(observer_, BlockingEnded());
+}
+
+TEST_F(ScopedBlockingCallTest, MayBlockMayBlock) {
+  EXPECT_CALL(observer_, BlockingStarted(BlockingType::MAY_BLOCK));
+  ScopedBlockingCall scoped_blocking_call_a(BlockingType::MAY_BLOCK);
+  testing::Mock::VerifyAndClear(&observer_);
+
+  { ScopedBlockingCall scoped_blocking_call_b(BlockingType::MAY_BLOCK); }
+
+  EXPECT_CALL(observer_, BlockingEnded());
+}
+
+TEST_F(ScopedBlockingCallTest, WillBlockWillBlock) {
+  EXPECT_CALL(observer_, BlockingStarted(BlockingType::WILL_BLOCK));
+  ScopedBlockingCall scoped_blocking_call_a(BlockingType::WILL_BLOCK);
+  testing::Mock::VerifyAndClear(&observer_);
+
+  { ScopedBlockingCall scoped_blocking_call_b(BlockingType::WILL_BLOCK); }
+
+  EXPECT_CALL(observer_, BlockingEnded());
+}
+
+TEST_F(ScopedBlockingCallTest, MayBlockWillBlockTwice) {
+  EXPECT_CALL(observer_, BlockingStarted(BlockingType::MAY_BLOCK));
+  ScopedBlockingCall scoped_blocking_call_a(BlockingType::MAY_BLOCK);
+  testing::Mock::VerifyAndClear(&observer_);
+
+  {
+    EXPECT_CALL(observer_, BlockingTypeUpgraded());
+    ScopedBlockingCall scoped_blocking_call_b(BlockingType::WILL_BLOCK);
+    testing::Mock::VerifyAndClear(&observer_);
+
+    {
+      ScopedBlockingCall scoped_blocking_call_c(BlockingType::MAY_BLOCK);
+      ScopedBlockingCall scoped_blocking_call_d(BlockingType::WILL_BLOCK);
+    }
+  }
+
+  EXPECT_CALL(observer_, BlockingEnded());
+}
+
+TEST(ScopedBlockingCallDestructionOrderTest, InvalidDestructionOrder) {
+  auto scoped_blocking_call_a =
+      std::make_unique<ScopedBlockingCall>(BlockingType::WILL_BLOCK);
+  auto scoped_blocking_call_b =
+      std::make_unique<ScopedBlockingCall>(BlockingType::WILL_BLOCK);
+
+  EXPECT_DCHECK_DEATH({ scoped_blocking_call_a.reset(); });
+}
+
+}  // namespace base
diff --git a/base/threading/sequence_local_storage_map.cc b/base/threading/sequence_local_storage_map.cc
new file mode 100644
index 0000000..2837aa0
--- /dev/null
+++ b/base/threading/sequence_local_storage_map.cc
@@ -0,0 +1,105 @@
+// Copyright 2017 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 "base/threading/sequence_local_storage_map.h"
+
+#include <utility>
+
+#include "base/lazy_instance.h"
+#include "base/logging.h"
+#include "base/threading/thread_local.h"
+
+namespace base {
+namespace internal {
+
+namespace {
+LazyInstance<ThreadLocalPointer<SequenceLocalStorageMap>>::Leaky
+    tls_current_sequence_local_storage = LAZY_INSTANCE_INITIALIZER;
+}  // namespace
+
+SequenceLocalStorageMap::SequenceLocalStorageMap() = default;
+
+SequenceLocalStorageMap::~SequenceLocalStorageMap() = default;
+
+ScopedSetSequenceLocalStorageMapForCurrentThread::
+    ScopedSetSequenceLocalStorageMapForCurrentThread(
+        SequenceLocalStorageMap* sequence_local_storage) {
+  DCHECK(!tls_current_sequence_local_storage.Get().Get());
+  tls_current_sequence_local_storage.Get().Set(sequence_local_storage);
+}
+
+ScopedSetSequenceLocalStorageMapForCurrentThread::
+    ~ScopedSetSequenceLocalStorageMapForCurrentThread() {
+  tls_current_sequence_local_storage.Get().Set(nullptr);
+}
+
+SequenceLocalStorageMap& SequenceLocalStorageMap::GetForCurrentThread() {
+  SequenceLocalStorageMap* current_sequence_local_storage =
+      tls_current_sequence_local_storage.Get().Get();
+
+  DCHECK(current_sequence_local_storage)
+      << "SequenceLocalStorageSlot cannot be used because no "
+         "SequenceLocalStorageMap was stored in TLS. Use "
+         "ScopedSetSequenceLocalStorageMapForCurrentThread to store a "
+         "SequenceLocalStorageMap object in TLS.";
+
+  return *current_sequence_local_storage;
+}
+
+void* SequenceLocalStorageMap::Get(int slot_id) {
+  const auto it = sls_map_.find(slot_id);
+  if (it == sls_map_.end())
+    return nullptr;
+  return it->second.value();
+}
+
+void SequenceLocalStorageMap::Set(
+    int slot_id,
+    SequenceLocalStorageMap::ValueDestructorPair value_destructor_pair) {
+  auto it = sls_map_.find(slot_id);
+
+  if (it == sls_map_.end())
+    sls_map_.emplace(slot_id, std::move(value_destructor_pair));
+  else
+    it->second = std::move(value_destructor_pair);
+
+  // The maximum number of entries in the map is 256. This can be adjusted, but
+  // will require reviewing the choice of data structure for the map.
+  DCHECK_LE(sls_map_.size(), 256U);
+}
+
+SequenceLocalStorageMap::ValueDestructorPair::ValueDestructorPair(
+    void* value,
+    DestructorFunc* destructor)
+    : value_(value), destructor_(destructor) {}
+
+SequenceLocalStorageMap::ValueDestructorPair::~ValueDestructorPair() {
+  if (value_)
+    destructor_(value_);
+}
+
+SequenceLocalStorageMap::ValueDestructorPair::ValueDestructorPair(
+    ValueDestructorPair&& value_destructor_pair)
+    : value_(value_destructor_pair.value_),
+      destructor_(value_destructor_pair.destructor_) {
+  value_destructor_pair.value_ = nullptr;
+}
+
+SequenceLocalStorageMap::ValueDestructorPair&
+SequenceLocalStorageMap::ValueDestructorPair::operator=(
+    ValueDestructorPair&& value_destructor_pair) {
+  // Destroy |value_| before overwriting it with a new value.
+  if (value_)
+    destructor_(value_);
+
+  value_ = value_destructor_pair.value_;
+  destructor_ = value_destructor_pair.destructor_;
+
+  value_destructor_pair.value_ = nullptr;
+
+  return *this;
+}
+
+}  // namespace internal
+}  // namespace base
diff --git a/base/threading/sequence_local_storage_map.h b/base/threading/sequence_local_storage_map.h
new file mode 100644
index 0000000..8b9155c
--- /dev/null
+++ b/base/threading/sequence_local_storage_map.h
@@ -0,0 +1,90 @@
+// Copyright 2017 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.
+
+#ifndef BASE_THREADING_SEQUENCE_LOCAL_STORAGE_MAP_H_
+#define BASE_THREADING_SEQUENCE_LOCAL_STORAGE_MAP_H_
+
+#include "base/base_export.h"
+#include "base/containers/flat_map.h"
+#include "base/macros.h"
+
+namespace base {
+namespace internal {
+
+// A SequenceLocalStorageMap holds (slot_id) -> (value, destructor) items for a
+// sequence. When a task runs, it is expected that a pointer to its sequence's
+// SequenceLocalStorageMap is set in TLS using
+// ScopedSetSequenceMapLocalStorageForCurrentThread. When a
+// SequenceLocalStorageMap is destroyed, it invokes the destructors associated
+// with values stored within it.
+// The Get() and Set() methods should not be accessed directly.
+// Use SequenceLocalStorageSlot to Get() and Set() values in the current
+// sequence's SequenceLocalStorageMap.
+class BASE_EXPORT SequenceLocalStorageMap {
+ public:
+  SequenceLocalStorageMap();
+  ~SequenceLocalStorageMap();
+
+  // Returns the SequenceLocalStorage bound to the current thread. It is invalid
+  // to call this outside the scope of a
+  // ScopedSetSequenceLocalStorageForCurrentThread.
+  static SequenceLocalStorageMap& GetForCurrentThread();
+
+  // Holds a pointer to a value alongside a destructor for this pointer.
+  // Calls the destructor on the value upon destruction.
+  class BASE_EXPORT ValueDestructorPair {
+   public:
+    using DestructorFunc = void(void*);
+
+    ValueDestructorPair(void* value, DestructorFunc* destructor);
+    ~ValueDestructorPair();
+
+    ValueDestructorPair(ValueDestructorPair&& value_destructor_pair);
+
+    ValueDestructorPair& operator=(ValueDestructorPair&& value_destructor_pair);
+
+    void* value() const { return value_; }
+
+   private:
+    void* value_;
+    DestructorFunc* destructor_;
+
+    DISALLOW_COPY_AND_ASSIGN(ValueDestructorPair);
+  };
+
+  // Returns the value stored in |slot_id| or nullptr if no value was stored.
+  void* Get(int slot_id);
+
+  // Stores |value_destructor_pair| in |slot_id|. Overwrites and destroys any
+  // previously stored value.
+  void Set(int slot_id, ValueDestructorPair value_destructor_pair);
+
+ private:
+  // Map from slot id to ValueDestructorPair.
+  // flat_map was chosen because there are expected to be relatively few entries
+  // in the map. For low number of entries, flat_map is known to perform better
+  // than other map implementations.
+  base::flat_map<int, ValueDestructorPair> sls_map_;
+
+  DISALLOW_COPY_AND_ASSIGN(SequenceLocalStorageMap);
+};
+
+// Within the scope of this object,
+// SequenceLocalStorageMap::GetForCurrentThread() will return a reference to the
+// SequenceLocalStorageMap object passed to the constructor. There can be only
+// one ScopedSetSequenceLocalStorageMapForCurrentThread instance per scope.
+class BASE_EXPORT ScopedSetSequenceLocalStorageMapForCurrentThread {
+ public:
+  ScopedSetSequenceLocalStorageMapForCurrentThread(
+      SequenceLocalStorageMap* sequence_local_storage);
+
+  ~ScopedSetSequenceLocalStorageMapForCurrentThread();
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ScopedSetSequenceLocalStorageMapForCurrentThread);
+};
+}  // namespace internal
+}  // namespace base
+
+#endif  // BASE_THREADING_SEQUENCE_LOCAL_STORAGE_MAP_H_
diff --git a/base/threading/sequence_local_storage_map_unittest.cc b/base/threading/sequence_local_storage_map_unittest.cc
new file mode 100644
index 0000000..a45bbc3
--- /dev/null
+++ b/base/threading/sequence_local_storage_map_unittest.cc
@@ -0,0 +1,117 @@
+// Copyright 2017 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 "base/threading/sequence_local_storage_map.h"
+
+#include <memory>
+#include <utility>
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+namespace internal {
+
+namespace {
+
+constexpr int kSlotId = 1;
+
+class SetOnDestroy {
+ public:
+  SetOnDestroy(bool* was_destroyed_ptr)
+      : was_destroyed_ptr_(was_destroyed_ptr) {
+    DCHECK(was_destroyed_ptr_);
+    DCHECK(!(*was_destroyed_ptr_));
+  }
+  ~SetOnDestroy() {
+    DCHECK(!(*was_destroyed_ptr_));
+    *was_destroyed_ptr_ = true;
+  }
+
+ private:
+  bool* const was_destroyed_ptr_;
+
+  DISALLOW_COPY_AND_ASSIGN(SetOnDestroy);
+};
+
+template <typename T, typename... Args>
+SequenceLocalStorageMap::ValueDestructorPair CreateValueDestructorPair(
+    Args... args) {
+  T* value = new T(args...);
+  SequenceLocalStorageMap::ValueDestructorPair::DestructorFunc* destructor =
+      [](void* ptr) { std::default_delete<T>()(static_cast<T*>(ptr)); };
+
+  SequenceLocalStorageMap::ValueDestructorPair value_destructor_pair{
+      value, destructor};
+
+  return value_destructor_pair;
+}
+
+}  // namespace
+
+// Verify that setting a value in the SequenceLocalStorageMap, then getting
+// it will yield the same value.
+TEST(SequenceLocalStorageMapTest, SetGet) {
+  SequenceLocalStorageMap sequence_local_storage_map;
+  ScopedSetSequenceLocalStorageMapForCurrentThread
+      scoped_sequence_local_storage_map(&sequence_local_storage_map);
+
+  SequenceLocalStorageMap::ValueDestructorPair value_destructor_pair =
+      CreateValueDestructorPair<int>(5);
+
+  sequence_local_storage_map.Set(kSlotId, std::move(value_destructor_pair));
+
+  EXPECT_EQ(*static_cast<int*>(sequence_local_storage_map.Get(kSlotId)), 5);
+}
+
+// Verify that the destructor is called on a value stored in the
+// SequenceLocalStorageMap when SequenceLocalStorageMap is destroyed.
+TEST(SequenceLocalStorageMapTest, Destructor) {
+  bool set_on_destruction = false;
+
+  {
+    SequenceLocalStorageMap sequence_local_storage_map;
+    ScopedSetSequenceLocalStorageMapForCurrentThread
+        scoped_sequence_local_storage_map(&sequence_local_storage_map);
+
+    SequenceLocalStorageMap::ValueDestructorPair value_destructor_pair =
+        CreateValueDestructorPair<SetOnDestroy>(&set_on_destruction);
+
+    sequence_local_storage_map.Set(kSlotId, std::move(value_destructor_pair));
+  }
+
+  EXPECT_TRUE(set_on_destruction);
+}
+
+// Verify that overwriting a value already in the SequenceLocalStorageMap
+// calls value's destructor.
+TEST(SequenceLocalStorageMapTest, DestructorCalledOnSetOverwrite) {
+  bool set_on_destruction = false;
+  bool set_on_destruction2 = false;
+  {
+    SequenceLocalStorageMap sequence_local_storage_map;
+    ScopedSetSequenceLocalStorageMapForCurrentThread
+        scoped_sequence_local_storage_map(&sequence_local_storage_map);
+
+    SequenceLocalStorageMap::ValueDestructorPair value_destructor_pair =
+        CreateValueDestructorPair<SetOnDestroy>(&set_on_destruction);
+    SequenceLocalStorageMap::ValueDestructorPair value_destructor_pair2 =
+        CreateValueDestructorPair<SetOnDestroy>(&set_on_destruction2);
+
+    sequence_local_storage_map.Set(kSlotId, std::move(value_destructor_pair));
+
+    ASSERT_FALSE(set_on_destruction);
+
+    // Overwrites the old value in the slot.
+    sequence_local_storage_map.Set(kSlotId, std::move(value_destructor_pair2));
+
+    // Destructor should've been called for the old value in the slot, and not
+    // yet called for the new value.
+    EXPECT_TRUE(set_on_destruction);
+    EXPECT_FALSE(set_on_destruction2);
+  }
+  EXPECT_TRUE(set_on_destruction2);
+}
+
+}  // namespace internal
+}  // namespace base
diff --git a/base/threading/sequence_local_storage_slot.cc b/base/threading/sequence_local_storage_slot.cc
new file mode 100644
index 0000000..b7db40b
--- /dev/null
+++ b/base/threading/sequence_local_storage_slot.cc
@@ -0,0 +1,26 @@
+// Copyright 2017 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 "base/threading/sequence_local_storage_slot.h"
+
+#include <limits>
+
+#include "base/atomic_sequence_num.h"
+#include "base/logging.h"
+
+namespace base {
+namespace internal {
+
+namespace {
+AtomicSequenceNumber g_sequence_local_storage_slot_generator;
+}  // namespace
+
+int GetNextSequenceLocalStorageSlotNumber() {
+  int slot_id = g_sequence_local_storage_slot_generator.GetNext();
+  DCHECK_LT(slot_id, std::numeric_limits<int>::max());
+  return slot_id;
+}
+
+}  // namespace internal
+}  // namespace base
diff --git a/base/threading/sequence_local_storage_slot.h b/base/threading/sequence_local_storage_slot.h
new file mode 100644
index 0000000..315df7d
--- /dev/null
+++ b/base/threading/sequence_local_storage_slot.h
@@ -0,0 +1,105 @@
+// Copyright 2017 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.
+
+#ifndef BASE_THREADING_SEQUENCE_LOCAL_STORAGE_SLOT_H_
+#define BASE_THREADING_SEQUENCE_LOCAL_STORAGE_SLOT_H_
+
+#include <memory>
+#include <utility>
+
+#include "base/base_export.h"
+#include "base/threading/sequence_local_storage_map.h"
+
+namespace base {
+
+namespace internal {
+BASE_EXPORT int GetNextSequenceLocalStorageSlotNumber();
+}
+
+// SequenceLocalStorageSlot allows arbitrary values to be stored and retrieved
+// from a sequence. Values are deleted when the sequence is deleted.
+//
+// Example usage:
+//
+// namespace {
+// base::LazyInstance<SequenceLocalStorageSlot<int>> sls_value;
+// }
+//
+// void Read() {
+//   int value = sls_value.Get().Get();
+//   ...
+// }
+//
+// void Write() {
+//   sls_value.Get().Set(42);
+// }
+//
+// void PostTasks() {
+//   // Since Read() runs on the same sequence as Write(), it
+//   // will read the value "42". A Read() running on a different
+//   // sequence would not see that value.
+//   scoped_refptr<base::SequencedTaskRunner> task_runner = ...;
+//   task_runner->PostTask(FROM_HERE, base::BindOnce(&Write));
+//   task_runner->PostTask(FROM_HERE, base::BindOnce(&Read));
+// }
+//
+// SequenceLocalStorageSlot must be used within the scope of a
+// ScopedSetSequenceLocalStorageMapForCurrentThread object.
+// Note: this is true on all TaskScheduler workers and on threads bound to a
+// MessageLoop.
+template <typename T, typename Deleter = std::default_delete<T>>
+class SequenceLocalStorageSlot {
+ public:
+  SequenceLocalStorageSlot()
+      : slot_id_(internal::GetNextSequenceLocalStorageSlotNumber()) {}
+  ~SequenceLocalStorageSlot() = default;
+
+  // Get the sequence-local value stored in this slot. Returns a
+  // default-constructed value if no value was previously set.
+  T& Get() {
+    void* value =
+        internal::SequenceLocalStorageMap::GetForCurrentThread().Get(slot_id_);
+
+    // Sets and returns a default-constructed value if no value was previously
+    // set.
+    if (!value) {
+      Set(T());
+      return Get();
+    }
+    return *(static_cast<T*>(value));
+  }
+
+  // Set this slot's sequence-local value to |value|.
+  // Note that if T is expensive to copy, it may be more appropriate to instead
+  // store a std::unique_ptr<T>. This is enforced by the
+  // DISALLOW_COPY_AND_ASSIGN style rather than directly by this class however.
+  void Set(T value) {
+    // Allocates the |value| with new rather than std::make_unique.
+    // Since SequenceLocalStorageMap needs to store values of various types
+    // within the same map, the type of value_destructor_pair.value is void*
+    // (std::unique_ptr<void> is invalid). Memory is freed by calling
+    // |value_destructor_pair.destructor| in the destructor of
+    // ValueDestructorPair which is invoked when the value is overwritten by
+    // another call to SequenceLocalStorageMap::Set or when the
+    // SequenceLocalStorageMap is deleted.
+    T* value_ptr = new T(std::move(value));
+
+    internal::SequenceLocalStorageMap::ValueDestructorPair::DestructorFunc*
+        destructor = [](void* ptr) { Deleter()(static_cast<T*>(ptr)); };
+
+    internal::SequenceLocalStorageMap::ValueDestructorPair
+        value_destructor_pair(value_ptr, destructor);
+
+    internal::SequenceLocalStorageMap::GetForCurrentThread().Set(
+        slot_id_, std::move(value_destructor_pair));
+  }
+
+ private:
+  // |slot_id_| is used as a key in SequenceLocalStorageMap
+  const int slot_id_;
+  DISALLOW_COPY_AND_ASSIGN(SequenceLocalStorageSlot);
+};
+
+}  // namespace base
+#endif  // BASE_THREADING_SEQUENCE_LOCAL_STORAGE_SLOT_H_
diff --git a/base/threading/sequence_local_storage_slot_unittest.cc b/base/threading/sequence_local_storage_slot_unittest.cc
new file mode 100644
index 0000000..4a9f6a9
--- /dev/null
+++ b/base/threading/sequence_local_storage_slot_unittest.cc
@@ -0,0 +1,143 @@
+// Copyright 2017 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 "base/threading/sequence_local_storage_slot.h"
+
+#include <utility>
+
+#include "base/macros.h"
+#include "base/memory/ptr_util.h"
+#include "base/threading/sequence_local_storage_map.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+
+namespace {
+
+class SequenceLocalStorageSlotTest : public testing::Test {
+ protected:
+  SequenceLocalStorageSlotTest()
+      : scoped_sequence_local_storage_(&sequence_local_storage_) {}
+
+  internal::SequenceLocalStorageMap sequence_local_storage_;
+  internal::ScopedSetSequenceLocalStorageMapForCurrentThread
+      scoped_sequence_local_storage_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(SequenceLocalStorageSlotTest);
+};
+
+}  // namespace
+
+// Verify that a value stored with Set() can be retrieved with Get().
+TEST_F(SequenceLocalStorageSlotTest, GetSet) {
+  SequenceLocalStorageSlot<int> slot;
+  slot.Set(5);
+  EXPECT_EQ(slot.Get(), 5);
+}
+
+// Verify that setting an object in a SequenceLocalStorageSlot creates a copy
+// of that object independent of the original one.
+TEST_F(SequenceLocalStorageSlotTest, SetObjectIsIndependent) {
+  bool should_be_false = false;
+
+  SequenceLocalStorageSlot<bool> slot;
+
+  slot.Set(should_be_false);
+
+  EXPECT_FALSE(slot.Get());
+  slot.Get() = true;
+  EXPECT_TRUE(slot.Get());
+
+  EXPECT_NE(should_be_false, slot.Get());
+}
+
+// Verify that multiple slots work and that calling Get after overwriting
+// a value in a slot yields the new value.
+TEST_F(SequenceLocalStorageSlotTest, GetSetMultipleSlots) {
+  SequenceLocalStorageSlot<int> slot1;
+  SequenceLocalStorageSlot<int> slot2;
+  SequenceLocalStorageSlot<int> slot3;
+
+  slot1.Set(1);
+  slot2.Set(2);
+  slot3.Set(3);
+
+  EXPECT_EQ(slot1.Get(), 1);
+  EXPECT_EQ(slot2.Get(), 2);
+  EXPECT_EQ(slot3.Get(), 3);
+
+  slot3.Set(4);
+  slot2.Set(5);
+  slot1.Set(6);
+
+  EXPECT_EQ(slot3.Get(), 4);
+  EXPECT_EQ(slot2.Get(), 5);
+  EXPECT_EQ(slot1.Get(), 6);
+}
+
+// Verify that changing the the value returned by Get() changes the value
+// in sequence local storage.
+TEST_F(SequenceLocalStorageSlotTest, GetReferenceModifiable) {
+  SequenceLocalStorageSlot<bool> slot;
+  slot.Set(false);
+  slot.Get() = true;
+  EXPECT_TRUE(slot.Get());
+}
+
+// Verify that a move-only type can be stored in sequence local storage.
+TEST_F(SequenceLocalStorageSlotTest, SetGetWithMoveOnlyType) {
+  std::unique_ptr<int> int_unique_ptr = std::make_unique<int>(5);
+
+  SequenceLocalStorageSlot<std::unique_ptr<int>> slot;
+  slot.Set(std::move(int_unique_ptr));
+
+  EXPECT_EQ(*slot.Get(), 5);
+}
+
+// Verify that a Get() without a previous Set() on a slot returns a
+// default-constructed value.
+TEST_F(SequenceLocalStorageSlotTest, GetWithoutSetDefaultConstructs) {
+  struct DefaultConstructable {
+    int x = 0x12345678;
+  };
+
+  SequenceLocalStorageSlot<DefaultConstructable> slot;
+
+  EXPECT_EQ(slot.Get().x, 0x12345678);
+}
+
+// Verify that a Get() without a previous Set() on a slot with a POD-type
+// returns a default-constructed value.
+// Note: this test could be flaky and give a false pass. If it's flaky, the test
+// might've "passed" because the memory for the slot happened to be zeroed.
+TEST_F(SequenceLocalStorageSlotTest, GetWithoutSetDefaultConstructsPOD) {
+  SequenceLocalStorageSlot<void*> slot;
+
+  EXPECT_EQ(slot.Get(), nullptr);
+}
+
+// Verify that the value of a slot is specific to a SequenceLocalStorageMap
+TEST(SequenceLocalStorageSlotMultipleMapTest, SetGetMultipleMapsOneSlot) {
+  SequenceLocalStorageSlot<unsigned int> slot;
+  internal::SequenceLocalStorageMap sequence_local_storage_maps[5];
+
+  // Set the value of the slot to be the index of the current
+  // SequenceLocalStorageMaps in the vector
+  for (unsigned int i = 0; i < arraysize(sequence_local_storage_maps); ++i) {
+    internal::ScopedSetSequenceLocalStorageMapForCurrentThread
+        scoped_sequence_local_storage(&sequence_local_storage_maps[i]);
+
+    slot.Set(i);
+  }
+
+  for (unsigned int i = 0; i < arraysize(sequence_local_storage_maps); ++i) {
+    internal::ScopedSetSequenceLocalStorageMapForCurrentThread
+        scoped_sequence_local_storage(&sequence_local_storage_maps[i]);
+
+    EXPECT_EQ(slot.Get(), i);
+  }
+}
+
+}  // namespace base
diff --git a/base/threading/sequenced_task_runner_handle.cc b/base/threading/sequenced_task_runner_handle.cc
new file mode 100644
index 0000000..e6920f5
--- /dev/null
+++ b/base/threading/sequenced_task_runner_handle.cc
@@ -0,0 +1,59 @@
+// Copyright 2015 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 "base/threading/sequenced_task_runner_handle.h"
+
+#include <utility>
+
+#include "base/lazy_instance.h"
+#include "base/logging.h"
+#include "base/threading/thread_local.h"
+#include "base/threading/thread_task_runner_handle.h"
+
+namespace base {
+
+namespace {
+
+LazyInstance<ThreadLocalPointer<SequencedTaskRunnerHandle>>::Leaky
+    sequenced_task_runner_tls = LAZY_INSTANCE_INITIALIZER;
+
+}  // namespace
+
+// static
+scoped_refptr<SequencedTaskRunner> SequencedTaskRunnerHandle::Get() {
+  // Return the registered SequencedTaskRunner, if any.
+  const SequencedTaskRunnerHandle* handle =
+      sequenced_task_runner_tls.Pointer()->Get();
+  if (handle)
+    return handle->task_runner_;
+
+  // Note if you hit this: the problem is the lack of a sequenced context. The
+  // ThreadTaskRunnerHandle is just the last attempt at finding such a context.
+  CHECK(ThreadTaskRunnerHandle::IsSet())
+      << "Error: This caller requires a sequenced context (i.e. the "
+         "current task needs to run from a SequencedTaskRunner).";
+  return ThreadTaskRunnerHandle::Get();
+}
+
+// static
+bool SequencedTaskRunnerHandle::IsSet() {
+  return sequenced_task_runner_tls.Pointer()->Get() ||
+         ThreadTaskRunnerHandle::IsSet();
+}
+
+SequencedTaskRunnerHandle::SequencedTaskRunnerHandle(
+    scoped_refptr<SequencedTaskRunner> task_runner)
+    : task_runner_(std::move(task_runner)) {
+  DCHECK(task_runner_->RunsTasksInCurrentSequence());
+  DCHECK(!SequencedTaskRunnerHandle::IsSet());
+  sequenced_task_runner_tls.Pointer()->Set(this);
+}
+
+SequencedTaskRunnerHandle::~SequencedTaskRunnerHandle() {
+  DCHECK(task_runner_->RunsTasksInCurrentSequence());
+  DCHECK_EQ(sequenced_task_runner_tls.Pointer()->Get(), this);
+  sequenced_task_runner_tls.Pointer()->Set(nullptr);
+}
+
+}  // namespace base
diff --git a/base/threading/sequenced_task_runner_handle.h b/base/threading/sequenced_task_runner_handle.h
new file mode 100644
index 0000000..f55cee5
--- /dev/null
+++ b/base/threading/sequenced_task_runner_handle.h
@@ -0,0 +1,43 @@
+// Copyright 2015 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.
+
+#ifndef BASE_THREADING_SEQUENCED_TASK_RUNNER_HANDLE_H_
+#define BASE_THREADING_SEQUENCED_TASK_RUNNER_HANDLE_H_
+
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/sequenced_task_runner.h"
+
+namespace base {
+
+class BASE_EXPORT SequencedTaskRunnerHandle {
+ public:
+  // Returns a SequencedTaskRunner which guarantees that posted tasks will only
+  // run after the current task is finished and will satisfy a SequenceChecker.
+  // It should only be called if IsSet() returns true (see the comment there for
+  // the requirements).
+  static scoped_refptr<SequencedTaskRunner> Get();
+
+  // Returns true if one of the following conditions is fulfilled:
+  // a) A SequencedTaskRunner has been assigned to the current thread by
+  //    instantiating a SequencedTaskRunnerHandle.
+  // b) The current thread has a ThreadTaskRunnerHandle (which includes any
+  //    thread that has a MessageLoop associated with it).
+  static bool IsSet();
+
+  // Binds |task_runner| to the current thread.
+  explicit SequencedTaskRunnerHandle(
+      scoped_refptr<SequencedTaskRunner> task_runner);
+  ~SequencedTaskRunnerHandle();
+
+ private:
+  scoped_refptr<SequencedTaskRunner> task_runner_;
+
+  DISALLOW_COPY_AND_ASSIGN(SequencedTaskRunnerHandle);
+};
+
+}  // namespace base
+
+#endif  // BASE_THREADING_SEQUENCED_TASK_RUNNER_HANDLE_H_
diff --git a/base/threading/sequenced_task_runner_handle_unittest.cc b/base/threading/sequenced_task_runner_handle_unittest.cc
new file mode 100644
index 0000000..48394da
--- /dev/null
+++ b/base/threading/sequenced_task_runner_handle_unittest.cc
@@ -0,0 +1,90 @@
+// Copyright 2015 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 "base/threading/sequenced_task_runner_handle.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/location.h"
+#include "base/memory/ref_counted.h"
+#include "base/run_loop.h"
+#include "base/sequence_checker_impl.h"
+#include "base/sequenced_task_runner.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/task_scheduler/post_task.h"
+#include "base/test/scoped_task_environment.h"
+#include "base/test/test_simple_task_runner.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+namespace {
+
+class SequencedTaskRunnerHandleTest : public ::testing::Test {
+ protected:
+  // Verifies that the context it runs on has a SequencedTaskRunnerHandle
+  // and that posting to it results in the posted task running in that same
+  // context (sequence).
+  static void VerifyCurrentSequencedTaskRunner() {
+    ASSERT_TRUE(SequencedTaskRunnerHandle::IsSet());
+    scoped_refptr<SequencedTaskRunner> task_runner =
+        SequencedTaskRunnerHandle::Get();
+    ASSERT_TRUE(task_runner);
+
+    // Use SequenceCheckerImpl to make sure it's not a no-op in Release builds.
+    std::unique_ptr<SequenceCheckerImpl> sequence_checker(
+        new SequenceCheckerImpl);
+    task_runner->PostTask(
+        FROM_HERE,
+        base::BindOnce(&SequencedTaskRunnerHandleTest::CheckValidSequence,
+                       std::move(sequence_checker)));
+  }
+
+  static void CheckValidSequence(
+      std::unique_ptr<SequenceCheckerImpl> sequence_checker) {
+    EXPECT_TRUE(sequence_checker->CalledOnValidSequence());
+  }
+
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
+};
+
+TEST_F(SequencedTaskRunnerHandleTest, FromMessageLoop) {
+  VerifyCurrentSequencedTaskRunner();
+  RunLoop().RunUntilIdle();
+}
+
+TEST_F(SequencedTaskRunnerHandleTest, FromTaskSchedulerSequencedTask) {
+  base::CreateSequencedTaskRunnerWithTraits({})->PostTask(
+      FROM_HERE,
+      base::BindOnce(
+          &SequencedTaskRunnerHandleTest::VerifyCurrentSequencedTaskRunner));
+  scoped_task_environment_.RunUntilIdle();
+}
+
+TEST_F(SequencedTaskRunnerHandleTest, NoHandleFromUnsequencedTask) {
+  base::PostTask(FROM_HERE, base::BindOnce([]() {
+                   EXPECT_FALSE(SequencedTaskRunnerHandle::IsSet());
+                 }));
+  scoped_task_environment_.RunUntilIdle();
+}
+
+TEST(SequencedTaskRunnerHandleTestWithoutMessageLoop, FromHandleInScope) {
+  scoped_refptr<SequencedTaskRunner> test_task_runner(new TestSimpleTaskRunner);
+  EXPECT_FALSE(SequencedTaskRunnerHandle::IsSet());
+  EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet());
+  {
+    SequencedTaskRunnerHandle handle(test_task_runner);
+    EXPECT_TRUE(SequencedTaskRunnerHandle::IsSet());
+    EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet());
+    EXPECT_EQ(test_task_runner, SequencedTaskRunnerHandle::Get());
+  }
+  EXPECT_FALSE(SequencedTaskRunnerHandle::IsSet());
+  EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet());
+}
+
+}  // namespace
+}  // namespace base
diff --git a/base/threading/simple_thread.cc b/base/threading/simple_thread.cc
new file mode 100644
index 0000000..04a5285
--- /dev/null
+++ b/base/threading/simple_thread.cc
@@ -0,0 +1,182 @@
+// Copyright (c) 2010 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 "base/threading/simple_thread.h"
+
+#include "base/logging.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/threading/platform_thread.h"
+#include "base/threading/thread_restrictions.h"
+
+namespace base {
+
+SimpleThread::SimpleThread(const std::string& name_prefix)
+    : SimpleThread(name_prefix, Options()) {}
+
+SimpleThread::SimpleThread(const std::string& name_prefix,
+                           const Options& options)
+    : name_prefix_(name_prefix),
+      options_(options),
+      event_(WaitableEvent::ResetPolicy::MANUAL,
+             WaitableEvent::InitialState::NOT_SIGNALED) {}
+
+SimpleThread::~SimpleThread() {
+  DCHECK(HasBeenStarted()) << "SimpleThread was never started.";
+  DCHECK(!options_.joinable || HasBeenJoined())
+      << "Joinable SimpleThread destroyed without being Join()ed.";
+}
+
+void SimpleThread::Start() {
+  StartAsync();
+  ThreadRestrictions::ScopedAllowWait allow_wait;
+  event_.Wait();  // Wait for the thread to complete initialization.
+}
+
+void SimpleThread::Join() {
+  DCHECK(options_.joinable) << "A non-joinable thread can't be joined.";
+  DCHECK(HasStartBeenAttempted()) << "Tried to Join a never-started thread.";
+  DCHECK(!HasBeenJoined()) << "Tried to Join a thread multiple times.";
+  BeforeJoin();
+  PlatformThread::Join(thread_);
+  thread_ = PlatformThreadHandle();
+  joined_ = true;
+}
+
+void SimpleThread::StartAsync() {
+  DCHECK(!HasStartBeenAttempted()) << "Tried to Start a thread multiple times.";
+  start_called_ = true;
+  BeforeStart();
+  bool success =
+      options_.joinable
+          ? PlatformThread::CreateWithPriority(options_.stack_size, this,
+                                               &thread_, options_.priority)
+          : PlatformThread::CreateNonJoinableWithPriority(
+                options_.stack_size, this, options_.priority);
+  DCHECK(success);
+}
+
+PlatformThreadId SimpleThread::tid() {
+  DCHECK(HasBeenStarted());
+  return tid_;
+}
+
+bool SimpleThread::HasBeenStarted() {
+  ThreadRestrictions::ScopedAllowWait allow_wait;
+  return event_.IsSignaled();
+}
+
+void SimpleThread::ThreadMain() {
+  tid_ = PlatformThread::CurrentId();
+  // Construct our full name of the form "name_prefix_/TID".
+  std::string name(name_prefix_);
+  name.push_back('/');
+  name.append(IntToString(tid_));
+  PlatformThread::SetName(name);
+
+  // We've initialized our new thread, signal that we're done to Start().
+  event_.Signal();
+
+  BeforeRun();
+  Run();
+}
+
+DelegateSimpleThread::DelegateSimpleThread(Delegate* delegate,
+                                           const std::string& name_prefix)
+    : DelegateSimpleThread(delegate, name_prefix, Options()) {}
+
+DelegateSimpleThread::DelegateSimpleThread(Delegate* delegate,
+                                           const std::string& name_prefix,
+                                           const Options& options)
+    : SimpleThread(name_prefix, options),
+      delegate_(delegate) {
+  DCHECK(delegate_);
+}
+
+DelegateSimpleThread::~DelegateSimpleThread() = default;
+
+void DelegateSimpleThread::Run() {
+  DCHECK(delegate_) << "Tried to call Run without a delegate (called twice?)";
+
+  // Non-joinable DelegateSimpleThreads are allowed to be deleted during Run().
+  // Member state must not be accessed after invoking Run().
+  Delegate* delegate = delegate_;
+  delegate_ = nullptr;
+  delegate->Run();
+}
+
+DelegateSimpleThreadPool::DelegateSimpleThreadPool(
+    const std::string& name_prefix,
+    int num_threads)
+    : name_prefix_(name_prefix),
+      num_threads_(num_threads),
+      dry_(WaitableEvent::ResetPolicy::MANUAL,
+           WaitableEvent::InitialState::NOT_SIGNALED) {}
+
+DelegateSimpleThreadPool::~DelegateSimpleThreadPool() {
+  DCHECK(threads_.empty());
+  DCHECK(delegates_.empty());
+  DCHECK(!dry_.IsSignaled());
+}
+
+void DelegateSimpleThreadPool::Start() {
+  DCHECK(threads_.empty()) << "Start() called with outstanding threads.";
+  for (int i = 0; i < num_threads_; ++i) {
+    DelegateSimpleThread* thread = new DelegateSimpleThread(this, name_prefix_);
+    thread->Start();
+    threads_.push_back(thread);
+  }
+}
+
+void DelegateSimpleThreadPool::JoinAll() {
+  DCHECK(!threads_.empty()) << "JoinAll() called with no outstanding threads.";
+
+  // Tell all our threads to quit their worker loop.
+  AddWork(nullptr, num_threads_);
+
+  // Join and destroy all the worker threads.
+  for (int i = 0; i < num_threads_; ++i) {
+    threads_[i]->Join();
+    delete threads_[i];
+  }
+  threads_.clear();
+  DCHECK(delegates_.empty());
+}
+
+void DelegateSimpleThreadPool::AddWork(Delegate* delegate, int repeat_count) {
+  AutoLock locked(lock_);
+  for (int i = 0; i < repeat_count; ++i)
+    delegates_.push(delegate);
+  // If we were empty, signal that we have work now.
+  if (!dry_.IsSignaled())
+    dry_.Signal();
+}
+
+void DelegateSimpleThreadPool::Run() {
+  Delegate* work = nullptr;
+
+  while (true) {
+    dry_.Wait();
+    {
+      AutoLock locked(lock_);
+      if (!dry_.IsSignaled())
+        continue;
+
+      DCHECK(!delegates_.empty());
+      work = delegates_.front();
+      delegates_.pop();
+
+      // Signal to any other threads that we're currently out of work.
+      if (delegates_.empty())
+        dry_.Reset();
+    }
+
+    // A NULL delegate pointer signals us to quit.
+    if (!work)
+      break;
+
+    work->Run();
+  }
+}
+
+}  // namespace base
diff --git a/base/threading/simple_thread.h b/base/threading/simple_thread.h
new file mode 100644
index 0000000..976f557
--- /dev/null
+++ b/base/threading/simple_thread.h
@@ -0,0 +1,232 @@
+// Copyright (c) 2011 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.
+
+// WARNING: You should probably be using Thread (thread.h) instead.  Thread is
+//          Chrome's message-loop based Thread abstraction, and if you are a
+//          thread running in the browser, there will likely be assumptions
+//          that your thread will have an associated message loop.
+//
+// This is a simple thread interface that backs to a native operating system
+// thread.  You should use this only when you want a thread that does not have
+// an associated MessageLoop.  Unittesting is the best example of this.
+//
+// The simplest interface to use is DelegateSimpleThread, which will create
+// a new thread, and execute the Delegate's virtual Run() in this new thread
+// until it has completed, exiting the thread.
+//
+// NOTE: You *MUST* call Join on the thread to clean up the underlying thread
+// resources.  You are also responsible for destructing the SimpleThread object.
+// It is invalid to destroy a SimpleThread while it is running, or without
+// Start() having been called (and a thread never created).  The Delegate
+// object should live as long as a DelegateSimpleThread.
+//
+// Thread Safety: A SimpleThread is not completely thread safe.  It is safe to
+// access it from the creating thread or from the newly created thread.  This
+// implies that the creator thread should be the thread that calls Join.
+//
+// Example:
+//   class MyThreadRunner : public DelegateSimpleThread::Delegate { ... };
+//   MyThreadRunner runner;
+//   DelegateSimpleThread thread(&runner, "good_name_here");
+//   thread.Start();
+//   // Start will return after the Thread has been successfully started and
+//   // initialized.  The newly created thread will invoke runner->Run(), and
+//   // run until it returns.
+//   thread.Join();  // Wait until the thread has exited.  You *MUST* Join!
+//   // The SimpleThread object is still valid, however you may not call Join
+//   // or Start again.
+
+#ifndef BASE_THREADING_SIMPLE_THREAD_H_
+#define BASE_THREADING_SIMPLE_THREAD_H_
+
+#include <stddef.h>
+
+#include <string>
+#include <vector>
+
+#include "base/base_export.h"
+#include "base/compiler_specific.h"
+#include "base/containers/queue.h"
+#include "base/macros.h"
+#include "base/synchronization/lock.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/threading/platform_thread.h"
+
+namespace base {
+
+// This is the base SimpleThread.  You can derive from it and implement the
+// virtual Run method, or you can use the DelegateSimpleThread interface.
+class BASE_EXPORT SimpleThread : public PlatformThread::Delegate {
+ public:
+  struct BASE_EXPORT Options {
+   public:
+    Options() = default;
+    explicit Options(ThreadPriority priority_in) : priority(priority_in) {}
+    ~Options() = default;
+
+    // Allow copies.
+    Options(const Options& other) = default;
+    Options& operator=(const Options& other) = default;
+
+    // A custom stack size, or 0 for the system default.
+    size_t stack_size = 0;
+
+    ThreadPriority priority = ThreadPriority::NORMAL;
+
+    // If false, the underlying thread's PlatformThreadHandle will not be kept
+    // around and as such the SimpleThread instance will not be Join()able and
+    // must not be deleted before Run() is invoked. After that, it's up to
+    // the subclass to determine when it is safe to delete itself.
+    bool joinable = true;
+  };
+
+  // Create a SimpleThread.  |options| should be used to manage any specific
+  // configuration involving the thread creation and management.
+  // Every thread has a name, in the form of |name_prefix|/TID, for example
+  // "my_thread/321".  The thread will not be created until Start() is called.
+  explicit SimpleThread(const std::string& name_prefix);
+  SimpleThread(const std::string& name_prefix, const Options& options);
+
+  ~SimpleThread() override;
+
+  // Starts the thread and returns only after the thread has started and
+  // initialized (i.e. ThreadMain() has been called).
+  void Start();
+
+  // Joins the thread. If StartAsync() was used to start the thread, then this
+  // first waits for the thread to start cleanly, then it joins.
+  void Join();
+
+  // Starts the thread, but returns immediately, without waiting for the thread
+  // to have initialized first (i.e. this does not wait for ThreadMain() to have
+  // been run first).
+  void StartAsync();
+
+  // Subclasses should override the Run method.
+  virtual void Run() = 0;
+
+  // Returns the thread id, only valid after the thread has started. If the
+  // thread was started using Start(), then this will be valid after the call to
+  // Start(). If StartAsync() was used to start the thread, then this must not
+  // be called before HasBeenStarted() returns True.
+  PlatformThreadId tid();
+
+  // Returns True if the thread has been started and initialized (i.e. if
+  // ThreadMain() has run). If the thread was started with StartAsync(), but it
+  // hasn't been initialized yet (i.e. ThreadMain() has not run), then this will
+  // return False.
+  bool HasBeenStarted();
+
+  // Returns True if Join() has ever been called.
+  bool HasBeenJoined() { return joined_; }
+
+  // Returns true if Start() or StartAsync() has been called.
+  bool HasStartBeenAttempted() { return start_called_; }
+
+  // Overridden from PlatformThread::Delegate:
+  void ThreadMain() override;
+
+ private:
+  // This is called just before the thread is started. This is called regardless
+  // of whether Start() or StartAsync() is used to start the thread.
+  virtual void BeforeStart() {}
+
+  // This is called just after the thread has been initialized and just before
+  // Run() is called. This is called on the newly started thread.
+  virtual void BeforeRun() {}
+
+  // This is called just before the thread is joined. The thread is started and
+  // has been initialized before this is called.
+  virtual void BeforeJoin() {}
+
+  const std::string name_prefix_;
+  std::string name_;
+  const Options options_;
+  PlatformThreadHandle thread_;  // PlatformThread handle, reset after Join.
+  WaitableEvent event_;          // Signaled if Start() was ever called.
+  PlatformThreadId tid_ = kInvalidThreadId;  // The backing thread's id.
+  bool joined_ = false;                      // True if Join has been called.
+  // Set to true when the platform-thread creation has started.
+  bool start_called_ = false;
+
+  DISALLOW_COPY_AND_ASSIGN(SimpleThread);
+};
+
+// A SimpleThread which delegates Run() to its Delegate. Non-joinable
+// DelegateSimpleThread are safe to delete after Run() was invoked, their
+// Delegates are also safe to delete after that point from this class' point of
+// view (although implementations must of course make sure that Run() will not
+// use their Delegate's member state after its deletion).
+class BASE_EXPORT DelegateSimpleThread : public SimpleThread {
+ public:
+  class BASE_EXPORT Delegate {
+   public:
+    virtual ~Delegate() = default;
+    virtual void Run() = 0;
+  };
+
+  DelegateSimpleThread(Delegate* delegate,
+                       const std::string& name_prefix);
+  DelegateSimpleThread(Delegate* delegate,
+                       const std::string& name_prefix,
+                       const Options& options);
+
+  ~DelegateSimpleThread() override;
+  void Run() override;
+
+ private:
+  Delegate* delegate_;
+
+  DISALLOW_COPY_AND_ASSIGN(DelegateSimpleThread);
+};
+
+// DelegateSimpleThreadPool allows you to start up a fixed number of threads,
+// and then add jobs which will be dispatched to the threads.  This is
+// convenient when you have a lot of small work that you want done
+// multi-threaded, but don't want to spawn a thread for each small bit of work.
+//
+// You just call AddWork() to add a delegate to the list of work to be done.
+// JoinAll() will make sure that all outstanding work is processed, and wait
+// for everything to finish.  You can reuse a pool, so you can call Start()
+// again after you've called JoinAll().
+class BASE_EXPORT DelegateSimpleThreadPool
+    : public DelegateSimpleThread::Delegate {
+ public:
+  typedef DelegateSimpleThread::Delegate Delegate;
+
+  DelegateSimpleThreadPool(const std::string& name_prefix, int num_threads);
+  ~DelegateSimpleThreadPool() override;
+
+  // Start up all of the underlying threads, and start processing work if we
+  // have any.
+  void Start();
+
+  // Make sure all outstanding work is finished, and wait for and destroy all
+  // of the underlying threads in the pool.
+  void JoinAll();
+
+  // It is safe to AddWork() any time, before or after Start().
+  // Delegate* should always be a valid pointer, NULL is reserved internally.
+  void AddWork(Delegate* work, int repeat_count);
+  void AddWork(Delegate* work) {
+    AddWork(work, 1);
+  }
+
+  // We implement the Delegate interface, for running our internal threads.
+  void Run() override;
+
+ private:
+  const std::string name_prefix_;
+  int num_threads_;
+  std::vector<DelegateSimpleThread*> threads_;
+  base::queue<Delegate*> delegates_;
+  base::Lock lock_;            // Locks delegates_
+  WaitableEvent dry_;    // Not signaled when there is no work to do.
+
+  DISALLOW_COPY_AND_ASSIGN(DelegateSimpleThreadPool);
+};
+
+}  // namespace base
+
+#endif  // BASE_THREADING_SIMPLE_THREAD_H_
diff --git a/base/threading/simple_thread_unittest.cc b/base/threading/simple_thread_unittest.cc
new file mode 100644
index 0000000..4e618f9
--- /dev/null
+++ b/base/threading/simple_thread_unittest.cc
@@ -0,0 +1,234 @@
+// 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 <memory>
+
+#include "base/atomic_sequence_num.h"
+#include "base/memory/ptr_util.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/test/gtest_util.h"
+#include "base/threading/simple_thread.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+
+namespace {
+
+class SetIntRunner : public DelegateSimpleThread::Delegate {
+ public:
+  SetIntRunner(int* ptr, int val) : ptr_(ptr), val_(val) { }
+  ~SetIntRunner() override = default;
+
+ private:
+  void Run() override { *ptr_ = val_; }
+
+  int* ptr_;
+  int val_;
+
+  DISALLOW_COPY_AND_ASSIGN(SetIntRunner);
+};
+
+// Signals |started_| when Run() is invoked and waits until |released_| is
+// signaled to return, signaling |done_| before doing so. Useful for tests that
+// care to control Run()'s flow.
+class ControlledRunner : public DelegateSimpleThread::Delegate {
+ public:
+  ControlledRunner()
+      : started_(WaitableEvent::ResetPolicy::MANUAL,
+                 WaitableEvent::InitialState::NOT_SIGNALED),
+        released_(WaitableEvent::ResetPolicy::MANUAL,
+                  WaitableEvent::InitialState::NOT_SIGNALED),
+        done_(WaitableEvent::ResetPolicy::MANUAL,
+              WaitableEvent::InitialState::NOT_SIGNALED) {}
+
+  ~ControlledRunner() override { ReleaseAndWaitUntilDone(); }
+
+  void WaitUntilStarted() { started_.Wait(); }
+
+  void ReleaseAndWaitUntilDone() {
+    released_.Signal();
+    done_.Wait();
+  }
+
+ private:
+  void Run() override {
+    started_.Signal();
+    released_.Wait();
+    done_.Signal();
+  }
+
+  WaitableEvent started_;
+  WaitableEvent released_;
+  WaitableEvent done_;
+
+  DISALLOW_COPY_AND_ASSIGN(ControlledRunner);
+};
+
+class WaitEventRunner : public DelegateSimpleThread::Delegate {
+ public:
+  explicit WaitEventRunner(WaitableEvent* event) : event_(event) { }
+  ~WaitEventRunner() override = default;
+
+ private:
+  void Run() override {
+    EXPECT_FALSE(event_->IsSignaled());
+    event_->Signal();
+    EXPECT_TRUE(event_->IsSignaled());
+  }
+
+  WaitableEvent* event_;
+
+  DISALLOW_COPY_AND_ASSIGN(WaitEventRunner);
+};
+
+class SeqRunner : public DelegateSimpleThread::Delegate {
+ public:
+  explicit SeqRunner(AtomicSequenceNumber* seq) : seq_(seq) { }
+
+ private:
+  void Run() override { seq_->GetNext(); }
+
+  AtomicSequenceNumber* seq_;
+
+  DISALLOW_COPY_AND_ASSIGN(SeqRunner);
+};
+
+// We count up on a sequence number, firing on the event when we've hit our
+// expected amount, otherwise we wait on the event.  This will ensure that we
+// have all threads outstanding until we hit our expected thread pool size.
+class VerifyPoolRunner : public DelegateSimpleThread::Delegate {
+ public:
+  VerifyPoolRunner(AtomicSequenceNumber* seq,
+                   int total, WaitableEvent* event)
+      : seq_(seq), total_(total), event_(event) { }
+
+ private:
+  void Run() override {
+    if (seq_->GetNext() == total_) {
+      event_->Signal();
+    } else {
+      event_->Wait();
+    }
+  }
+
+  AtomicSequenceNumber* seq_;
+  int total_;
+  WaitableEvent* event_;
+
+  DISALLOW_COPY_AND_ASSIGN(VerifyPoolRunner);
+};
+
+}  // namespace
+
+TEST(SimpleThreadTest, CreateAndJoin) {
+  int stack_int = 0;
+
+  SetIntRunner runner(&stack_int, 7);
+  EXPECT_EQ(0, stack_int);
+
+  DelegateSimpleThread thread(&runner, "int_setter");
+  EXPECT_FALSE(thread.HasBeenStarted());
+  EXPECT_FALSE(thread.HasBeenJoined());
+  EXPECT_EQ(0, stack_int);
+
+  thread.Start();
+  EXPECT_TRUE(thread.HasBeenStarted());
+  EXPECT_FALSE(thread.HasBeenJoined());
+
+  thread.Join();
+  EXPECT_TRUE(thread.HasBeenStarted());
+  EXPECT_TRUE(thread.HasBeenJoined());
+  EXPECT_EQ(7, stack_int);
+}
+
+TEST(SimpleThreadTest, WaitForEvent) {
+  // Create a thread, and wait for it to signal us.
+  WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL,
+                      WaitableEvent::InitialState::NOT_SIGNALED);
+
+  WaitEventRunner runner(&event);
+  DelegateSimpleThread thread(&runner, "event_waiter");
+
+  EXPECT_FALSE(event.IsSignaled());
+  thread.Start();
+  event.Wait();
+  EXPECT_TRUE(event.IsSignaled());
+  thread.Join();
+}
+
+TEST(SimpleThreadTest, NonJoinableStartAndDieOnJoin) {
+  ControlledRunner runner;
+
+  SimpleThread::Options options;
+  options.joinable = false;
+  DelegateSimpleThread thread(&runner, "non_joinable", options);
+
+  EXPECT_FALSE(thread.HasBeenStarted());
+  thread.Start();
+  EXPECT_TRUE(thread.HasBeenStarted());
+
+  // Note: this is not quite the same as |thread.HasBeenStarted()| which
+  // represents ThreadMain() getting ready to invoke Run() whereas
+  // |runner.WaitUntilStarted()| ensures Run() was actually invoked.
+  runner.WaitUntilStarted();
+
+  EXPECT_FALSE(thread.HasBeenJoined());
+  EXPECT_DCHECK_DEATH({ thread.Join(); });
+}
+
+TEST(SimpleThreadTest, NonJoinableInactiveDelegateDestructionIsOkay) {
+  std::unique_ptr<ControlledRunner> runner(new ControlledRunner);
+
+  SimpleThread::Options options;
+  options.joinable = false;
+  std::unique_ptr<DelegateSimpleThread> thread(
+      new DelegateSimpleThread(runner.get(), "non_joinable", options));
+
+  thread->Start();
+  runner->WaitUntilStarted();
+
+  // Deleting a non-joinable SimpleThread after Run() was invoked is okay.
+  thread.reset();
+
+  runner->WaitUntilStarted();
+  runner->ReleaseAndWaitUntilDone();
+  // It should be safe to destroy a Delegate after its Run() method completed.
+  runner.reset();
+}
+
+TEST(SimpleThreadTest, ThreadPool) {
+  AtomicSequenceNumber seq;
+  SeqRunner runner(&seq);
+  DelegateSimpleThreadPool pool("seq_runner", 10);
+
+  // Add work before we're running.
+  pool.AddWork(&runner, 300);
+
+  EXPECT_EQ(seq.GetNext(), 0);
+  pool.Start();
+
+  // Add work while we're running.
+  pool.AddWork(&runner, 300);
+
+  pool.JoinAll();
+
+  EXPECT_EQ(seq.GetNext(), 601);
+
+  // We can reuse our pool.  Verify that all 10 threads can actually run in
+  // parallel, so this test will only pass if there are actually 10 threads.
+  AtomicSequenceNumber seq2;
+  WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL,
+                      WaitableEvent::InitialState::NOT_SIGNALED);
+  // Changing 9 to 10, for example, would cause us JoinAll() to never return.
+  VerifyPoolRunner verifier(&seq2, 9, &event);
+  pool.Start();
+
+  pool.AddWork(&verifier, 10);
+
+  pool.JoinAll();
+  EXPECT_EQ(seq2.GetNext(), 10);
+}
+
+}  // namespace base
diff --git a/base/threading/thread.cc b/base/threading/thread.cc
new file mode 100644
index 0000000..97e160f
--- /dev/null
+++ b/base/threading/thread.cc
@@ -0,0 +1,370 @@
+// 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 "base/threading/thread.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/lazy_instance.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/run_loop.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
+#include "base/threading/thread_id_name_manager.h"
+#include "base/threading/thread_local.h"
+#include "base/threading/thread_restrictions.h"
+#include "build/build_config.h"
+
+#if defined(OS_POSIX) && !defined(OS_NACL)
+#include "base/files/file_descriptor_watcher_posix.h"
+#endif
+
+#if defined(OS_WIN)
+#include "base/win/scoped_com_initializer.h"
+#endif
+
+namespace base {
+
+namespace {
+
+// We use this thread-local variable to record whether or not a thread exited
+// because its Stop method was called.  This allows us to catch cases where
+// MessageLoop::QuitWhenIdle() is called directly, which is unexpected when
+// using a Thread to setup and run a MessageLoop.
+base::LazyInstance<base::ThreadLocalBoolean>::Leaky lazy_tls_bool =
+    LAZY_INSTANCE_INITIALIZER;
+
+}  // namespace
+
+Thread::Options::Options() = default;
+
+Thread::Options::Options(MessageLoop::Type type, size_t size)
+    : message_loop_type(type), stack_size(size) {}
+
+Thread::Options::Options(const Options& other) = default;
+
+Thread::Options::~Options() = default;
+
+Thread::Thread(const std::string& name)
+    : id_event_(WaitableEvent::ResetPolicy::MANUAL,
+                WaitableEvent::InitialState::NOT_SIGNALED),
+      name_(name),
+      start_event_(WaitableEvent::ResetPolicy::MANUAL,
+                   WaitableEvent::InitialState::NOT_SIGNALED) {
+  // Only bind the sequence on Start(): the state is constant between
+  // construction and Start() and it's thus valid for Start() to be called on
+  // another sequence as long as every other operation is then performed on that
+  // sequence.
+  owning_sequence_checker_.DetachFromSequence();
+}
+
+Thread::~Thread() {
+  Stop();
+}
+
+bool Thread::Start() {
+  DCHECK(owning_sequence_checker_.CalledOnValidSequence());
+
+  Options options;
+#if defined(OS_WIN)
+  if (com_status_ == STA)
+    options.message_loop_type = MessageLoop::TYPE_UI;
+#endif
+  return StartWithOptions(options);
+}
+
+bool Thread::StartWithOptions(const Options& options) {
+  DCHECK(owning_sequence_checker_.CalledOnValidSequence());
+  DCHECK(!message_loop_);
+  DCHECK(!IsRunning());
+  DCHECK(!stopping_) << "Starting a non-joinable thread a second time? That's "
+                     << "not allowed!";
+#if defined(OS_WIN)
+  DCHECK((com_status_ != STA) ||
+      (options.message_loop_type == MessageLoop::TYPE_UI));
+#endif
+
+  // Reset |id_| here to support restarting the thread.
+  id_event_.Reset();
+  id_ = kInvalidThreadId;
+
+  SetThreadWasQuitProperly(false);
+
+  MessageLoop::Type type = options.message_loop_type;
+  if (!options.message_pump_factory.is_null())
+    type = MessageLoop::TYPE_CUSTOM;
+
+  message_loop_timer_slack_ = options.timer_slack;
+  std::unique_ptr<MessageLoop> message_loop_owned =
+      MessageLoop::CreateUnbound(type, options.message_pump_factory);
+  message_loop_ = message_loop_owned.get();
+  start_event_.Reset();
+
+  // Hold |thread_lock_| while starting the new thread to synchronize with
+  // Stop() while it's not guaranteed to be sequenced (until crbug/629139 is
+  // fixed).
+  {
+    AutoLock lock(thread_lock_);
+    bool success =
+        options.joinable
+            ? PlatformThread::CreateWithPriority(options.stack_size, this,
+                                                 &thread_, options.priority)
+            : PlatformThread::CreateNonJoinableWithPriority(
+                  options.stack_size, this, options.priority);
+    if (!success) {
+      DLOG(ERROR) << "failed to create thread";
+      message_loop_ = nullptr;
+      return false;
+    }
+  }
+
+  joinable_ = options.joinable;
+
+  // The ownership of |message_loop_| is managed by the newly created thread
+  // within the ThreadMain.
+  ignore_result(message_loop_owned.release());
+
+  DCHECK(message_loop_);
+  return true;
+}
+
+bool Thread::StartAndWaitForTesting() {
+  DCHECK(owning_sequence_checker_.CalledOnValidSequence());
+  bool result = Start();
+  if (!result)
+    return false;
+  WaitUntilThreadStarted();
+  return true;
+}
+
+bool Thread::WaitUntilThreadStarted() const {
+  DCHECK(owning_sequence_checker_.CalledOnValidSequence());
+  if (!message_loop_)
+    return false;
+  base::ThreadRestrictions::ScopedAllowWait allow_wait;
+  start_event_.Wait();
+  return true;
+}
+
+void Thread::FlushForTesting() {
+  DCHECK(owning_sequence_checker_.CalledOnValidSequence());
+  if (!message_loop_)
+    return;
+
+  WaitableEvent done(WaitableEvent::ResetPolicy::AUTOMATIC,
+                     WaitableEvent::InitialState::NOT_SIGNALED);
+  task_runner()->PostTask(FROM_HERE,
+                          BindOnce(&WaitableEvent::Signal, Unretained(&done)));
+  done.Wait();
+}
+
+void Thread::Stop() {
+  DCHECK(joinable_);
+
+  // TODO(gab): Fix improper usage of this API (http://crbug.com/629139) and
+  // enable this check, until then synchronization with Start() via
+  // |thread_lock_| is required...
+  // DCHECK(owning_sequence_checker_.CalledOnValidSequence());
+  AutoLock lock(thread_lock_);
+
+  StopSoon();
+
+  // Can't join if the |thread_| is either already gone or is non-joinable.
+  if (thread_.is_null())
+    return;
+
+  // Wait for the thread to exit.
+  //
+  // TODO(darin): Unfortunately, we need to keep |message_loop_| around until
+  // the thread exits.  Some consumers are abusing the API.  Make them stop.
+  //
+  PlatformThread::Join(thread_);
+  thread_ = base::PlatformThreadHandle();
+
+  // The thread should nullify |message_loop_| on exit (note: Join() adds an
+  // implicit memory barrier and no lock is thus required for this check).
+  DCHECK(!message_loop_);
+
+  stopping_ = false;
+}
+
+void Thread::StopSoon() {
+  // TODO(gab): Fix improper usage of this API (http://crbug.com/629139) and
+  // enable this check.
+  // DCHECK(owning_sequence_checker_.CalledOnValidSequence());
+
+  if (stopping_ || !message_loop_)
+    return;
+
+  stopping_ = true;
+
+  if (using_external_message_loop_) {
+    // Setting |stopping_| to true above should have been sufficient for this
+    // thread to be considered "stopped" per it having never set its |running_|
+    // bit by lack of its own ThreadMain.
+    DCHECK(!IsRunning());
+    message_loop_ = nullptr;
+    return;
+  }
+
+  task_runner()->PostTask(
+      FROM_HERE, base::BindOnce(&Thread::ThreadQuitHelper, Unretained(this)));
+}
+
+void Thread::DetachFromSequence() {
+  DCHECK(owning_sequence_checker_.CalledOnValidSequence());
+  owning_sequence_checker_.DetachFromSequence();
+}
+
+PlatformThreadId Thread::GetThreadId() const {
+  // If the thread is created but not started yet, wait for |id_| being ready.
+  base::ThreadRestrictions::ScopedAllowWait allow_wait;
+  id_event_.Wait();
+  return id_;
+}
+
+PlatformThreadHandle Thread::GetThreadHandle() const {
+  AutoLock lock(thread_lock_);
+  return thread_;
+}
+
+bool Thread::IsRunning() const {
+  // TODO(gab): Fix improper usage of this API (http://crbug.com/629139) and
+  // enable this check.
+  // DCHECK(owning_sequence_checker_.CalledOnValidSequence());
+
+  // If the thread's already started (i.e. |message_loop_| is non-null) and not
+  // yet requested to stop (i.e. |stopping_| is false) we can just return true.
+  // (Note that |stopping_| is touched only on the same sequence that starts /
+  // started the new thread so we need no locking here.)
+  if (message_loop_ && !stopping_)
+    return true;
+  // Otherwise check the |running_| flag, which is set to true by the new thread
+  // only while it is inside Run().
+  AutoLock lock(running_lock_);
+  return running_;
+}
+
+void Thread::Run(RunLoop* run_loop) {
+  // Overridable protected method to be called from our |thread_| only.
+  DCHECK(id_event_.IsSignaled());
+  DCHECK_EQ(id_, PlatformThread::CurrentId());
+
+  run_loop->Run();
+}
+
+// static
+void Thread::SetThreadWasQuitProperly(bool flag) {
+  lazy_tls_bool.Pointer()->Set(flag);
+}
+
+// static
+bool Thread::GetThreadWasQuitProperly() {
+  bool quit_properly = true;
+#ifndef NDEBUG
+  quit_properly = lazy_tls_bool.Pointer()->Get();
+#endif
+  return quit_properly;
+}
+
+void Thread::SetMessageLoop(MessageLoop* message_loop) {
+  DCHECK(owning_sequence_checker_.CalledOnValidSequence());
+  DCHECK(message_loop);
+
+  // Setting |message_loop_| should suffice for this thread to be considered
+  // as "running", until Stop() is invoked.
+  DCHECK(!IsRunning());
+  message_loop_ = message_loop;
+  DCHECK(IsRunning());
+
+  using_external_message_loop_ = true;
+}
+
+void Thread::ThreadMain() {
+  // First, make GetThreadId() available to avoid deadlocks. It could be called
+  // any place in the following thread initialization code.
+  DCHECK(!id_event_.IsSignaled());
+  // Note: this read of |id_| while |id_event_| isn't signaled is exceptionally
+  // okay because ThreadMain has a happens-after relationship with the other
+  // write in StartWithOptions().
+  DCHECK_EQ(kInvalidThreadId, id_);
+  id_ = PlatformThread::CurrentId();
+  DCHECK_NE(kInvalidThreadId, id_);
+  id_event_.Signal();
+
+  // Complete the initialization of our Thread object.
+  PlatformThread::SetName(name_.c_str());
+  ANNOTATE_THREAD_NAME(name_.c_str());  // Tell the name to race detector.
+
+  // Lazily initialize the |message_loop| so that it can run on this thread.
+  DCHECK(message_loop_);
+  std::unique_ptr<MessageLoop> message_loop(message_loop_);
+  message_loop_->BindToCurrentThread();
+  message_loop_->SetTimerSlack(message_loop_timer_slack_);
+
+#if defined(OS_POSIX) && !defined(OS_NACL)
+  // Allow threads running a MessageLoopForIO to use FileDescriptorWatcher API.
+  std::unique_ptr<FileDescriptorWatcher> file_descriptor_watcher;
+  if (MessageLoopForIO::IsCurrent()) {
+    file_descriptor_watcher.reset(new FileDescriptorWatcher(
+        static_cast<MessageLoopForIO*>(message_loop_)));
+  }
+#endif
+
+#if defined(OS_WIN)
+  std::unique_ptr<win::ScopedCOMInitializer> com_initializer;
+  if (com_status_ != NONE) {
+    com_initializer.reset((com_status_ == STA) ?
+        new win::ScopedCOMInitializer() :
+        new win::ScopedCOMInitializer(win::ScopedCOMInitializer::kMTA));
+  }
+#endif
+
+  // Let the thread do extra initialization.
+  Init();
+
+  {
+    AutoLock lock(running_lock_);
+    running_ = true;
+  }
+
+  start_event_.Signal();
+
+  RunLoop run_loop;
+  run_loop_ = &run_loop;
+  Run(run_loop_);
+
+  {
+    AutoLock lock(running_lock_);
+    running_ = false;
+  }
+
+  // Let the thread do extra cleanup.
+  CleanUp();
+
+#if defined(OS_WIN)
+  com_initializer.reset();
+#endif
+
+  if (message_loop->type() != MessageLoop::TYPE_CUSTOM) {
+    // Assert that RunLoop::QuitWhenIdle was called by ThreadQuitHelper. Don't
+    // check for custom message pumps, because their shutdown might not allow
+    // this.
+    DCHECK(GetThreadWasQuitProperly());
+  }
+
+  // We can't receive messages anymore.
+  // (The message loop is destructed at the end of this block)
+  message_loop_ = nullptr;
+  run_loop_ = nullptr;
+}
+
+void Thread::ThreadQuitHelper() {
+  DCHECK(run_loop_);
+  run_loop_->QuitWhenIdle();
+  SetThreadWasQuitProperly(true);
+}
+
+}  // namespace base
diff --git a/base/threading/thread.h b/base/threading/thread.h
new file mode 100644
index 0000000..9fbdcb8
--- /dev/null
+++ b/base/threading/thread.h
@@ -0,0 +1,356 @@
+// 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.
+
+#ifndef BASE_THREADING_THREAD_H_
+#define BASE_THREADING_THREAD_H_
+
+#include <stddef.h>
+
+#include <memory>
+#include <string>
+
+#include "base/base_export.h"
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/message_loop/message_loop.h"
+#include "base/message_loop/timer_slack.h"
+#include "base/sequence_checker.h"
+#include "base/single_thread_task_runner.h"
+#include "base/synchronization/atomic_flag.h"
+#include "base/synchronization/lock.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/threading/platform_thread.h"
+#include "build/build_config.h"
+
+namespace base {
+
+class MessagePump;
+class RunLoop;
+
+// IMPORTANT: Instead of creating a base::Thread, consider using
+// base::Create(Sequenced|SingleThread)TaskRunnerWithTraits().
+//
+// A simple thread abstraction that establishes a MessageLoop on a new thread.
+// The consumer uses the MessageLoop of the thread to cause code to execute on
+// the thread.  When this object is destroyed the thread is terminated.  All
+// pending tasks queued on the thread's message loop will run to completion
+// before the thread is terminated.
+//
+// WARNING! SUBCLASSES MUST CALL Stop() IN THEIR DESTRUCTORS!  See ~Thread().
+//
+// After the thread is stopped, the destruction sequence is:
+//
+//  (1) Thread::CleanUp()
+//  (2) MessageLoop::~MessageLoop
+//  (3.b) MessageLoopCurrent::DestructionObserver::WillDestroyCurrentMessageLoop
+//
+// This API is not thread-safe: unless indicated otherwise its methods are only
+// valid from the owning sequence (which is the one from which Start() is
+// invoked -- should it differ from the one on which it was constructed).
+//
+// Sometimes it's useful to kick things off on the initial sequence (e.g.
+// construction, Start(), task_runner()), but to then hand the Thread over to a
+// pool of users for the last one of them to destroy it when done. For that use
+// case, Thread::DetachFromSequence() allows the owning sequence to give up
+// ownership. The caller is then responsible to ensure a happens-after
+// relationship between the DetachFromSequence() call and the next use of that
+// Thread object (including ~Thread()).
+class BASE_EXPORT Thread : PlatformThread::Delegate {
+ public:
+  struct BASE_EXPORT Options {
+    typedef Callback<std::unique_ptr<MessagePump>()> MessagePumpFactory;
+
+    Options();
+    Options(MessageLoop::Type type, size_t size);
+    Options(const Options& other);
+    ~Options();
+
+    // Specifies the type of message loop that will be allocated on the thread.
+    // This is ignored if message_pump_factory.is_null() is false.
+    MessageLoop::Type message_loop_type = MessageLoop::TYPE_DEFAULT;
+
+    // Specifies timer slack for thread message loop.
+    TimerSlack timer_slack = TIMER_SLACK_NONE;
+
+    // Used to create the MessagePump for the MessageLoop. The callback is Run()
+    // on the thread. If message_pump_factory.is_null(), then a MessagePump
+    // appropriate for |message_loop_type| is created. Setting this forces the
+    // MessageLoop::Type to TYPE_CUSTOM.
+    MessagePumpFactory message_pump_factory;
+
+    // Specifies the maximum stack size that the thread is allowed to use.
+    // This does not necessarily correspond to the thread's initial stack size.
+    // A value of 0 indicates that the default maximum should be used.
+    size_t stack_size = 0;
+
+    // Specifies the initial thread priority.
+    ThreadPriority priority = ThreadPriority::NORMAL;
+
+    // If false, the thread will not be joined on destruction. This is intended
+    // for threads that want TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN
+    // semantics. Non-joinable threads can't be joined (must be leaked and
+    // can't be destroyed or Stop()'ed).
+    // TODO(gab): allow non-joinable instances to be deleted without causing
+    // user-after-frees (proposal @ https://crbug.com/629139#c14)
+    bool joinable = true;
+  };
+
+  // Constructor.
+  // name is a display string to identify the thread.
+  explicit Thread(const std::string& name);
+
+  // Destroys the thread, stopping it if necessary.
+  //
+  // NOTE: ALL SUBCLASSES OF Thread MUST CALL Stop() IN THEIR DESTRUCTORS (or
+  // guarantee Stop() is explicitly called before the subclass is destroyed).
+  // This is required to avoid a data race between the destructor modifying the
+  // vtable, and the thread's ThreadMain calling the virtual method Run().  It
+  // also ensures that the CleanUp() virtual method is called on the subclass
+  // before it is destructed.
+  ~Thread() override;
+
+#if defined(OS_WIN)
+  // Causes the thread to initialize COM.  This must be called before calling
+  // Start() or StartWithOptions().  If |use_mta| is false, the thread is also
+  // started with a TYPE_UI message loop.  It is an error to call
+  // init_com_with_mta(false) and then StartWithOptions() with any message loop
+  // type other than TYPE_UI.
+  void init_com_with_mta(bool use_mta) {
+    DCHECK(!message_loop_);
+    com_status_ = use_mta ? MTA : STA;
+  }
+#endif
+
+  // Starts the thread.  Returns true if the thread was successfully started;
+  // otherwise, returns false.  Upon successful return, the message_loop()
+  // getter will return non-null.
+  //
+  // Note: This function can't be called on Windows with the loader lock held;
+  // i.e. during a DllMain, global object construction or destruction, atexit()
+  // callback.
+  bool Start();
+
+  // Starts the thread. Behaves exactly like Start in addition to allow to
+  // override the default options.
+  //
+  // Note: This function can't be called on Windows with the loader lock held;
+  // i.e. during a DllMain, global object construction or destruction, atexit()
+  // callback.
+  bool StartWithOptions(const Options& options);
+
+  // Starts the thread and wait for the thread to start and run initialization
+  // before returning. It's same as calling Start() and then
+  // WaitUntilThreadStarted().
+  // Note that using this (instead of Start() or StartWithOptions() causes
+  // jank on the calling thread, should be used only in testing code.
+  bool StartAndWaitForTesting();
+
+  // Blocks until the thread starts running. Called within StartAndWait().
+  // Note that calling this causes jank on the calling thread, must be used
+  // carefully for production code.
+  bool WaitUntilThreadStarted() const;
+
+  // Blocks until all tasks previously posted to this thread have been executed.
+  void FlushForTesting();
+
+  // Signals the thread to exit and returns once the thread has exited. The
+  // Thread object is completely reset and may be used as if it were newly
+  // constructed (i.e., Start may be called again). Can only be called if
+  // |joinable_|.
+  //
+  // Stop may be called multiple times and is simply ignored if the thread is
+  // already stopped or currently stopping.
+  //
+  // Start/Stop are not thread-safe and callers that desire to invoke them from
+  // different threads must ensure mutual exclusion.
+  //
+  // NOTE: If you are a consumer of Thread, it is not necessary to call this
+  // before deleting your Thread objects, as the destructor will do it.
+  // IF YOU ARE A SUBCLASS OF Thread, YOU MUST CALL THIS IN YOUR DESTRUCTOR.
+  void Stop();
+
+  // Signals the thread to exit in the near future.
+  //
+  // WARNING: This function is not meant to be commonly used. Use at your own
+  // risk. Calling this function will cause message_loop() to become invalid in
+  // the near future. This function was created to workaround a specific
+  // deadlock on Windows with printer worker thread. In any other case, Stop()
+  // should be used.
+  //
+  // Call Stop() to reset the thread object once it is known that the thread has
+  // quit.
+  void StopSoon();
+
+  // Detaches the owning sequence, indicating that the next call to this API
+  // (including ~Thread()) can happen from a different sequence (to which it
+  // will be rebound). This call itself must happen on the current owning
+  // sequence and the caller must ensure the next API call has a happens-after
+  // relationship with this one.
+  void DetachFromSequence();
+
+  // Returns the message loop for this thread.  Use the MessageLoop's
+  // PostTask methods to execute code on the thread.  This only returns
+  // non-null after a successful call to Start.  After Stop has been called,
+  // this will return nullptr.
+  //
+  // NOTE: You must not call this MessageLoop's Quit method directly.  Use
+  // the Thread's Stop method instead.
+  //
+  // In addition to this Thread's owning sequence, this can also safely be
+  // called from the underlying thread itself.
+  MessageLoop* message_loop() const {
+    // This class doesn't provide synchronization around |message_loop_| and as
+    // such only the owner should access it (and the underlying thread which
+    // never sees it before it's set). In practice, many callers are coming from
+    // unrelated threads but provide their own implicit (e.g. memory barriers
+    // from task posting) or explicit (e.g. locks) synchronization making the
+    // access of |message_loop_| safe... Changing all of those callers is
+    // unfeasible; instead verify that they can reliably see
+    // |message_loop_ != nullptr| without synchronization as a proof that their
+    // external synchronization catches the unsynchronized effects of Start().
+    // TODO(gab): Despite all of the above this test has to be disabled for now
+    // per crbug.com/629139#c6.
+    // DCHECK(owning_sequence_checker_.CalledOnValidSequence() ||
+    //        (id_event_.IsSignaled() && id_ == PlatformThread::CurrentId()) ||
+    //        message_loop_);
+    return message_loop_;
+  }
+
+  // Returns a TaskRunner for this thread. Use the TaskRunner's PostTask
+  // methods to execute code on the thread. Returns nullptr if the thread is not
+  // running (e.g. before Start or after Stop have been called). Callers can
+  // hold on to this even after the thread is gone; in this situation, attempts
+  // to PostTask() will fail.
+  //
+  // In addition to this Thread's owning sequence, this can also safely be
+  // called from the underlying thread itself.
+  scoped_refptr<SingleThreadTaskRunner> task_runner() const {
+    // Refer to the DCHECK and comment inside |message_loop()|.
+    DCHECK(owning_sequence_checker_.CalledOnValidSequence() ||
+           (id_event_.IsSignaled() && id_ == PlatformThread::CurrentId()) ||
+           message_loop_);
+    return message_loop_ ? message_loop_->task_runner() : nullptr;
+  }
+
+  // Returns the name of this thread (for display in debugger too).
+  const std::string& thread_name() const { return name_; }
+
+  // Returns the thread ID.  Should not be called before the first Start*()
+  // call.  Keeps on returning the same ID even after a Stop() call. The next
+  // Start*() call renews the ID.
+  //
+  // WARNING: This function will block if the thread hasn't started yet.
+  //
+  // This method is thread-safe.
+  PlatformThreadId GetThreadId() const;
+
+  // Returns the current thread handle. If called before Start*() returns or
+  // after Stop() returns, an empty thread handle will be returned.
+  //
+  // This method is thread-safe.
+  //
+  // TODO(robliao): Remove this when it no longer needs to be temporarily
+  // exposed for http://crbug.com/717380.
+  PlatformThreadHandle GetThreadHandle() const;
+
+  // Returns true if the thread has been started, and not yet stopped.
+  bool IsRunning() const;
+
+ protected:
+  // Called just prior to starting the message loop
+  virtual void Init() {}
+
+  // Called to start the run loop
+  virtual void Run(RunLoop* run_loop);
+
+  // Called just after the message loop ends
+  virtual void CleanUp() {}
+
+  static void SetThreadWasQuitProperly(bool flag);
+  static bool GetThreadWasQuitProperly();
+
+  // Bind this Thread to an existing MessageLoop instead of starting a new one.
+  // TODO(gab): Remove this after ios/ has undergone the same surgery as
+  // BrowserThreadImpl (ref.
+  // https://chromium-review.googlesource.com/c/chromium/src/+/969104).
+  void SetMessageLoop(MessageLoop* message_loop);
+
+  bool using_external_message_loop() const {
+    return using_external_message_loop_;
+  }
+
+ private:
+#if defined(OS_WIN)
+  enum ComStatus {
+    NONE,
+    STA,
+    MTA,
+  };
+#endif
+
+  // PlatformThread::Delegate methods:
+  void ThreadMain() override;
+
+  void ThreadQuitHelper();
+
+#if defined(OS_WIN)
+  // Whether this thread needs to initialize COM, and if so, in what mode.
+  ComStatus com_status_ = NONE;
+#endif
+
+  // Mirrors the Options::joinable field used to start this thread. Verified
+  // on Stop() -- non-joinable threads can't be joined (must be leaked).
+  bool joinable_ = true;
+
+  // If true, we're in the middle of stopping, and shouldn't access
+  // |message_loop_|. It may non-nullptr and invalid.
+  // Should be written on the thread that created this thread. Also read data
+  // could be wrong on other threads.
+  bool stopping_ = false;
+
+  // True while inside of Run().
+  bool running_ = false;
+  mutable base::Lock running_lock_;  // Protects |running_|.
+
+  // The thread's handle.
+  PlatformThreadHandle thread_;
+  mutable base::Lock thread_lock_;  // Protects |thread_|.
+
+  // The thread's id once it has started.
+  PlatformThreadId id_ = kInvalidThreadId;
+  // Protects |id_| which must only be read while it's signaled.
+  mutable WaitableEvent id_event_;
+
+  // The thread's MessageLoop and RunLoop. Valid only while the thread is alive.
+  // Set by the created thread.
+  MessageLoop* message_loop_ = nullptr;
+  RunLoop* run_loop_ = nullptr;
+
+  // True only if |message_loop_| was externally provided by |SetMessageLoop()|
+  // in which case this Thread has no underlying |thread_| and should merely
+  // drop |message_loop_| on Stop(). In that event, this remains true after
+  // Stop() was invoked so that subclasses can use this state to build their own
+  // cleanup logic as required.
+  bool using_external_message_loop_ = false;
+
+  // Stores Options::timer_slack_ until the message loop has been bound to
+  // a thread.
+  TimerSlack message_loop_timer_slack_ = TIMER_SLACK_NONE;
+
+  // The name of the thread.  Used for debugging purposes.
+  const std::string name_;
+
+  // Signaled when the created thread gets ready to use the message loop.
+  mutable WaitableEvent start_event_;
+
+  // This class is not thread-safe, use this to verify access from the owning
+  // sequence of the Thread.
+  SequenceChecker owning_sequence_checker_;
+
+  DISALLOW_COPY_AND_ASSIGN(Thread);
+};
+
+}  // namespace base
+
+#endif  // BASE_THREADING_THREAD_H_
diff --git a/base/threading/thread_checker.h b/base/threading/thread_checker.h
new file mode 100644
index 0000000..6799e25
--- /dev/null
+++ b/base/threading/thread_checker.h
@@ -0,0 +1,103 @@
+// 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.
+
+#ifndef BASE_THREADING_THREAD_CHECKER_H_
+#define BASE_THREADING_THREAD_CHECKER_H_
+
+#include "base/compiler_specific.h"
+#include "base/logging.h"
+#include "base/threading/thread_checker_impl.h"
+
+// ThreadChecker is a helper class used to help verify that some methods of a
+// class are called from the same thread (for thread-affinity).
+//
+// Use the macros below instead of the ThreadChecker directly so that the unused
+// member doesn't result in an extra byte (four when padded) per instance in
+// production.
+//
+// Usage of this class should be *rare* as most classes require thread-safety
+// but not thread-affinity. Prefer base::SequenceChecker to verify thread-safe
+// access.
+//
+// Thread-affinity checks should only be required in classes that use thread-
+// local-storage or a third-party API that does.
+//
+// Prefer to encode the minimum requirements of each class instead of the
+// environment it happens to run in today. e.g. if a class requires thread-
+// safety but not thread-affinity, use a SequenceChecker even if it happens to
+// run on a SingleThreadTaskRunner today. That makes it easier to understand
+// what would need to change to turn that SingleThreadTaskRunner into a
+// SequencedTaskRunner for ease of scheduling as well as minimizes side-effects
+// if that change is made.
+//
+// Usage:
+//   class MyClass {
+//    public:
+//     MyClass() {
+//       // It's sometimes useful to detach on construction for objects that are
+//       // constructed in one place and forever after used from another
+//       // thread.
+//       DETACH_FROM_THREAD(my_thread_checker_);
+//     }
+//
+//     ~MyClass() {
+//       // ThreadChecker doesn't automatically check it's destroyed on origin
+//       // thread for the same reason it's sometimes detached in the
+//       // constructor. It's okay to destroy off thread if the owner otherwise
+//       // knows usage on the associated thread is done. If you're not
+//       // detaching in the constructor, you probably want to explicitly check
+//       // in the destructor.
+//       DCHECK_CALLED_ON_VALID_THREAD(my_thread_checker_);
+//     }
+//
+//     void MyMethod() {
+//       DCHECK_CALLED_ON_VALID_THREAD(my_thread_checker_);
+//       ... (do stuff) ...
+//     }
+//
+//    private:
+//     THREAD_CHECKER(my_thread_checker_);
+//   }
+
+#if DCHECK_IS_ON()
+#define THREAD_CHECKER(name) base::ThreadChecker name
+#define DCHECK_CALLED_ON_VALID_THREAD(name) DCHECK((name).CalledOnValidThread())
+#define DETACH_FROM_THREAD(name) (name).DetachFromThread()
+#else  // DCHECK_IS_ON()
+#define THREAD_CHECKER(name)
+#define DCHECK_CALLED_ON_VALID_THREAD(name) EAT_STREAM_PARAMETERS
+#define DETACH_FROM_THREAD(name)
+#endif  // DCHECK_IS_ON()
+
+namespace base {
+
+// Do nothing implementation, for use in release mode.
+//
+// Note: You should almost always use the ThreadChecker class (through the above
+// macros) to get the right version for your build configuration.
+class ThreadCheckerDoNothing {
+ public:
+  ThreadCheckerDoNothing() = default;
+  bool CalledOnValidThread() const WARN_UNUSED_RESULT { return true; }
+  void DetachFromThread() {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ThreadCheckerDoNothing);
+};
+
+// Note that ThreadCheckerImpl::CalledOnValidThread() returns false when called
+// from tasks posted to SingleThreadTaskRunners bound to different sequences,
+// even if the tasks happen to run on the same thread (e.g. two independent
+// SingleThreadTaskRunners on the TaskScheduler that happen to share a thread).
+#if DCHECK_IS_ON()
+class ThreadChecker : public ThreadCheckerImpl {
+};
+#else
+class ThreadChecker : public ThreadCheckerDoNothing {
+};
+#endif  // DCHECK_IS_ON()
+
+}  // namespace base
+
+#endif  // BASE_THREADING_THREAD_CHECKER_H_
diff --git a/base/threading/thread_checker_impl.cc b/base/threading/thread_checker_impl.cc
new file mode 100644
index 0000000..d5ccbdb
--- /dev/null
+++ b/base/threading/thread_checker_impl.cc
@@ -0,0 +1,57 @@
+// Copyright (c) 2011 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 "base/threading/thread_checker_impl.h"
+
+#include "base/threading/thread_task_runner_handle.h"
+
+namespace base {
+
+ThreadCheckerImpl::ThreadCheckerImpl() {
+  AutoLock auto_lock(lock_);
+  EnsureAssigned();
+}
+
+ThreadCheckerImpl::~ThreadCheckerImpl() = default;
+
+bool ThreadCheckerImpl::CalledOnValidThread() const {
+  AutoLock auto_lock(lock_);
+  EnsureAssigned();
+
+  // Always return true when called from the task from which this
+  // ThreadCheckerImpl was assigned to a thread.
+  if (task_token_ == TaskToken::GetForCurrentThread())
+    return true;
+
+  // If this ThreadCheckerImpl is bound to a valid SequenceToken, it must be
+  // equal to the current SequenceToken and there must be a registered
+  // ThreadTaskRunnerHandle. Otherwise, the fact that the current task runs on
+  // the thread to which this ThreadCheckerImpl is bound is fortuitous.
+  if (sequence_token_.IsValid() &&
+      (sequence_token_ != SequenceToken::GetForCurrentThread() ||
+       !ThreadTaskRunnerHandle::IsSet())) {
+    return false;
+  }
+
+  return thread_id_ == PlatformThread::CurrentRef();
+}
+
+void ThreadCheckerImpl::DetachFromThread() {
+  AutoLock auto_lock(lock_);
+  thread_id_ = PlatformThreadRef();
+  task_token_ = TaskToken();
+  sequence_token_ = SequenceToken();
+}
+
+void ThreadCheckerImpl::EnsureAssigned() const {
+  lock_.AssertAcquired();
+  if (!thread_id_.is_null())
+    return;
+
+  thread_id_ = PlatformThread::CurrentRef();
+  task_token_ = TaskToken::GetForCurrentThread();
+  sequence_token_ = SequenceToken::GetForCurrentThread();
+}
+
+}  // namespace base
diff --git a/base/threading/thread_checker_impl.h b/base/threading/thread_checker_impl.h
new file mode 100644
index 0000000..103dfe7
--- /dev/null
+++ b/base/threading/thread_checker_impl.h
@@ -0,0 +1,62 @@
+// Copyright (c) 2011 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.
+
+#ifndef BASE_THREADING_THREAD_CHECKER_IMPL_H_
+#define BASE_THREADING_THREAD_CHECKER_IMPL_H_
+
+#include "base/base_export.h"
+#include "base/compiler_specific.h"
+#include "base/sequence_token.h"
+#include "base/synchronization/lock.h"
+#include "base/threading/platform_thread.h"
+
+namespace base {
+
+// Real implementation of ThreadChecker, for use in debug mode, or for temporary
+// use in release mode (e.g. to CHECK on a threading issue seen only in the
+// wild).
+//
+// Note: You should almost always use the ThreadChecker class to get the right
+// version for your build configuration.
+class BASE_EXPORT ThreadCheckerImpl {
+ public:
+  ThreadCheckerImpl();
+  ~ThreadCheckerImpl();
+
+  bool CalledOnValidThread() const WARN_UNUSED_RESULT;
+
+  // Changes the thread that is checked for in CalledOnValidThread.  This may
+  // be useful when an object may be created on one thread and then used
+  // exclusively on another thread.
+  void DetachFromThread();
+
+ private:
+  void EnsureAssigned() const;
+
+  // Members are mutable so that CalledOnValidThread() can set them.
+
+  // Synchronizes access to all members.
+  mutable base::Lock lock_;
+
+  // Thread on which CalledOnValidThread() may return true.
+  mutable PlatformThreadRef thread_id_;
+
+  // TaskToken for which CalledOnValidThread() always returns true. This allows
+  // CalledOnValidThread() to return true when called multiple times from the
+  // same task, even if it's not running in a single-threaded context itself
+  // (allowing usage of ThreadChecker objects on the stack in the scope of one-
+  // off tasks). Note: CalledOnValidThread() may return true even if the current
+  // TaskToken is not equal to this.
+  mutable TaskToken task_token_;
+
+  // SequenceToken for which CalledOnValidThread() may return true. Used to
+  // ensure that CalledOnValidThread() doesn't return true for TaskScheduler
+  // tasks that happen to run on the same thread but weren't posted to the same
+  // SingleThreadTaskRunner.
+  mutable SequenceToken sequence_token_;
+};
+
+}  // namespace base
+
+#endif  // BASE_THREADING_THREAD_CHECKER_IMPL_H_
diff --git a/base/threading/thread_checker_unittest.cc b/base/threading/thread_checker_unittest.cc
new file mode 100644
index 0000000..5fbbc52
--- /dev/null
+++ b/base/threading/thread_checker_unittest.cc
@@ -0,0 +1,245 @@
+// 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 "base/threading/thread_checker.h"
+
+#include <memory>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/sequence_token.h"
+#include "base/test/gtest_util.h"
+#include "base/test/test_simple_task_runner.h"
+#include "base/threading/simple_thread.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+namespace {
+
+// A thread that runs a callback.
+class RunCallbackThread : public SimpleThread {
+ public:
+  explicit RunCallbackThread(const Closure& callback)
+      : SimpleThread("RunCallbackThread"), callback_(callback) {}
+
+ private:
+  // SimpleThread:
+  void Run() override { callback_.Run(); }
+
+  const Closure callback_;
+
+  DISALLOW_COPY_AND_ASSIGN(RunCallbackThread);
+};
+
+// Runs a callback on a new thread synchronously.
+void RunCallbackOnNewThreadSynchronously(const Closure& callback) {
+  RunCallbackThread run_callback_thread(callback);
+  run_callback_thread.Start();
+  run_callback_thread.Join();
+}
+
+void ExpectCalledOnValidThread(ThreadCheckerImpl* thread_checker) {
+  ASSERT_TRUE(thread_checker);
+
+  // This should bind |thread_checker| to the current thread if it wasn't
+  // already bound to a thread.
+  EXPECT_TRUE(thread_checker->CalledOnValidThread());
+
+  // Since |thread_checker| is now bound to the current thread, another call to
+  // CalledOnValidThread() should return true.
+  EXPECT_TRUE(thread_checker->CalledOnValidThread());
+}
+
+void ExpectNotCalledOnValidThread(ThreadCheckerImpl* thread_checker) {
+  ASSERT_TRUE(thread_checker);
+  EXPECT_FALSE(thread_checker->CalledOnValidThread());
+}
+
+void ExpectNotCalledOnValidThreadWithSequenceTokenAndThreadTaskRunnerHandle(
+    ThreadCheckerImpl* thread_checker,
+    SequenceToken sequence_token) {
+  ThreadTaskRunnerHandle thread_task_runner_handle(
+      MakeRefCounted<TestSimpleTaskRunner>());
+  ScopedSetSequenceTokenForCurrentThread
+      scoped_set_sequence_token_for_current_thread(sequence_token);
+  ExpectNotCalledOnValidThread(thread_checker);
+}
+
+}  // namespace
+
+TEST(ThreadCheckerTest, AllowedSameThreadNoSequenceToken) {
+  ThreadCheckerImpl thread_checker;
+  EXPECT_TRUE(thread_checker.CalledOnValidThread());
+}
+
+TEST(ThreadCheckerTest,
+     AllowedSameThreadAndSequenceDifferentTasksWithThreadTaskRunnerHandle) {
+  ThreadTaskRunnerHandle thread_task_runner_handle(
+      MakeRefCounted<TestSimpleTaskRunner>());
+
+  std::unique_ptr<ThreadCheckerImpl> thread_checker;
+  const SequenceToken sequence_token = SequenceToken::Create();
+
+  {
+    ScopedSetSequenceTokenForCurrentThread
+        scoped_set_sequence_token_for_current_thread(sequence_token);
+    thread_checker.reset(new ThreadCheckerImpl);
+  }
+
+  {
+    ScopedSetSequenceTokenForCurrentThread
+        scoped_set_sequence_token_for_current_thread(sequence_token);
+    EXPECT_TRUE(thread_checker->CalledOnValidThread());
+  }
+}
+
+TEST(ThreadCheckerTest,
+     AllowedSameThreadSequenceAndTaskNoThreadTaskRunnerHandle) {
+  ScopedSetSequenceTokenForCurrentThread
+      scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
+  ThreadCheckerImpl thread_checker;
+  EXPECT_TRUE(thread_checker.CalledOnValidThread());
+}
+
+TEST(ThreadCheckerTest,
+     DisallowedSameThreadAndSequenceDifferentTasksNoThreadTaskRunnerHandle) {
+  std::unique_ptr<ThreadCheckerImpl> thread_checker;
+
+  {
+    ScopedSetSequenceTokenForCurrentThread
+        scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
+    thread_checker.reset(new ThreadCheckerImpl);
+  }
+
+  {
+    ScopedSetSequenceTokenForCurrentThread
+        scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
+    EXPECT_FALSE(thread_checker->CalledOnValidThread());
+  }
+}
+
+TEST(ThreadCheckerTest, DisallowedDifferentThreadsNoSequenceToken) {
+  ThreadCheckerImpl thread_checker;
+  RunCallbackOnNewThreadSynchronously(
+      Bind(&ExpectNotCalledOnValidThread, Unretained(&thread_checker)));
+}
+
+TEST(ThreadCheckerTest, DisallowedDifferentThreadsSameSequence) {
+  ThreadTaskRunnerHandle thread_task_runner_handle(
+      MakeRefCounted<TestSimpleTaskRunner>());
+  const SequenceToken sequence_token(SequenceToken::Create());
+
+  ScopedSetSequenceTokenForCurrentThread
+      scoped_set_sequence_token_for_current_thread(sequence_token);
+  ThreadCheckerImpl thread_checker;
+  EXPECT_TRUE(thread_checker.CalledOnValidThread());
+
+  RunCallbackOnNewThreadSynchronously(Bind(
+      &ExpectNotCalledOnValidThreadWithSequenceTokenAndThreadTaskRunnerHandle,
+      Unretained(&thread_checker), sequence_token));
+}
+
+TEST(ThreadCheckerTest, DisallowedSameThreadDifferentSequence) {
+  std::unique_ptr<ThreadCheckerImpl> thread_checker;
+
+  ThreadTaskRunnerHandle thread_task_runner_handle(
+      MakeRefCounted<TestSimpleTaskRunner>());
+
+  {
+    ScopedSetSequenceTokenForCurrentThread
+        scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
+    thread_checker.reset(new ThreadCheckerImpl);
+  }
+
+  {
+    // Different SequenceToken.
+    ScopedSetSequenceTokenForCurrentThread
+        scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
+    EXPECT_FALSE(thread_checker->CalledOnValidThread());
+  }
+
+  // No SequenceToken.
+  EXPECT_FALSE(thread_checker->CalledOnValidThread());
+}
+
+TEST(ThreadCheckerTest, DetachFromThread) {
+  ThreadCheckerImpl thread_checker;
+  thread_checker.DetachFromThread();
+
+  // Verify that CalledOnValidThread() returns true when called on a different
+  // thread after a call to DetachFromThread().
+  RunCallbackOnNewThreadSynchronously(
+      Bind(&ExpectCalledOnValidThread, Unretained(&thread_checker)));
+
+  EXPECT_FALSE(thread_checker.CalledOnValidThread());
+}
+
+TEST(ThreadCheckerTest, DetachFromThreadWithSequenceToken) {
+  ThreadTaskRunnerHandle thread_task_runner_handle(
+      MakeRefCounted<TestSimpleTaskRunner>());
+  ScopedSetSequenceTokenForCurrentThread
+      scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
+  ThreadCheckerImpl thread_checker;
+  thread_checker.DetachFromThread();
+
+  // Verify that CalledOnValidThread() returns true when called on a different
+  // thread after a call to DetachFromThread().
+  RunCallbackOnNewThreadSynchronously(
+      Bind(&ExpectCalledOnValidThread, Unretained(&thread_checker)));
+
+  EXPECT_FALSE(thread_checker.CalledOnValidThread());
+}
+
+namespace {
+
+// This fixture is a helper for unit testing the thread checker macros as it is
+// not possible to inline ExpectDeathOnOtherThread() and
+// ExpectNoDeathOnOtherThreadAfterDetach() as lambdas since binding
+// |Unretained(&my_sequence_checker)| wouldn't compile on non-dcheck builds
+// where it won't be defined.
+class ThreadCheckerMacroTest : public testing::Test {
+ public:
+  ThreadCheckerMacroTest() = default;
+
+  void ExpectDeathOnOtherThread() {
+#if DCHECK_IS_ON()
+    EXPECT_DCHECK_DEATH({ DCHECK_CALLED_ON_VALID_THREAD(my_thread_checker_); });
+#else
+    // Happily no-ops on non-dcheck builds.
+    DCHECK_CALLED_ON_VALID_THREAD(my_thread_checker_);
+#endif
+  }
+
+  void ExpectNoDeathOnOtherThreadAfterDetach() {
+    DCHECK_CALLED_ON_VALID_THREAD(my_thread_checker_);
+    DCHECK_CALLED_ON_VALID_THREAD(my_thread_checker_)
+        << "Make sure it compiles when DCHECK is off";
+  }
+
+ protected:
+  THREAD_CHECKER(my_thread_checker_);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ThreadCheckerMacroTest);
+};
+
+}  // namespace
+
+TEST_F(ThreadCheckerMacroTest, Macros) {
+  THREAD_CHECKER(my_thread_checker);
+
+  RunCallbackOnNewThreadSynchronously(Bind(
+      &ThreadCheckerMacroTest::ExpectDeathOnOtherThread, Unretained(this)));
+
+  DETACH_FROM_THREAD(my_thread_checker_);
+
+  RunCallbackOnNewThreadSynchronously(
+      Bind(&ThreadCheckerMacroTest::ExpectNoDeathOnOtherThreadAfterDetach,
+           Unretained(this)));
+}
+
+}  // namespace base
diff --git a/base/threading/thread_collision_warner.cc b/base/threading/thread_collision_warner.cc
new file mode 100644
index 0000000..547e11c
--- /dev/null
+++ b/base/threading/thread_collision_warner.cc
@@ -0,0 +1,64 @@
+// Copyright (c) 2010 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 "base/threading/thread_collision_warner.h"
+
+#include "base/logging.h"
+#include "base/threading/platform_thread.h"
+
+namespace base {
+
+void DCheckAsserter::warn() {
+  NOTREACHED() << "Thread Collision";
+}
+
+static subtle::Atomic32 CurrentThread() {
+  const PlatformThreadId current_thread_id = PlatformThread::CurrentId();
+  // We need to get the thread id into an atomic data type. This might be a
+  // truncating conversion, but any loss-of-information just increases the
+  // chance of a fault negative, not a false positive.
+  const subtle::Atomic32 atomic_thread_id =
+      static_cast<subtle::Atomic32>(current_thread_id);
+
+  return atomic_thread_id;
+}
+
+void ThreadCollisionWarner::EnterSelf() {
+  // If the active thread is 0 then I'll write the current thread ID
+  // if two or more threads arrive here only one will succeed to
+  // write on valid_thread_id_ the current thread ID.
+  subtle::Atomic32 current_thread_id = CurrentThread();
+
+  int previous_value = subtle::NoBarrier_CompareAndSwap(&valid_thread_id_,
+                                                        0,
+                                                        current_thread_id);
+  if (previous_value != 0 && previous_value != current_thread_id) {
+    // gotcha! a thread is trying to use the same class and that is
+    // not current thread.
+    asserter_->warn();
+  }
+
+  subtle::NoBarrier_AtomicIncrement(&counter_, 1);
+}
+
+void ThreadCollisionWarner::Enter() {
+  subtle::Atomic32 current_thread_id = CurrentThread();
+
+  if (subtle::NoBarrier_CompareAndSwap(&valid_thread_id_,
+                                       0,
+                                       current_thread_id) != 0) {
+    // gotcha! another thread is trying to use the same class.
+    asserter_->warn();
+  }
+
+  subtle::NoBarrier_AtomicIncrement(&counter_, 1);
+}
+
+void ThreadCollisionWarner::Leave() {
+  if (subtle::Barrier_AtomicIncrement(&counter_, -1) == 0) {
+    subtle::NoBarrier_Store(&valid_thread_id_, 0);
+  }
+}
+
+}  // namespace base
diff --git a/base/threading/thread_collision_warner.h b/base/threading/thread_collision_warner.h
new file mode 100644
index 0000000..b6993f6
--- /dev/null
+++ b/base/threading/thread_collision_warner.h
@@ -0,0 +1,245 @@
+// 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.
+
+#ifndef BASE_THREADING_THREAD_COLLISION_WARNER_H_
+#define BASE_THREADING_THREAD_COLLISION_WARNER_H_
+
+#include <memory>
+
+#include "base/atomicops.h"
+#include "base/base_export.h"
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+
+// A helper class alongside macros to be used to verify assumptions about thread
+// safety of a class.
+//
+// Example: Queue implementation non thread-safe but still usable if clients
+//          are synchronized somehow.
+//
+//          In this case the macro DFAKE_SCOPED_LOCK has to be
+//          used, it checks that if a thread is inside the push/pop then
+//          noone else is still inside the pop/push
+//
+// class NonThreadSafeQueue {
+//  public:
+//   ...
+//   void push(int) { DFAKE_SCOPED_LOCK(push_pop_); ... }
+//   int pop() { DFAKE_SCOPED_LOCK(push_pop_); ... }
+//   ...
+//  private:
+//   DFAKE_MUTEX(push_pop_);
+// };
+//
+//
+// Example: Queue implementation non thread-safe but still usable if clients
+//          are synchronized somehow, it calls a method to "protect" from
+//          a "protected" method
+//
+//          In this case the macro DFAKE_SCOPED_RECURSIVE_LOCK
+//          has to be used, it checks that if a thread is inside the push/pop
+//          then noone else is still inside the pop/push
+//
+// class NonThreadSafeQueue {
+//  public:
+//   void push(int) {
+//     DFAKE_SCOPED_LOCK(push_pop_);
+//     ...
+//   }
+//   int pop() {
+//     DFAKE_SCOPED_RECURSIVE_LOCK(push_pop_);
+//     bar();
+//     ...
+//   }
+//   void bar() { DFAKE_SCOPED_RECURSIVE_LOCK(push_pop_); ... }
+//   ...
+//  private:
+//   DFAKE_MUTEX(push_pop_);
+// };
+//
+//
+// Example: Queue implementation not usable even if clients are synchronized,
+//          so only one thread in the class life cycle can use the two members
+//          push/pop.
+//
+//          In this case the macro DFAKE_SCOPED_LOCK_THREAD_LOCKED pins the
+//          specified
+//          critical section the first time a thread enters push or pop, from
+//          that time on only that thread is allowed to execute push or pop.
+//
+// class NonThreadSafeQueue {
+//  public:
+//   ...
+//   void push(int) { DFAKE_SCOPED_LOCK_THREAD_LOCKED(push_pop_); ... }
+//   int pop() { DFAKE_SCOPED_LOCK_THREAD_LOCKED(push_pop_); ... }
+//   ...
+//  private:
+//   DFAKE_MUTEX(push_pop_);
+// };
+//
+//
+// Example: Class that has to be contructed/destroyed on same thread, it has
+//          a "shareable" method (with external synchronization) and a not
+//          shareable method (even with external synchronization).
+//
+//          In this case 3 Critical sections have to be defined
+//
+// class ExoticClass {
+//  public:
+//   ExoticClass() { DFAKE_SCOPED_LOCK_THREAD_LOCKED(ctor_dtor_); ... }
+//   ~ExoticClass() { DFAKE_SCOPED_LOCK_THREAD_LOCKED(ctor_dtor_); ... }
+//
+//   void Shareable() { DFAKE_SCOPED_LOCK(shareable_section_); ... }
+//   void NotShareable() { DFAKE_SCOPED_LOCK_THREAD_LOCKED(ctor_dtor_); ... }
+//   ...
+//  private:
+//   DFAKE_MUTEX(ctor_dtor_);
+//   DFAKE_MUTEX(shareable_section_);
+// };
+
+
+#if !defined(NDEBUG)
+
+// Defines a class member that acts like a mutex. It is used only as a
+// verification tool.
+#define DFAKE_MUTEX(obj) \
+     mutable base::ThreadCollisionWarner obj
+// Asserts the call is never called simultaneously in two threads. Used at
+// member function scope.
+#define DFAKE_SCOPED_LOCK(obj) \
+     base::ThreadCollisionWarner::ScopedCheck s_check_##obj(&obj)
+// Asserts the call is never called simultaneously in two threads. Used at
+// member function scope. Same as DFAKE_SCOPED_LOCK but allows recursive locks.
+#define DFAKE_SCOPED_RECURSIVE_LOCK(obj) \
+     base::ThreadCollisionWarner::ScopedRecursiveCheck sr_check_##obj(&obj)
+// Asserts the code is always executed in the same thread.
+#define DFAKE_SCOPED_LOCK_THREAD_LOCKED(obj) \
+     base::ThreadCollisionWarner::Check check_##obj(&obj)
+
+#else
+
+#define DFAKE_MUTEX(obj) typedef void InternalFakeMutexType##obj
+#define DFAKE_SCOPED_LOCK(obj) ((void)0)
+#define DFAKE_SCOPED_RECURSIVE_LOCK(obj) ((void)0)
+#define DFAKE_SCOPED_LOCK_THREAD_LOCKED(obj) ((void)0)
+
+#endif
+
+namespace base {
+
+// The class ThreadCollisionWarner uses an Asserter to notify the collision
+// AsserterBase is the interfaces and DCheckAsserter is the default asserter
+// used. During the unit tests is used another class that doesn't "DCHECK"
+// in case of collision (check thread_collision_warner_unittests.cc)
+struct BASE_EXPORT AsserterBase {
+  virtual ~AsserterBase() = default;
+  virtual void warn() = 0;
+};
+
+struct BASE_EXPORT DCheckAsserter : public AsserterBase {
+  ~DCheckAsserter() override = default;
+  void warn() override;
+};
+
+class BASE_EXPORT ThreadCollisionWarner {
+ public:
+  // The parameter asserter is there only for test purpose
+  explicit ThreadCollisionWarner(AsserterBase* asserter = new DCheckAsserter())
+      : valid_thread_id_(0),
+        counter_(0),
+        asserter_(asserter) {}
+
+  ~ThreadCollisionWarner() {
+    delete asserter_;
+  }
+
+  // This class is meant to be used through the macro
+  // DFAKE_SCOPED_LOCK_THREAD_LOCKED
+  // it doesn't leave the critical section, as opposed to ScopedCheck,
+  // because the critical section being pinned is allowed to be used only
+  // from one thread
+  class BASE_EXPORT Check {
+   public:
+    explicit Check(ThreadCollisionWarner* warner)
+        : warner_(warner) {
+      warner_->EnterSelf();
+    }
+
+    ~Check() = default;
+
+   private:
+    ThreadCollisionWarner* warner_;
+
+    DISALLOW_COPY_AND_ASSIGN(Check);
+  };
+
+  // This class is meant to be used through the macro
+  // DFAKE_SCOPED_LOCK
+  class BASE_EXPORT ScopedCheck {
+   public:
+    explicit ScopedCheck(ThreadCollisionWarner* warner)
+        : warner_(warner) {
+      warner_->Enter();
+    }
+
+    ~ScopedCheck() {
+      warner_->Leave();
+    }
+
+   private:
+    ThreadCollisionWarner* warner_;
+
+    DISALLOW_COPY_AND_ASSIGN(ScopedCheck);
+  };
+
+  // This class is meant to be used through the macro
+  // DFAKE_SCOPED_RECURSIVE_LOCK
+  class BASE_EXPORT ScopedRecursiveCheck {
+   public:
+    explicit ScopedRecursiveCheck(ThreadCollisionWarner* warner)
+        : warner_(warner) {
+      warner_->EnterSelf();
+    }
+
+    ~ScopedRecursiveCheck() {
+      warner_->Leave();
+    }
+
+   private:
+    ThreadCollisionWarner* warner_;
+
+    DISALLOW_COPY_AND_ASSIGN(ScopedRecursiveCheck);
+  };
+
+ private:
+  // This method stores the current thread identifier and does a DCHECK
+  // if a another thread has already done it, it is safe if same thread
+  // calls this multiple time (recursion allowed).
+  void EnterSelf();
+
+  // Same as EnterSelf but recursion is not allowed.
+  void Enter();
+
+  // Removes the thread_id stored in order to allow other threads to
+  // call EnterSelf or Enter.
+  void Leave();
+
+  // This stores the thread id that is inside the critical section, if the
+  // value is 0 then no thread is inside.
+  volatile subtle::Atomic32 valid_thread_id_;
+
+  // Counter to trace how many time a critical section was "pinned"
+  // (when allowed) in order to unpin it when counter_ reaches 0.
+  volatile subtle::Atomic32 counter_;
+
+  // Here only for class unit tests purpose, during the test I need to not
+  // DCHECK but notify the collision with something else.
+  AsserterBase* asserter_;
+
+  DISALLOW_COPY_AND_ASSIGN(ThreadCollisionWarner);
+};
+
+}  // namespace base
+
+#endif  // BASE_THREADING_THREAD_COLLISION_WARNER_H_
diff --git a/base/threading/thread_collision_warner_unittest.cc b/base/threading/thread_collision_warner_unittest.cc
new file mode 100644
index 0000000..cd56768
--- /dev/null
+++ b/base/threading/thread_collision_warner_unittest.cc
@@ -0,0 +1,382 @@
+// 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 "base/threading/thread_collision_warner.h"
+
+#include <memory>
+
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "base/synchronization/lock.h"
+#include "base/threading/platform_thread.h"
+#include "base/threading/simple_thread.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+// '' : local class member function does not have a body
+MSVC_PUSH_DISABLE_WARNING(4822)
+
+
+#if defined(NDEBUG)
+
+// Would cause a memory leak otherwise.
+#undef DFAKE_MUTEX
+#define DFAKE_MUTEX(obj) std::unique_ptr<base::AsserterBase> obj
+
+// In Release, we expect the AsserterBase::warn() to not happen.
+#define EXPECT_NDEBUG_FALSE_DEBUG_TRUE EXPECT_FALSE
+
+#else
+
+// In Debug, we expect the AsserterBase::warn() to happen.
+#define EXPECT_NDEBUG_FALSE_DEBUG_TRUE EXPECT_TRUE
+
+#endif
+
+
+namespace {
+
+// This is the asserter used with ThreadCollisionWarner instead of the default
+// DCheckAsserter. The method fail_state is used to know if a collision took
+// place.
+class AssertReporter : public base::AsserterBase {
+ public:
+  AssertReporter()
+      : failed_(false) {}
+
+  void warn() override { failed_ = true; }
+
+  ~AssertReporter() override = default;
+
+  bool fail_state() const { return failed_; }
+  void reset() { failed_ = false; }
+
+ private:
+  bool failed_;
+};
+
+}  // namespace
+
+TEST(ThreadCollisionTest, BookCriticalSection) {
+  AssertReporter* local_reporter = new AssertReporter();
+
+  base::ThreadCollisionWarner warner(local_reporter);
+  EXPECT_FALSE(local_reporter->fail_state());
+
+  {  // Pin section.
+    DFAKE_SCOPED_LOCK_THREAD_LOCKED(warner);
+    EXPECT_FALSE(local_reporter->fail_state());
+    {  // Pin section.
+      DFAKE_SCOPED_LOCK_THREAD_LOCKED(warner);
+      EXPECT_FALSE(local_reporter->fail_state());
+    }
+  }
+}
+
+TEST(ThreadCollisionTest, ScopedRecursiveBookCriticalSection) {
+  AssertReporter* local_reporter = new AssertReporter();
+
+  base::ThreadCollisionWarner warner(local_reporter);
+  EXPECT_FALSE(local_reporter->fail_state());
+
+  {  // Pin section.
+    DFAKE_SCOPED_RECURSIVE_LOCK(warner);
+    EXPECT_FALSE(local_reporter->fail_state());
+    {  // Pin section again (allowed by DFAKE_SCOPED_RECURSIVE_LOCK)
+      DFAKE_SCOPED_RECURSIVE_LOCK(warner);
+      EXPECT_FALSE(local_reporter->fail_state());
+    }  // Unpin section.
+  }  // Unpin section.
+
+  // Check that section is not pinned
+  {  // Pin section.
+    DFAKE_SCOPED_LOCK(warner);
+    EXPECT_FALSE(local_reporter->fail_state());
+  }  // Unpin section.
+}
+
+TEST(ThreadCollisionTest, ScopedBookCriticalSection) {
+  AssertReporter* local_reporter = new AssertReporter();
+
+  base::ThreadCollisionWarner warner(local_reporter);
+  EXPECT_FALSE(local_reporter->fail_state());
+
+  {  // Pin section.
+    DFAKE_SCOPED_LOCK(warner);
+    EXPECT_FALSE(local_reporter->fail_state());
+  }  // Unpin section.
+
+  {  // Pin section.
+    DFAKE_SCOPED_LOCK(warner);
+    EXPECT_FALSE(local_reporter->fail_state());
+    {
+      // Pin section again (not allowed by DFAKE_SCOPED_LOCK)
+      DFAKE_SCOPED_LOCK(warner);
+      EXPECT_NDEBUG_FALSE_DEBUG_TRUE(local_reporter->fail_state());
+      // Reset the status of warner for further tests.
+      local_reporter->reset();
+    }  // Unpin section.
+  }  // Unpin section.
+
+  {
+    // Pin section.
+    DFAKE_SCOPED_LOCK(warner);
+    EXPECT_FALSE(local_reporter->fail_state());
+  }  // Unpin section.
+}
+
+TEST(ThreadCollisionTest, MTBookCriticalSectionTest) {
+  class NonThreadSafeQueue {
+   public:
+    explicit NonThreadSafeQueue(base::AsserterBase* asserter)
+        : push_pop_(asserter) {
+    }
+
+    void push(int value) {
+      DFAKE_SCOPED_LOCK_THREAD_LOCKED(push_pop_);
+    }
+
+    int pop() {
+      DFAKE_SCOPED_LOCK_THREAD_LOCKED(push_pop_);
+      return 0;
+    }
+
+   private:
+    DFAKE_MUTEX(push_pop_);
+
+    DISALLOW_COPY_AND_ASSIGN(NonThreadSafeQueue);
+  };
+
+  class QueueUser : public base::DelegateSimpleThread::Delegate {
+   public:
+    explicit QueueUser(NonThreadSafeQueue* queue) : queue_(queue) {}
+
+    void Run() override {
+      queue_->push(0);
+      queue_->pop();
+    }
+
+   private:
+    NonThreadSafeQueue* queue_;
+  };
+
+  AssertReporter* local_reporter = new AssertReporter();
+
+  NonThreadSafeQueue queue(local_reporter);
+
+  QueueUser queue_user_a(&queue);
+  QueueUser queue_user_b(&queue);
+
+  base::DelegateSimpleThread thread_a(&queue_user_a, "queue_user_thread_a");
+  base::DelegateSimpleThread thread_b(&queue_user_b, "queue_user_thread_b");
+
+  thread_a.Start();
+  thread_b.Start();
+
+  thread_a.Join();
+  thread_b.Join();
+
+  EXPECT_NDEBUG_FALSE_DEBUG_TRUE(local_reporter->fail_state());
+}
+
+TEST(ThreadCollisionTest, MTScopedBookCriticalSectionTest) {
+  // Queue with a 5 seconds push execution time, hopefuly the two used threads
+  // in the test will enter the push at same time.
+  class NonThreadSafeQueue {
+   public:
+    explicit NonThreadSafeQueue(base::AsserterBase* asserter)
+        : push_pop_(asserter) {
+    }
+
+    void push(int value) {
+      DFAKE_SCOPED_LOCK(push_pop_);
+      base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(5));
+    }
+
+    int pop() {
+      DFAKE_SCOPED_LOCK(push_pop_);
+      return 0;
+    }
+
+   private:
+    DFAKE_MUTEX(push_pop_);
+
+    DISALLOW_COPY_AND_ASSIGN(NonThreadSafeQueue);
+  };
+
+  class QueueUser : public base::DelegateSimpleThread::Delegate {
+   public:
+    explicit QueueUser(NonThreadSafeQueue* queue) : queue_(queue) {}
+
+    void Run() override {
+      queue_->push(0);
+      queue_->pop();
+    }
+
+   private:
+    NonThreadSafeQueue* queue_;
+  };
+
+  AssertReporter* local_reporter = new AssertReporter();
+
+  NonThreadSafeQueue queue(local_reporter);
+
+  QueueUser queue_user_a(&queue);
+  QueueUser queue_user_b(&queue);
+
+  base::DelegateSimpleThread thread_a(&queue_user_a, "queue_user_thread_a");
+  base::DelegateSimpleThread thread_b(&queue_user_b, "queue_user_thread_b");
+
+  thread_a.Start();
+  thread_b.Start();
+
+  thread_a.Join();
+  thread_b.Join();
+
+  EXPECT_NDEBUG_FALSE_DEBUG_TRUE(local_reporter->fail_state());
+}
+
+TEST(ThreadCollisionTest, MTSynchedScopedBookCriticalSectionTest) {
+  // Queue with a 2 seconds push execution time, hopefuly the two used threads
+  // in the test will enter the push at same time.
+  class NonThreadSafeQueue {
+   public:
+    explicit NonThreadSafeQueue(base::AsserterBase* asserter)
+        : push_pop_(asserter) {
+    }
+
+    void push(int value) {
+      DFAKE_SCOPED_LOCK(push_pop_);
+      base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(2));
+    }
+
+    int pop() {
+      DFAKE_SCOPED_LOCK(push_pop_);
+      return 0;
+    }
+
+   private:
+    DFAKE_MUTEX(push_pop_);
+
+    DISALLOW_COPY_AND_ASSIGN(NonThreadSafeQueue);
+  };
+
+  // This time the QueueUser class protects the non thread safe queue with
+  // a lock.
+  class QueueUser : public base::DelegateSimpleThread::Delegate {
+   public:
+    QueueUser(NonThreadSafeQueue* queue, base::Lock* lock)
+        : queue_(queue), lock_(lock) {}
+
+    void Run() override {
+      {
+        base::AutoLock auto_lock(*lock_);
+        queue_->push(0);
+      }
+      {
+        base::AutoLock auto_lock(*lock_);
+        queue_->pop();
+      }
+    }
+   private:
+    NonThreadSafeQueue* queue_;
+    base::Lock* lock_;
+  };
+
+  AssertReporter* local_reporter = new AssertReporter();
+
+  NonThreadSafeQueue queue(local_reporter);
+
+  base::Lock lock;
+
+  QueueUser queue_user_a(&queue, &lock);
+  QueueUser queue_user_b(&queue, &lock);
+
+  base::DelegateSimpleThread thread_a(&queue_user_a, "queue_user_thread_a");
+  base::DelegateSimpleThread thread_b(&queue_user_b, "queue_user_thread_b");
+
+  thread_a.Start();
+  thread_b.Start();
+
+  thread_a.Join();
+  thread_b.Join();
+
+  EXPECT_FALSE(local_reporter->fail_state());
+}
+
+TEST(ThreadCollisionTest, MTSynchedScopedRecursiveBookCriticalSectionTest) {
+  // Queue with a 2 seconds push execution time, hopefuly the two used threads
+  // in the test will enter the push at same time.
+  class NonThreadSafeQueue {
+   public:
+    explicit NonThreadSafeQueue(base::AsserterBase* asserter)
+        : push_pop_(asserter) {
+    }
+
+    void push(int) {
+      DFAKE_SCOPED_RECURSIVE_LOCK(push_pop_);
+      bar();
+      base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(2));
+    }
+
+    int pop() {
+      DFAKE_SCOPED_RECURSIVE_LOCK(push_pop_);
+      return 0;
+    }
+
+    void bar() {
+      DFAKE_SCOPED_RECURSIVE_LOCK(push_pop_);
+    }
+
+   private:
+    DFAKE_MUTEX(push_pop_);
+
+    DISALLOW_COPY_AND_ASSIGN(NonThreadSafeQueue);
+  };
+
+  // This time the QueueUser class protects the non thread safe queue with
+  // a lock.
+  class QueueUser : public base::DelegateSimpleThread::Delegate {
+   public:
+    QueueUser(NonThreadSafeQueue* queue, base::Lock* lock)
+        : queue_(queue), lock_(lock) {}
+
+    void Run() override {
+      {
+        base::AutoLock auto_lock(*lock_);
+        queue_->push(0);
+      }
+      {
+        base::AutoLock auto_lock(*lock_);
+        queue_->bar();
+      }
+      {
+        base::AutoLock auto_lock(*lock_);
+        queue_->pop();
+      }
+    }
+   private:
+    NonThreadSafeQueue* queue_;
+    base::Lock* lock_;
+  };
+
+  AssertReporter* local_reporter = new AssertReporter();
+
+  NonThreadSafeQueue queue(local_reporter);
+
+  base::Lock lock;
+
+  QueueUser queue_user_a(&queue, &lock);
+  QueueUser queue_user_b(&queue, &lock);
+
+  base::DelegateSimpleThread thread_a(&queue_user_a, "queue_user_thread_a");
+  base::DelegateSimpleThread thread_b(&queue_user_b, "queue_user_thread_b");
+
+  thread_a.Start();
+  thread_b.Start();
+
+  thread_a.Join();
+  thread_b.Join();
+
+  EXPECT_FALSE(local_reporter->fail_state());
+}
diff --git a/base/threading/thread_id_name_manager.cc b/base/threading/thread_id_name_manager.cc
new file mode 100644
index 0000000..ca1979d
--- /dev/null
+++ b/base/threading/thread_id_name_manager.cc
@@ -0,0 +1,142 @@
+// 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 "base/threading/thread_id_name_manager.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "base/logging.h"
+#include "base/memory/singleton.h"
+#include "base/no_destructor.h"
+#include "base/strings/string_util.h"
+#include "base/threading/thread_local.h"
+#include "base/trace_event/heap_profiler_allocation_context_tracker.h"
+
+namespace base {
+namespace {
+
+static const char kDefaultName[] = "";
+static std::string* g_default_name;
+
+ThreadLocalStorage::Slot& GetThreadNameTLS() {
+  static base::NoDestructor<base::ThreadLocalStorage::Slot> thread_name_tls;
+  return *thread_name_tls;
+}
+}
+
+ThreadIdNameManager::ThreadIdNameManager()
+    : main_process_name_(nullptr), main_process_id_(kInvalidThreadId) {
+  g_default_name = new std::string(kDefaultName);
+
+  AutoLock locked(lock_);
+  name_to_interned_name_[kDefaultName] = g_default_name;
+}
+
+ThreadIdNameManager::~ThreadIdNameManager() = default;
+
+ThreadIdNameManager* ThreadIdNameManager::GetInstance() {
+  return Singleton<ThreadIdNameManager,
+      LeakySingletonTraits<ThreadIdNameManager> >::get();
+}
+
+const char* ThreadIdNameManager::GetDefaultInternedString() {
+  return g_default_name->c_str();
+}
+
+void ThreadIdNameManager::RegisterThread(PlatformThreadHandle::Handle handle,
+                                         PlatformThreadId id) {
+  AutoLock locked(lock_);
+  thread_id_to_handle_[id] = handle;
+  thread_handle_to_interned_name_[handle] =
+      name_to_interned_name_[kDefaultName];
+}
+
+void ThreadIdNameManager::InstallSetNameCallback(SetNameCallback callback) {
+  AutoLock locked(lock_);
+  set_name_callback_ = std::move(callback);
+}
+
+void ThreadIdNameManager::SetName(const std::string& name) {
+  PlatformThreadId id = PlatformThread::CurrentId();
+  std::string* leaked_str = nullptr;
+  {
+    AutoLock locked(lock_);
+    NameToInternedNameMap::iterator iter = name_to_interned_name_.find(name);
+    if (iter != name_to_interned_name_.end()) {
+      leaked_str = iter->second;
+    } else {
+      leaked_str = new std::string(name);
+      name_to_interned_name_[name] = leaked_str;
+    }
+
+    ThreadIdToHandleMap::iterator id_to_handle_iter =
+        thread_id_to_handle_.find(id);
+
+    GetThreadNameTLS().Set(const_cast<char*>(leaked_str->c_str()));
+    if (set_name_callback_) {
+      set_name_callback_.Run(leaked_str->c_str());
+    }
+
+    // The main thread of a process will not be created as a Thread object which
+    // means there is no PlatformThreadHandler registered.
+    if (id_to_handle_iter == thread_id_to_handle_.end()) {
+      main_process_name_ = leaked_str;
+      main_process_id_ = id;
+      return;
+    }
+    thread_handle_to_interned_name_[id_to_handle_iter->second] = leaked_str;
+  }
+
+  // Add the leaked thread name to heap profiler context tracker. The name added
+  // is valid for the lifetime of the process. AllocationContextTracker cannot
+  // call GetName(which holds a lock) during the first allocation because it can
+  // cause a deadlock when the first allocation happens in the
+  // ThreadIdNameManager itself when holding the lock.
+  trace_event::AllocationContextTracker::SetCurrentThreadName(
+      leaked_str->c_str());
+}
+
+const char* ThreadIdNameManager::GetName(PlatformThreadId id) {
+  AutoLock locked(lock_);
+
+  if (id == main_process_id_)
+    return main_process_name_->c_str();
+
+  ThreadIdToHandleMap::iterator id_to_handle_iter =
+      thread_id_to_handle_.find(id);
+  if (id_to_handle_iter == thread_id_to_handle_.end())
+    return name_to_interned_name_[kDefaultName]->c_str();
+
+  ThreadHandleToInternedNameMap::iterator handle_to_name_iter =
+      thread_handle_to_interned_name_.find(id_to_handle_iter->second);
+  return handle_to_name_iter->second->c_str();
+}
+
+const char* ThreadIdNameManager::GetNameForCurrentThread() {
+  const char* name = reinterpret_cast<const char*>(GetThreadNameTLS().Get());
+  return name ? name : kDefaultName;
+}
+
+void ThreadIdNameManager::RemoveName(PlatformThreadHandle::Handle handle,
+                                     PlatformThreadId id) {
+  AutoLock locked(lock_);
+  ThreadHandleToInternedNameMap::iterator handle_to_name_iter =
+      thread_handle_to_interned_name_.find(handle);
+
+  DCHECK(handle_to_name_iter != thread_handle_to_interned_name_.end());
+  thread_handle_to_interned_name_.erase(handle_to_name_iter);
+
+  ThreadIdToHandleMap::iterator id_to_handle_iter =
+      thread_id_to_handle_.find(id);
+  DCHECK((id_to_handle_iter!= thread_id_to_handle_.end()));
+  // The given |id| may have been re-used by the system. Make sure the
+  // mapping points to the provided |handle| before removal.
+  if (id_to_handle_iter->second != handle)
+    return;
+
+  thread_id_to_handle_.erase(id_to_handle_iter);
+}
+
+}  // namespace base
diff --git a/base/threading/thread_id_name_manager.h b/base/threading/thread_id_name_manager.h
new file mode 100644
index 0000000..f17dc1a
--- /dev/null
+++ b/base/threading/thread_id_name_manager.h
@@ -0,0 +1,80 @@
+// 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.
+
+#ifndef BASE_THREADING_THREAD_ID_NAME_MANAGER_H_
+#define BASE_THREADING_THREAD_ID_NAME_MANAGER_H_
+
+#include <map>
+#include <string>
+
+#include "base/base_export.h"
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/synchronization/lock.h"
+#include "base/threading/platform_thread.h"
+
+namespace base {
+
+template <typename T>
+struct DefaultSingletonTraits;
+
+class BASE_EXPORT ThreadIdNameManager {
+ public:
+  static ThreadIdNameManager* GetInstance();
+
+  static const char* GetDefaultInternedString();
+
+  // Register the mapping between a thread |id| and |handle|.
+  void RegisterThread(PlatformThreadHandle::Handle handle, PlatformThreadId id);
+
+  // The callback is called on the thread, immediately after the name is set.
+  // |name| is a pointer to a C string that is guaranteed to remain valid for
+  // the duration of the process.
+  using SetNameCallback = base::RepeatingCallback<void(const char* name)>;
+  void InstallSetNameCallback(SetNameCallback callback);
+
+  // Set the name for the current thread.
+  void SetName(const std::string& name);
+
+  // Get the name for the given id.
+  const char* GetName(PlatformThreadId id);
+
+  // Unlike |GetName|, this method using TLS and avoids touching |lock_|.
+  const char* GetNameForCurrentThread();
+
+  // Remove the name for the given id.
+  void RemoveName(PlatformThreadHandle::Handle handle, PlatformThreadId id);
+
+ private:
+  friend struct DefaultSingletonTraits<ThreadIdNameManager>;
+
+  typedef std::map<PlatformThreadId, PlatformThreadHandle::Handle>
+      ThreadIdToHandleMap;
+  typedef std::map<PlatformThreadHandle::Handle, std::string*>
+      ThreadHandleToInternedNameMap;
+  typedef std::map<std::string, std::string*> NameToInternedNameMap;
+
+  ThreadIdNameManager();
+  ~ThreadIdNameManager();
+
+  // lock_ protects the name_to_interned_name_, thread_id_to_handle_ and
+  // thread_handle_to_interned_name_ maps.
+  Lock lock_;
+
+  NameToInternedNameMap name_to_interned_name_;
+  ThreadIdToHandleMap thread_id_to_handle_;
+  ThreadHandleToInternedNameMap thread_handle_to_interned_name_;
+
+  // Treat the main process specially as there is no PlatformThreadHandle.
+  std::string* main_process_name_;
+  PlatformThreadId main_process_id_;
+
+  SetNameCallback set_name_callback_;
+
+  DISALLOW_COPY_AND_ASSIGN(ThreadIdNameManager);
+};
+
+}  // namespace base
+
+#endif  // BASE_THREADING_THREAD_ID_NAME_MANAGER_H_
diff --git a/base/threading/thread_id_name_manager_unittest.cc b/base/threading/thread_id_name_manager_unittest.cc
new file mode 100644
index 0000000..350dc0f
--- /dev/null
+++ b/base/threading/thread_id_name_manager_unittest.cc
@@ -0,0 +1,93 @@
+// 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 "base/threading/thread_id_name_manager.h"
+
+#include "base/threading/platform_thread.h"
+#include "base/threading/thread.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+typedef PlatformTest ThreadIdNameManagerTest;
+
+namespace {
+
+const char kAThread[] = "a thread";
+const char kBThread[] = "b thread";
+
+TEST_F(ThreadIdNameManagerTest, AddThreads) {
+  base::ThreadIdNameManager* manager = base::ThreadIdNameManager::GetInstance();
+  base::Thread thread_a(kAThread);
+  base::Thread thread_b(kBThread);
+
+  thread_a.StartAndWaitForTesting();
+  thread_b.StartAndWaitForTesting();
+
+  EXPECT_STREQ(kAThread, manager->GetName(thread_a.GetThreadId()));
+  EXPECT_STREQ(kBThread, manager->GetName(thread_b.GetThreadId()));
+
+  thread_b.Stop();
+  thread_a.Stop();
+}
+
+TEST_F(ThreadIdNameManagerTest, RemoveThreads) {
+  base::ThreadIdNameManager* manager = base::ThreadIdNameManager::GetInstance();
+  base::Thread thread_a(kAThread);
+
+  thread_a.StartAndWaitForTesting();
+  {
+    base::Thread thread_b(kBThread);
+    thread_b.StartAndWaitForTesting();
+    thread_b.Stop();
+  }
+  EXPECT_STREQ(kAThread, manager->GetName(thread_a.GetThreadId()));
+
+  thread_a.Stop();
+  EXPECT_STREQ("", manager->GetName(thread_a.GetThreadId()));
+}
+
+TEST_F(ThreadIdNameManagerTest, RestartThread) {
+  base::ThreadIdNameManager* manager = base::ThreadIdNameManager::GetInstance();
+  base::Thread thread_a(kAThread);
+
+  thread_a.StartAndWaitForTesting();
+  base::PlatformThreadId a_id = thread_a.GetThreadId();
+  EXPECT_STREQ(kAThread, manager->GetName(a_id));
+  thread_a.Stop();
+
+  thread_a.StartAndWaitForTesting();
+  EXPECT_STREQ("", manager->GetName(a_id));
+  EXPECT_STREQ(kAThread, manager->GetName(thread_a.GetThreadId()));
+  thread_a.Stop();
+}
+
+TEST_F(ThreadIdNameManagerTest, ThreadNameInterning) {
+  base::ThreadIdNameManager* manager = base::ThreadIdNameManager::GetInstance();
+
+  base::PlatformThreadId a_id = base::PlatformThread::CurrentId();
+  base::PlatformThread::SetName("First Name");
+  std::string version = manager->GetName(a_id);
+
+  base::PlatformThread::SetName("New name");
+  EXPECT_NE(version, manager->GetName(a_id));
+  base::PlatformThread::SetName("");
+}
+
+TEST_F(ThreadIdNameManagerTest, ResettingNameKeepsCorrectInternedValue) {
+  base::ThreadIdNameManager* manager = base::ThreadIdNameManager::GetInstance();
+
+  base::PlatformThreadId a_id = base::PlatformThread::CurrentId();
+  base::PlatformThread::SetName("Test Name");
+  std::string version = manager->GetName(a_id);
+
+  base::PlatformThread::SetName("New name");
+  EXPECT_NE(version, manager->GetName(a_id));
+
+  base::PlatformThread::SetName("Test Name");
+  EXPECT_EQ(version, manager->GetName(a_id));
+
+  base::PlatformThread::SetName("");
+}
+
+}  // namespace
diff --git a/base/threading/thread_local.h b/base/threading/thread_local.h
new file mode 100644
index 0000000..cad9add
--- /dev/null
+++ b/base/threading/thread_local.h
@@ -0,0 +1,99 @@
+// Copyright (c) 2011 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.
+
+// WARNING: Thread local storage is a bit tricky to get right. Please make sure
+// that this is really the proper solution for what you're trying to achieve.
+// Don't prematurely optimize, most likely you can just use a Lock.
+//
+// These classes implement a wrapper around ThreadLocalStorage::Slot. On
+// construction, they will allocate a TLS slot, and free the TLS slot on
+// destruction. No memory management (creation or destruction) is handled. This
+// means for uses of ThreadLocalPointer, you must correctly manage the memory
+// yourself, these classes will not destroy the pointer for you. There are no
+// at-thread-exit actions taken by these classes.
+//
+// ThreadLocalPointer<Type> wraps a Type*. It performs no creation or
+// destruction, so memory management must be handled elsewhere. The first call
+// to Get() on a thread will return NULL. You can update the pointer with a call
+// to Set().
+//
+// ThreadLocalBoolean wraps a bool. It will default to false if it has never
+// been set otherwise with Set().
+//
+// Thread Safety: An instance of ThreadLocalStorage is completely thread safe
+// once it has been created. If you want to dynamically create an instance, you
+// must of course properly deal with safety and race conditions. This means a
+// function-level static initializer is generally inappropiate.
+//
+// In Android, the system TLS is limited.
+//
+// Example usage:
+//   // My class is logically attached to a single thread. We cache a pointer
+//   // on the thread it was created on, so we can implement current().
+//   MyClass::MyClass() {
+//     DCHECK(Singleton<ThreadLocalPointer<MyClass> >::get()->Get() == NULL);
+//     Singleton<ThreadLocalPointer<MyClass> >::get()->Set(this);
+//   }
+//
+//   MyClass::~MyClass() {
+//     DCHECK(Singleton<ThreadLocalPointer<MyClass> >::get()->Get() != NULL);
+//     Singleton<ThreadLocalPointer<MyClass> >::get()->Set(NULL);
+//   }
+//
+//   // Return the current MyClass associated with the calling thread, can be
+//   // NULL if there isn't a MyClass associated.
+//   MyClass* MyClass::current() {
+//     return Singleton<ThreadLocalPointer<MyClass> >::get()->Get();
+//   }
+
+#ifndef BASE_THREADING_THREAD_LOCAL_H_
+#define BASE_THREADING_THREAD_LOCAL_H_
+
+#include "base/macros.h"
+#include "base/threading/thread_local_storage.h"
+
+namespace base {
+
+template <typename Type>
+class ThreadLocalPointer {
+ public:
+  ThreadLocalPointer() = default;
+  ~ThreadLocalPointer() = default;
+
+  Type* Get() {
+    return static_cast<Type*>(slot_.Get());
+  }
+
+  void Set(Type* ptr) {
+    slot_.Set(const_cast<void*>(static_cast<const void*>(ptr)));
+  }
+
+ private:
+  ThreadLocalStorage::Slot slot_;
+
+  DISALLOW_COPY_AND_ASSIGN(ThreadLocalPointer<Type>);
+};
+
+class ThreadLocalBoolean {
+ public:
+  ThreadLocalBoolean() = default;
+  ~ThreadLocalBoolean() = default;
+
+  bool Get() {
+    return tlp_.Get() != nullptr;
+  }
+
+  void Set(bool val) {
+    tlp_.Set(val ? this : nullptr);
+  }
+
+ private:
+  ThreadLocalPointer<void> tlp_;
+
+  DISALLOW_COPY_AND_ASSIGN(ThreadLocalBoolean);
+};
+
+}  // namespace base
+
+#endif  // BASE_THREADING_THREAD_LOCAL_H_
diff --git a/base/threading/thread_local_storage.cc b/base/threading/thread_local_storage.cc
new file mode 100644
index 0000000..21fd323
--- /dev/null
+++ b/base/threading/thread_local_storage.cc
@@ -0,0 +1,397 @@
+// Copyright 2014 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 "base/threading/thread_local_storage.h"
+
+#include "base/atomicops.h"
+#include "base/logging.h"
+#include "base/synchronization/lock.h"
+#include "build/build_config.h"
+
+using base::internal::PlatformThreadLocalStorage;
+
+// Chrome Thread Local Storage (TLS)
+//
+// This TLS system allows Chrome to use a single OS level TLS slot process-wide,
+// and allows us to control the slot limits instead of being at the mercy of the
+// platform. To do this, Chrome TLS replicates an array commonly found in the OS
+// thread metadata.
+//
+// Overview:
+//
+// OS TLS Slots       Per-Thread                 Per-Process Global
+//     ...
+//     []             Chrome TLS Array           Chrome TLS Metadata
+//     [] ----------> [][][][][ ][][][][]        [][][][][ ][][][][]
+//     []                      |                          |
+//     ...                     V                          V
+//                      Metadata Version           Slot Information
+//                         Your Data!
+//
+// Using a single OS TLS slot, Chrome TLS allocates an array on demand for the
+// lifetime of each thread that requests Chrome TLS data. Each per-thread TLS
+// array matches the length of the per-process global metadata array.
+//
+// A per-process global TLS metadata array tracks information about each item in
+// the per-thread array:
+//   * Status: Tracks if the slot is allocated or free to assign.
+//   * Destructor: An optional destructor to call on thread destruction for that
+//                 specific slot.
+//   * Version: Tracks the current version of the TLS slot. Each TLS slot
+//              allocation is associated with a unique version number.
+//
+//              Most OS TLS APIs guarantee that a newly allocated TLS slot is
+//              initialized to 0 for all threads. The Chrome TLS system provides
+//              this guarantee by tracking the version for each TLS slot here
+//              on each per-thread Chrome TLS array entry. Threads that access
+//              a slot with a mismatched version will receive 0 as their value.
+//              The metadata version is incremented when the client frees a
+//              slot. The per-thread metadata version is updated when a client
+//              writes to the slot. This scheme allows for constant time
+//              invalidation and avoids the need to iterate through each Chrome
+//              TLS array to mark the slot as zero.
+//
+// Just like an OS TLS API, clients of the Chrome TLS are responsible for
+// managing any necessary lifetime of the data in their slots. The only
+// convenience provided is automatic destruction when a thread ends. If a client
+// frees a slot, that client is responsible for destroying the data in the slot.
+
+namespace {
+// In order to make TLS destructors work, we need to keep around a function
+// pointer to the destructor for each slot. We keep this array of pointers in a
+// global (static) array.
+// We use the single OS-level TLS slot (giving us one pointer per thread) to
+// hold a pointer to a per-thread array (table) of slots that we allocate to
+// Chromium consumers.
+
+// g_native_tls_key is the one native TLS that we use. It stores our table.
+base::subtle::Atomic32 g_native_tls_key =
+    PlatformThreadLocalStorage::TLS_KEY_OUT_OF_INDEXES;
+
+// The OS TLS slot has three states:
+//   * kUninitialized: Any call to Slot::Get()/Set() will create the base
+//     per-thread TLS state. On POSIX, kUninitialized must be 0.
+//   * [Memory Address]: Raw pointer to the base per-thread TLS state.
+//   * kDestroyed: The base per-thread TLS state has been freed.
+//
+// Final States:
+//   * Windows: kDestroyed. Windows does not iterate through the OS TLS to clean
+//     up the values.
+//   * POSIX: kUninitialized. POSIX iterates through TLS until all slots contain
+//     nullptr.
+//
+// More details on this design:
+//   We need some type of thread-local state to indicate that the TLS system has
+//   been destroyed. To do so, we leverage the multi-pass nature of destruction
+//   of pthread_key.
+//
+//    a) After destruction of TLS system, we set the pthread_key to a sentinel
+//       kDestroyed.
+//    b) All calls to Slot::Get() DCHECK that the state is not kDestroyed, and
+//       any system which might potentially invoke Slot::Get() after destruction
+//       of TLS must check ThreadLocalStorage::ThreadIsBeingDestroyed().
+//    c) After a full pass of the pthread_keys, on the next invocation of
+//       ConstructTlsVector(), we'll then set the key to nullptr.
+//    d) At this stage, the TLS system is back in its uninitialized state.
+//    e) If in the second pass of destruction of pthread_keys something were to
+//       re-initialize TLS [this should never happen! Since the only code which
+//       uses Chrome TLS is Chrome controlled, we should really be striving for
+//       single-pass destruction], then TLS will be re-initialized and then go
+//       through the 2-pass destruction system again. Everything should just
+//       work (TM).
+
+// The consumers of kUninitialized and kDestroyed expect void*, since that's
+// what the API exposes on both POSIX and Windows.
+void* const kUninitialized = nullptr;
+
+// A sentinel value to indicate that the TLS system has been destroyed.
+void* const kDestroyed = reinterpret_cast<void*>(1);
+
+// The maximum number of slots in our thread local storage stack.
+constexpr int kThreadLocalStorageSize = 256;
+
+enum TlsStatus {
+  FREE,
+  IN_USE,
+};
+
+struct TlsMetadata {
+  TlsStatus status;
+  base::ThreadLocalStorage::TLSDestructorFunc destructor;
+  uint32_t version;
+};
+
+struct TlsVectorEntry {
+  void* data;
+  uint32_t version;
+};
+
+// This lock isn't needed until after we've constructed the per-thread TLS
+// vector, so it's safe to use.
+base::Lock* GetTLSMetadataLock() {
+  static auto* lock = new base::Lock();
+  return lock;
+}
+TlsMetadata g_tls_metadata[kThreadLocalStorageSize];
+size_t g_last_assigned_slot = 0;
+
+// The maximum number of times to try to clear slots by calling destructors.
+// Use pthread naming convention for clarity.
+constexpr int kMaxDestructorIterations = kThreadLocalStorageSize;
+
+// This function is called to initialize our entire Chromium TLS system.
+// It may be called very early, and we need to complete most all of the setup
+// (initialization) before calling *any* memory allocator functions, which may
+// recursively depend on this initialization.
+// As a result, we use Atomics, and avoid anything (like a singleton) that might
+// require memory allocations.
+TlsVectorEntry* ConstructTlsVector() {
+  PlatformThreadLocalStorage::TLSKey key =
+      base::subtle::NoBarrier_Load(&g_native_tls_key);
+  if (key == PlatformThreadLocalStorage::TLS_KEY_OUT_OF_INDEXES) {
+    CHECK(PlatformThreadLocalStorage::AllocTLS(&key));
+
+    // The TLS_KEY_OUT_OF_INDEXES is used to find out whether the key is set or
+    // not in NoBarrier_CompareAndSwap, but Posix doesn't have invalid key, we
+    // define an almost impossible value be it.
+    // If we really get TLS_KEY_OUT_OF_INDEXES as value of key, just alloc
+    // another TLS slot.
+    if (key == PlatformThreadLocalStorage::TLS_KEY_OUT_OF_INDEXES) {
+      PlatformThreadLocalStorage::TLSKey tmp = key;
+      CHECK(PlatformThreadLocalStorage::AllocTLS(&key) &&
+            key != PlatformThreadLocalStorage::TLS_KEY_OUT_OF_INDEXES);
+      PlatformThreadLocalStorage::FreeTLS(tmp);
+    }
+    // Atomically test-and-set the tls_key. If the key is
+    // TLS_KEY_OUT_OF_INDEXES, go ahead and set it. Otherwise, do nothing, as
+    // another thread already did our dirty work.
+    if (PlatformThreadLocalStorage::TLS_KEY_OUT_OF_INDEXES !=
+        static_cast<PlatformThreadLocalStorage::TLSKey>(
+            base::subtle::NoBarrier_CompareAndSwap(
+                &g_native_tls_key,
+                PlatformThreadLocalStorage::TLS_KEY_OUT_OF_INDEXES, key))) {
+      // We've been shortcut. Another thread replaced g_native_tls_key first so
+      // we need to destroy our index and use the one the other thread got
+      // first.
+      PlatformThreadLocalStorage::FreeTLS(key);
+      key = base::subtle::NoBarrier_Load(&g_native_tls_key);
+    }
+  }
+  CHECK_EQ(PlatformThreadLocalStorage::GetTLSValue(key), kUninitialized);
+
+  // Some allocators, such as TCMalloc, make use of thread local storage. As a
+  // result, any attempt to call new (or malloc) will lazily cause such a system
+  // to initialize, which will include registering for a TLS key. If we are not
+  // careful here, then that request to create a key will call new back, and
+  // we'll have an infinite loop. We avoid that as follows: Use a stack
+  // allocated vector, so that we don't have dependence on our allocator until
+  // our service is in place. (i.e., don't even call new until after we're
+  // setup)
+  TlsVectorEntry stack_allocated_tls_data[kThreadLocalStorageSize];
+  memset(stack_allocated_tls_data, 0, sizeof(stack_allocated_tls_data));
+  // Ensure that any rentrant calls change the temp version.
+  PlatformThreadLocalStorage::SetTLSValue(key, stack_allocated_tls_data);
+
+  // Allocate an array to store our data.
+  TlsVectorEntry* tls_data = new TlsVectorEntry[kThreadLocalStorageSize];
+  memcpy(tls_data, stack_allocated_tls_data, sizeof(stack_allocated_tls_data));
+  PlatformThreadLocalStorage::SetTLSValue(key, tls_data);
+  return tls_data;
+}
+
+void OnThreadExitInternal(TlsVectorEntry* tls_data) {
+  // This branch is for POSIX, where this function is called twice. The first
+  // pass calls dtors and sets state to kDestroyed. The second pass sets
+  // kDestroyed to kUninitialized.
+  if (tls_data == kDestroyed) {
+    PlatformThreadLocalStorage::TLSKey key =
+        base::subtle::NoBarrier_Load(&g_native_tls_key);
+    PlatformThreadLocalStorage::SetTLSValue(key, kUninitialized);
+    return;
+  }
+
+  DCHECK(tls_data);
+  // Some allocators, such as TCMalloc, use TLS. As a result, when a thread
+  // terminates, one of the destructor calls we make may be to shut down an
+  // allocator. We have to be careful that after we've shutdown all of the known
+  // destructors (perchance including an allocator), that we don't call the
+  // allocator and cause it to resurrect itself (with no possibly destructor
+  // call to follow). We handle this problem as follows: Switch to using a stack
+  // allocated vector, so that we don't have dependence on our allocator after
+  // we have called all g_tls_metadata destructors. (i.e., don't even call
+  // delete[] after we're done with destructors.)
+  TlsVectorEntry stack_allocated_tls_data[kThreadLocalStorageSize];
+  memcpy(stack_allocated_tls_data, tls_data, sizeof(stack_allocated_tls_data));
+  // Ensure that any re-entrant calls change the temp version.
+  PlatformThreadLocalStorage::TLSKey key =
+      base::subtle::NoBarrier_Load(&g_native_tls_key);
+  PlatformThreadLocalStorage::SetTLSValue(key, stack_allocated_tls_data);
+  delete[] tls_data;  // Our last dependence on an allocator.
+
+  // Snapshot the TLS Metadata so we don't have to lock on every access.
+  TlsMetadata tls_metadata[kThreadLocalStorageSize];
+  {
+    base::AutoLock auto_lock(*GetTLSMetadataLock());
+    memcpy(tls_metadata, g_tls_metadata, sizeof(g_tls_metadata));
+  }
+
+  int remaining_attempts = kMaxDestructorIterations;
+  bool need_to_scan_destructors = true;
+  while (need_to_scan_destructors) {
+    need_to_scan_destructors = false;
+    // Try to destroy the first-created-slot (which is slot 1) in our last
+    // destructor call. That user was able to function, and define a slot with
+    // no other services running, so perhaps it is a basic service (like an
+    // allocator) and should also be destroyed last. If we get the order wrong,
+    // then we'll iterate several more times, so it is really not that critical
+    // (but it might help).
+    for (int slot = 0; slot < kThreadLocalStorageSize ; ++slot) {
+      void* tls_value = stack_allocated_tls_data[slot].data;
+      if (!tls_value || tls_metadata[slot].status == TlsStatus::FREE ||
+          stack_allocated_tls_data[slot].version != tls_metadata[slot].version)
+        continue;
+
+      base::ThreadLocalStorage::TLSDestructorFunc destructor =
+          tls_metadata[slot].destructor;
+      if (!destructor)
+        continue;
+      stack_allocated_tls_data[slot].data = nullptr;  // pre-clear the slot.
+      destructor(tls_value);
+      // Any destructor might have called a different service, which then set a
+      // different slot to a non-null value. Hence we need to check the whole
+      // vector again. This is a pthread standard.
+      need_to_scan_destructors = true;
+    }
+    if (--remaining_attempts <= 0) {
+      NOTREACHED();  // Destructors might not have been called.
+      break;
+    }
+  }
+
+  // Remove our stack allocated vector.
+  PlatformThreadLocalStorage::SetTLSValue(key, kDestroyed);
+}
+
+}  // namespace
+
+namespace base {
+
+namespace internal {
+
+#if defined(OS_WIN)
+void PlatformThreadLocalStorage::OnThreadExit() {
+  PlatformThreadLocalStorage::TLSKey key =
+      base::subtle::NoBarrier_Load(&g_native_tls_key);
+  if (key == PlatformThreadLocalStorage::TLS_KEY_OUT_OF_INDEXES)
+    return;
+  void *tls_data = GetTLSValue(key);
+
+  // On Windows, thread destruction callbacks are only invoked once per module,
+  // so there should be no way that this could be invoked twice.
+  DCHECK_NE(tls_data, kDestroyed);
+
+  // Maybe we have never initialized TLS for this thread.
+  if (tls_data == kUninitialized)
+    return;
+  OnThreadExitInternal(static_cast<TlsVectorEntry*>(tls_data));
+}
+#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
+void PlatformThreadLocalStorage::OnThreadExit(void* value) {
+  OnThreadExitInternal(static_cast<TlsVectorEntry*>(value));
+}
+#endif  // defined(OS_WIN)
+
+}  // namespace internal
+
+bool ThreadLocalStorage::HasBeenDestroyed() {
+  PlatformThreadLocalStorage::TLSKey key =
+      base::subtle::NoBarrier_Load(&g_native_tls_key);
+  if (key == PlatformThreadLocalStorage::TLS_KEY_OUT_OF_INDEXES)
+    return false;
+  return PlatformThreadLocalStorage::GetTLSValue(key) == kDestroyed;
+}
+
+void ThreadLocalStorage::Slot::Initialize(TLSDestructorFunc destructor) {
+  PlatformThreadLocalStorage::TLSKey key =
+      base::subtle::NoBarrier_Load(&g_native_tls_key);
+  if (key == PlatformThreadLocalStorage::TLS_KEY_OUT_OF_INDEXES ||
+      PlatformThreadLocalStorage::GetTLSValue(key) == kUninitialized) {
+    ConstructTlsVector();
+  }
+
+  // Grab a new slot.
+  {
+    base::AutoLock auto_lock(*GetTLSMetadataLock());
+    for (int i = 0; i < kThreadLocalStorageSize; ++i) {
+      // Tracking the last assigned slot is an attempt to find the next
+      // available slot within one iteration. Under normal usage, slots remain
+      // in use for the lifetime of the process (otherwise before we reclaimed
+      // slots, we would have run out of slots). This makes it highly likely the
+      // next slot is going to be a free slot.
+      size_t slot_candidate =
+          (g_last_assigned_slot + 1 + i) % kThreadLocalStorageSize;
+      if (g_tls_metadata[slot_candidate].status == TlsStatus::FREE) {
+        g_tls_metadata[slot_candidate].status = TlsStatus::IN_USE;
+        g_tls_metadata[slot_candidate].destructor = destructor;
+        g_last_assigned_slot = slot_candidate;
+        DCHECK_EQ(kInvalidSlotValue, slot_);
+        slot_ = slot_candidate;
+        version_ = g_tls_metadata[slot_candidate].version;
+        break;
+      }
+    }
+  }
+  CHECK_NE(slot_, kInvalidSlotValue);
+  CHECK_LT(slot_, kThreadLocalStorageSize);
+}
+
+void ThreadLocalStorage::Slot::Free() {
+  DCHECK_NE(slot_, kInvalidSlotValue);
+  DCHECK_LT(slot_, kThreadLocalStorageSize);
+  {
+    base::AutoLock auto_lock(*GetTLSMetadataLock());
+    g_tls_metadata[slot_].status = TlsStatus::FREE;
+    g_tls_metadata[slot_].destructor = nullptr;
+    ++(g_tls_metadata[slot_].version);
+  }
+  slot_ = kInvalidSlotValue;
+}
+
+void* ThreadLocalStorage::Slot::Get() const {
+  TlsVectorEntry* tls_data = static_cast<TlsVectorEntry*>(
+      PlatformThreadLocalStorage::GetTLSValue(
+          base::subtle::NoBarrier_Load(&g_native_tls_key)));
+  DCHECK_NE(tls_data, kDestroyed);
+  if (!tls_data)
+    return nullptr;
+  DCHECK_NE(slot_, kInvalidSlotValue);
+  DCHECK_LT(slot_, kThreadLocalStorageSize);
+  // Version mismatches means this slot was previously freed.
+  if (tls_data[slot_].version != version_)
+    return nullptr;
+  return tls_data[slot_].data;
+}
+
+void ThreadLocalStorage::Slot::Set(void* value) {
+  TlsVectorEntry* tls_data = static_cast<TlsVectorEntry*>(
+      PlatformThreadLocalStorage::GetTLSValue(
+          base::subtle::NoBarrier_Load(&g_native_tls_key)));
+  DCHECK_NE(tls_data, kDestroyed);
+  if (!tls_data)
+    tls_data = ConstructTlsVector();
+  DCHECK_NE(slot_, kInvalidSlotValue);
+  DCHECK_LT(slot_, kThreadLocalStorageSize);
+  tls_data[slot_].data = value;
+  tls_data[slot_].version = version_;
+}
+
+ThreadLocalStorage::Slot::Slot(TLSDestructorFunc destructor) {
+  Initialize(destructor);
+}
+
+ThreadLocalStorage::Slot::~Slot() {
+  Free();
+}
+
+}  // namespace base
diff --git a/base/threading/thread_local_storage.h b/base/threading/thread_local_storage.h
new file mode 100644
index 0000000..f84ac33
--- /dev/null
+++ b/base/threading/thread_local_storage.h
@@ -0,0 +1,167 @@
+// 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.
+
+#ifndef BASE_THREADING_THREAD_LOCAL_STORAGE_H_
+#define BASE_THREADING_THREAD_LOCAL_STORAGE_H_
+
+#include <stdint.h>
+
+#include "base/atomicops.h"
+#include "base/base_export.h"
+#include "base/macros.h"
+#include "build/build_config.h"
+
+#if defined(OS_WIN)
+#include "base/win/windows_types.h"
+#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
+#include <pthread.h>
+#endif
+
+namespace heap_profiling {
+class ScopedAllowLogging;
+}  // namespace heap_profiling
+
+namespace base {
+
+class SamplingHeapProfiler;
+
+namespace trace_event {
+class MallocDumpProvider;
+}  // namespace trace_event
+
+namespace internal {
+
+class ThreadLocalStorageTestInternal;
+
+// WARNING: You should *NOT* use this class directly.
+// PlatformThreadLocalStorage is a low-level abstraction of the OS's TLS
+// interface. Instead, you should use one of the following:
+// * ThreadLocalBoolean (from thread_local.h) for booleans.
+// * ThreadLocalPointer (from thread_local.h) for pointers.
+// * ThreadLocalStorage::StaticSlot/Slot for more direct control of the slot.
+class BASE_EXPORT PlatformThreadLocalStorage {
+ public:
+
+#if defined(OS_WIN)
+  typedef unsigned long TLSKey;
+  enum : unsigned { TLS_KEY_OUT_OF_INDEXES = TLS_OUT_OF_INDEXES };
+#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
+  typedef pthread_key_t TLSKey;
+  // The following is a "reserved key" which is used in our generic Chromium
+  // ThreadLocalStorage implementation.  We expect that an OS will not return
+  // such a key, but if it is returned (i.e., the OS tries to allocate it) we
+  // will just request another key.
+  enum { TLS_KEY_OUT_OF_INDEXES = 0x7FFFFFFF };
+#endif
+
+  // The following methods need to be supported on each OS platform, so that
+  // the Chromium ThreadLocalStore functionality can be constructed.
+  // Chromium will use these methods to acquire a single OS slot, and then use
+  // that to support a much larger number of Chromium slots (independent of the
+  // OS restrictions).
+  // The following returns true if it successfully is able to return an OS
+  // key in |key|.
+  static bool AllocTLS(TLSKey* key);
+  // Note: FreeTLS() doesn't have to be called, it is fine with this leak, OS
+  // might not reuse released slot, you might just reset the TLS value with
+  // SetTLSValue().
+  static void FreeTLS(TLSKey key);
+  static void SetTLSValue(TLSKey key, void* value);
+  static void* GetTLSValue(TLSKey key) {
+#if defined(OS_WIN)
+    return TlsGetValue(key);
+#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
+    return pthread_getspecific(key);
+#endif
+  }
+
+  // Each platform (OS implementation) is required to call this method on each
+  // terminating thread when the thread is about to terminate.  This method
+  // will then call all registered destructors for slots in Chromium
+  // ThreadLocalStorage, until there are no slot values remaining as having
+  // been set on this thread.
+  // Destructors may end up being called multiple times on a terminating
+  // thread, as other destructors may re-set slots that were previously
+  // destroyed.
+#if defined(OS_WIN)
+  // Since Windows which doesn't support TLS destructor, the implementation
+  // should use GetTLSValue() to retrieve the value of TLS slot.
+  static void OnThreadExit();
+#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
+  // |Value| is the data stored in TLS slot, The implementation can't use
+  // GetTLSValue() to retrieve the value of slot as it has already been reset
+  // in Posix.
+  static void OnThreadExit(void* value);
+#endif
+};
+
+}  // namespace internal
+
+// Wrapper for thread local storage.  This class doesn't do much except provide
+// an API for portability.
+class BASE_EXPORT ThreadLocalStorage {
+ public:
+  // Prototype for the TLS destructor function, which can be optionally used to
+  // cleanup thread local storage on thread exit.  'value' is the data that is
+  // stored in thread local storage.
+  typedef void (*TLSDestructorFunc)(void* value);
+
+  // A key representing one value stored in TLS. Use as a class member or a
+  // local variable. If you need a static storage duration variable, use the
+  // following pattern with a NoDestructor<Slot>:
+  // void MyDestructorFunc(void* value);
+  // ThreadLocalStorage::Slot& ImportantContentTLS() {
+  //   static NoDestructor<ThreadLocalStorage::Slot> important_content_tls(
+  //       &MyDestructorFunc);
+  //   return *important_content_tls;
+  // }
+  class BASE_EXPORT Slot final {
+   public:
+    // |destructor| is a pointer to a function to perform per-thread cleanup of
+    // this object.  If set to nullptr, no cleanup is done for this TLS slot.
+    explicit Slot(TLSDestructorFunc destructor = nullptr);
+    // If a destructor was set for this slot, removes the destructor so that
+    // remaining threads exiting will not free data.
+    ~Slot();
+
+    // Get the thread-local value stored in slot 'slot'.
+    // Values are guaranteed to initially be zero.
+    void* Get() const;
+
+    // Set the thread-local value stored in slot 'slot' to
+    // value 'value'.
+    void Set(void* value);
+
+   private:
+    void Initialize(TLSDestructorFunc destructor);
+    void Free();
+
+    static constexpr int kInvalidSlotValue = -1;
+    int slot_ = kInvalidSlotValue;
+    uint32_t version_ = 0;
+
+    DISALLOW_COPY_AND_ASSIGN(Slot);
+  };
+
+ private:
+  // In most cases, most callers should not need access to HasBeenDestroyed().
+  // If you are working in code that runs during thread destruction, contact the
+  // base OWNERs for advice and then make a friend request.
+  //
+  // Returns |true| if Chrome's implementation of TLS has been destroyed during
+  // thread destruction. Attempting to call Slot::Get() during destruction is
+  // disallowed and will hit a DCHECK. Any code that relies on TLS during thread
+  // destruction must first check this method before calling Slot::Get().
+  friend class base::SamplingHeapProfiler;
+  friend class base::internal::ThreadLocalStorageTestInternal;
+  friend class base::trace_event::MallocDumpProvider;
+  friend class heap_profiling::ScopedAllowLogging;
+  static bool HasBeenDestroyed();
+
+  DISALLOW_COPY_AND_ASSIGN(ThreadLocalStorage);
+};
+
+}  // namespace base
+
+#endif  // BASE_THREADING_THREAD_LOCAL_STORAGE_H_
diff --git a/base/threading/thread_local_storage_posix.cc b/base/threading/thread_local_storage_posix.cc
new file mode 100644
index 0000000..89edeee
--- /dev/null
+++ b/base/threading/thread_local_storage_posix.cc
@@ -0,0 +1,30 @@
+// 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 "base/threading/thread_local_storage.h"
+
+#include "base/logging.h"
+
+namespace base {
+
+namespace internal {
+
+bool PlatformThreadLocalStorage::AllocTLS(TLSKey* key) {
+  return !pthread_key_create(key,
+      base::internal::PlatformThreadLocalStorage::OnThreadExit);
+}
+
+void PlatformThreadLocalStorage::FreeTLS(TLSKey key) {
+  int ret = pthread_key_delete(key);
+  DCHECK_EQ(ret, 0);
+}
+
+void PlatformThreadLocalStorage::SetTLSValue(TLSKey key, void* value) {
+  int ret = pthread_setspecific(key, value);
+  DCHECK_EQ(ret, 0);
+}
+
+}  // namespace internal
+
+}  // namespace base
diff --git a/base/threading/thread_local_storage_unittest.cc b/base/threading/thread_local_storage_unittest.cc
new file mode 100644
index 0000000..9062ff0
--- /dev/null
+++ b/base/threading/thread_local_storage_unittest.cc
@@ -0,0 +1,278 @@
+// 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 "base/threading/thread_local_storage.h"
+
+#if defined(OS_WIN)
+#include <windows.h>
+#include <process.h>
+#endif
+
+#include "base/macros.h"
+#include "base/no_destructor.h"
+#include "base/threading/simple_thread.h"
+#include "build/build_config.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#if defined(OS_WIN)
+// Ignore warnings about ptr->int conversions that we use when
+// storing ints into ThreadLocalStorage.
+#pragma warning(disable : 4311 4312)
+#endif
+
+namespace base {
+
+#if defined(OS_POSIX)
+
+namespace internal {
+
+// This class is friended by ThreadLocalStorage.
+class ThreadLocalStorageTestInternal {
+ public:
+  static bool HasBeenDestroyed() {
+    return ThreadLocalStorage::HasBeenDestroyed();
+  }
+};
+
+}  // namespace internal
+
+#endif  // defined(OS_POSIX)
+
+namespace {
+
+const int kInitialTlsValue = 0x5555;
+const int kFinalTlsValue = 0x7777;
+// How many times must a destructor be called before we really are done.
+const int kNumberDestructorCallRepetitions = 3;
+
+void ThreadLocalStorageCleanup(void* value);
+
+ThreadLocalStorage::Slot& TLSSlot() {
+  static NoDestructor<ThreadLocalStorage::Slot> slot(
+      &ThreadLocalStorageCleanup);
+  return *slot;
+}
+
+class ThreadLocalStorageRunner : public DelegateSimpleThread::Delegate {
+ public:
+  explicit ThreadLocalStorageRunner(int* tls_value_ptr)
+      : tls_value_ptr_(tls_value_ptr) {}
+
+  ~ThreadLocalStorageRunner() override = default;
+
+  void Run() override {
+    *tls_value_ptr_ = kInitialTlsValue;
+    TLSSlot().Set(tls_value_ptr_);
+
+    int* ptr = static_cast<int*>(TLSSlot().Get());
+    EXPECT_EQ(ptr, tls_value_ptr_);
+    EXPECT_EQ(*ptr, kInitialTlsValue);
+    *tls_value_ptr_ = 0;
+
+    ptr = static_cast<int*>(TLSSlot().Get());
+    EXPECT_EQ(ptr, tls_value_ptr_);
+    EXPECT_EQ(*ptr, 0);
+
+    *ptr = kFinalTlsValue + kNumberDestructorCallRepetitions;
+  }
+
+ private:
+  int* tls_value_ptr_;
+  DISALLOW_COPY_AND_ASSIGN(ThreadLocalStorageRunner);
+};
+
+
+void ThreadLocalStorageCleanup(void *value) {
+  int *ptr = reinterpret_cast<int*>(value);
+  // Destructors should never be called with a NULL.
+  ASSERT_NE(reinterpret_cast<int*>(NULL), ptr);
+  if (*ptr == kFinalTlsValue)
+    return;  // We've been called enough times.
+  ASSERT_LT(kFinalTlsValue, *ptr);
+  ASSERT_GE(kFinalTlsValue + kNumberDestructorCallRepetitions, *ptr);
+  --*ptr;  // Move closer to our target.
+  // Tell tls that we're not done with this thread, and still need destruction.
+  TLSSlot().Set(value);
+}
+
+#if defined(OS_POSIX)
+constexpr intptr_t kDummyValue = 0xABCD;
+constexpr size_t kKeyCount = 20;
+
+// The order in which pthread keys are destructed is not specified by the POSIX
+// specification. Hopefully, of the 20 keys we create, some of them should be
+// destroyed after the TLS key is destroyed.
+class UseTLSDuringDestructionRunner {
+ public:
+  UseTLSDuringDestructionRunner() = default;
+
+  // The order in which pthread_key destructors are called is not well defined.
+  // Hopefully, by creating 10 both before and after initializing TLS on the
+  // thread, at least 1 will be called after TLS destruction.
+  void Run() {
+    ASSERT_FALSE(internal::ThreadLocalStorageTestInternal::HasBeenDestroyed());
+
+    // Create 10 pthread keys before initializing TLS on the thread.
+    size_t slot_index = 0;
+    for (; slot_index < 10; ++slot_index) {
+      CreateTlsKeyWithDestructor(slot_index);
+    }
+
+    // Initialize the Chrome TLS system. It's possible that base::Thread has
+    // already initialized Chrome TLS, but we don't rely on that.
+    slot_.Set(reinterpret_cast<void*>(kDummyValue));
+
+    // Create 10 pthread keys after initializing TLS on the thread.
+    for (; slot_index < kKeyCount; ++slot_index) {
+      CreateTlsKeyWithDestructor(slot_index);
+    }
+  }
+
+  bool teardown_works_correctly() { return teardown_works_correctly_; }
+
+ private:
+  struct TLSState {
+    pthread_key_t key;
+    bool* teardown_works_correctly;
+  };
+
+  // The POSIX TLS destruction API takes as input a single C-function, which is
+  // called with the current |value| of a (key, value) pair. We need this
+  // function to do two things: set the |value| to nullptr, which requires
+  // knowing the associated |key|, and update the |teardown_works_correctly_|
+  // state.
+  //
+  // To accomplish this, we set the value to an instance of TLSState, which
+  // contains |key| as well as a pointer to |teardown_works_correctly|.
+  static void ThreadLocalDestructor(void* value) {
+    TLSState* state = static_cast<TLSState*>(value);
+    int result = pthread_setspecific(state->key, nullptr);
+    ASSERT_EQ(result, 0);
+
+    // If this path is hit, then the thread local destructor was called after
+    // the Chrome-TLS destructor and the internal state was updated correctly.
+    // No further checks are necessary.
+    if (internal::ThreadLocalStorageTestInternal::HasBeenDestroyed()) {
+      *(state->teardown_works_correctly) = true;
+      return;
+    }
+
+    // If this path is hit, then the thread local destructor was called before
+    // the Chrome-TLS destructor is hit. The ThreadLocalStorage::Slot should
+    // still function correctly.
+    ASSERT_EQ(reinterpret_cast<intptr_t>(slot_.Get()), kDummyValue);
+  }
+
+  void CreateTlsKeyWithDestructor(size_t index) {
+    ASSERT_LT(index, kKeyCount);
+
+    tls_states_[index].teardown_works_correctly = &teardown_works_correctly_;
+    int result = pthread_key_create(
+        &(tls_states_[index].key),
+        UseTLSDuringDestructionRunner::ThreadLocalDestructor);
+    ASSERT_EQ(result, 0);
+
+    result = pthread_setspecific(tls_states_[index].key, &tls_states_[index]);
+    ASSERT_EQ(result, 0);
+  }
+
+  static base::ThreadLocalStorage::Slot slot_;
+  bool teardown_works_correctly_ = false;
+  TLSState tls_states_[kKeyCount];
+
+  DISALLOW_COPY_AND_ASSIGN(UseTLSDuringDestructionRunner);
+};
+
+base::ThreadLocalStorage::Slot UseTLSDuringDestructionRunner::slot_;
+
+void* UseTLSTestThreadRun(void* input) {
+  UseTLSDuringDestructionRunner* runner =
+      static_cast<UseTLSDuringDestructionRunner*>(input);
+  runner->Run();
+  return nullptr;
+}
+
+#endif  // defined(OS_POSIX)
+
+}  // namespace
+
+TEST(ThreadLocalStorageTest, Basics) {
+  ThreadLocalStorage::Slot slot;
+  slot.Set(reinterpret_cast<void*>(123));
+  int value = reinterpret_cast<intptr_t>(slot.Get());
+  EXPECT_EQ(value, 123);
+}
+
+#if defined(THREAD_SANITIZER) || \
+    (defined(OS_WIN) && defined(ARCH_CPU_X86_64) && !defined(NDEBUG))
+// Do not run the test under ThreadSanitizer. Because this test iterates its
+// own TSD destructor for the maximum possible number of times, TSan can't jump
+// in after the last destructor invocation, therefore the destructor remains
+// unsynchronized with the following users of the same TSD slot. This results
+// in race reports between the destructor and functions in other tests.
+//
+// It is disabled on Win x64 with incremental linking (i.e. "Debug") pending
+// resolution of http://crbug.com/251251.
+#define MAYBE_TLSDestructors DISABLED_TLSDestructors
+#else
+#define MAYBE_TLSDestructors TLSDestructors
+#endif
+TEST(ThreadLocalStorageTest, MAYBE_TLSDestructors) {
+  // Create a TLS index with a destructor.  Create a set of
+  // threads that set the TLS, while the destructor cleans it up.
+  // After the threads finish, verify that the value is cleaned up.
+  const int kNumThreads = 5;
+  int values[kNumThreads];
+  ThreadLocalStorageRunner* thread_delegates[kNumThreads];
+  DelegateSimpleThread* threads[kNumThreads];
+
+  // Spawn the threads.
+  for (int index = 0; index < kNumThreads; index++) {
+    values[index] = kInitialTlsValue;
+    thread_delegates[index] = new ThreadLocalStorageRunner(&values[index]);
+    threads[index] = new DelegateSimpleThread(thread_delegates[index],
+                                              "tls thread");
+    threads[index]->Start();
+  }
+
+  // Wait for the threads to finish.
+  for (int index = 0; index < kNumThreads; index++) {
+    threads[index]->Join();
+    delete threads[index];
+    delete thread_delegates[index];
+
+    // Verify that the destructor was called and that we reset.
+    EXPECT_EQ(values[index], kFinalTlsValue);
+  }
+}
+
+TEST(ThreadLocalStorageTest, TLSReclaim) {
+  // Creates and destroys many TLS slots and ensures they all zero-inited.
+  for (int i = 0; i < 1000; ++i) {
+    ThreadLocalStorage::Slot slot(nullptr);
+    EXPECT_EQ(nullptr, slot.Get());
+    slot.Set(reinterpret_cast<void*>(0xBAADF00D));
+    EXPECT_EQ(reinterpret_cast<void*>(0xBAADF00D), slot.Get());
+  }
+}
+
+#if defined(OS_POSIX)
+// Unlike POSIX, Windows does not iterate through the OS TLS to cleanup any
+// values there. Instead a per-module thread destruction function is called.
+// However, it is not possible to perform a check after this point (as the code
+// is detached from the thread), so this check remains POSIX only.
+TEST(ThreadLocalStorageTest, UseTLSDuringDestruction) {
+  UseTLSDuringDestructionRunner runner;
+  pthread_t thread;
+  int result = pthread_create(&thread, nullptr, UseTLSTestThreadRun, &runner);
+  ASSERT_EQ(result, 0);
+
+  result = pthread_join(thread, nullptr);
+  ASSERT_EQ(result, 0);
+
+  EXPECT_TRUE(runner.teardown_works_correctly());
+}
+#endif  // defined(OS_POSIX)
+
+}  // namespace base
diff --git a/base/threading/thread_local_storage_win.cc b/base/threading/thread_local_storage_win.cc
new file mode 100644
index 0000000..a9aec31
--- /dev/null
+++ b/base/threading/thread_local_storage_win.cc
@@ -0,0 +1,107 @@
+// 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 "base/threading/thread_local_storage.h"
+
+#include <windows.h>
+
+#include "base/logging.h"
+
+namespace base {
+
+namespace internal {
+
+bool PlatformThreadLocalStorage::AllocTLS(TLSKey* key) {
+  TLSKey value = TlsAlloc();
+  if (value != TLS_OUT_OF_INDEXES) {
+    *key = value;
+    return true;
+  }
+  return false;
+}
+
+void PlatformThreadLocalStorage::FreeTLS(TLSKey key) {
+  BOOL ret = TlsFree(key);
+  DCHECK(ret);
+}
+
+void PlatformThreadLocalStorage::SetTLSValue(TLSKey key, void* value) {
+  BOOL ret = TlsSetValue(key, value);
+  DCHECK(ret);
+}
+
+}  // namespace internal
+
+}  // namespace base
+
+// Thread Termination Callbacks.
+// Windows doesn't support a per-thread destructor with its
+// TLS primitives.  So, we build it manually by inserting a
+// function to be called on each thread's exit.
+// This magic is from http://www.codeproject.com/threads/tls.asp
+// and it works for VC++ 7.0 and later.
+
+// Force a reference to _tls_used to make the linker create the TLS directory
+// if it's not already there.  (e.g. if __declspec(thread) is not used).
+// Force a reference to p_thread_callback_base to prevent whole program
+// optimization from discarding the variable.
+#ifdef _WIN64
+
+#pragma comment(linker, "/INCLUDE:_tls_used")
+#pragma comment(linker, "/INCLUDE:p_thread_callback_base")
+
+#else  // _WIN64
+
+#pragma comment(linker, "/INCLUDE:__tls_used")
+#pragma comment(linker, "/INCLUDE:_p_thread_callback_base")
+
+#endif  // _WIN64
+
+// Static callback function to call with each thread termination.
+void NTAPI OnThreadExit(PVOID module, DWORD reason, PVOID reserved) {
+  // On XP SP0 & SP1, the DLL_PROCESS_ATTACH is never seen. It is sent on SP2+
+  // and on W2K and W2K3. So don't assume it is sent.
+  if (DLL_THREAD_DETACH == reason || DLL_PROCESS_DETACH == reason)
+    base::internal::PlatformThreadLocalStorage::OnThreadExit();
+}
+
+// .CRT$XLA to .CRT$XLZ is an array of PIMAGE_TLS_CALLBACK pointers that are
+// called automatically by the OS loader code (not the CRT) when the module is
+// loaded and on thread creation. They are NOT called if the module has been
+// loaded by a LoadLibrary() call. It must have implicitly been loaded at
+// process startup.
+// By implicitly loaded, I mean that it is directly referenced by the main EXE
+// or by one of its dependent DLLs. Delay-loaded DLL doesn't count as being
+// implicitly loaded.
+//
+// See VC\crt\src\tlssup.c for reference.
+
+// extern "C" suppresses C++ name mangling so we know the symbol name for the
+// linker /INCLUDE:symbol pragma above.
+extern "C" {
+// The linker must not discard p_thread_callback_base.  (We force a reference
+// to this variable with a linker /INCLUDE:symbol pragma to ensure that.) If
+// this variable is discarded, the OnThreadExit function will never be called.
+#ifdef _WIN64
+
+// .CRT section is merged with .rdata on x64 so it must be constant data.
+#pragma const_seg(".CRT$XLB")
+// When defining a const variable, it must have external linkage to be sure the
+// linker doesn't discard it.
+extern const PIMAGE_TLS_CALLBACK p_thread_callback_base;
+const PIMAGE_TLS_CALLBACK p_thread_callback_base = OnThreadExit;
+
+// Reset the default section.
+#pragma const_seg()
+
+#else  // _WIN64
+
+#pragma data_seg(".CRT$XLB")
+PIMAGE_TLS_CALLBACK p_thread_callback_base = OnThreadExit;
+
+// Reset the default section.
+#pragma data_seg()
+
+#endif  // _WIN64
+}  // extern "C"
diff --git a/base/threading/thread_local_unittest.cc b/base/threading/thread_local_unittest.cc
new file mode 100644
index 0000000..54f2ad2
--- /dev/null
+++ b/base/threading/thread_local_unittest.cc
@@ -0,0 +1,164 @@
+// 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 "base/logging.h"
+#include "base/threading/simple_thread.h"
+#include "base/threading/thread_local.h"
+#include "base/synchronization/waitable_event.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+
+namespace {
+
+class ThreadLocalTesterBase : public base::DelegateSimpleThreadPool::Delegate {
+ public:
+  typedef base::ThreadLocalPointer<char> TLPType;
+
+  ThreadLocalTesterBase(TLPType* tlp, base::WaitableEvent* done)
+      : tlp_(tlp),
+        done_(done) {
+  }
+  ~ThreadLocalTesterBase() override = default;
+
+ protected:
+  TLPType* tlp_;
+  base::WaitableEvent* done_;
+};
+
+class SetThreadLocal : public ThreadLocalTesterBase {
+ public:
+  SetThreadLocal(TLPType* tlp, base::WaitableEvent* done)
+      : ThreadLocalTesterBase(tlp, done), val_(nullptr) {}
+  ~SetThreadLocal() override = default;
+
+  void set_value(char* val) { val_ = val; }
+
+  void Run() override {
+    DCHECK(!done_->IsSignaled());
+    tlp_->Set(val_);
+    done_->Signal();
+  }
+
+ private:
+  char* val_;
+};
+
+class GetThreadLocal : public ThreadLocalTesterBase {
+ public:
+  GetThreadLocal(TLPType* tlp, base::WaitableEvent* done)
+      : ThreadLocalTesterBase(tlp, done), ptr_(nullptr) {}
+  ~GetThreadLocal() override = default;
+
+  void set_ptr(char** ptr) { ptr_ = ptr; }
+
+  void Run() override {
+    DCHECK(!done_->IsSignaled());
+    *ptr_ = tlp_->Get();
+    done_->Signal();
+  }
+
+ private:
+  char** ptr_;
+};
+
+}  // namespace
+
+// In this test, we start 2 threads which will access a ThreadLocalPointer.  We
+// make sure the default is NULL, and the pointers are unique to the threads.
+TEST(ThreadLocalTest, Pointer) {
+  base::DelegateSimpleThreadPool tp1("ThreadLocalTest tp1", 1);
+  base::DelegateSimpleThreadPool tp2("ThreadLocalTest tp1", 1);
+  tp1.Start();
+  tp2.Start();
+
+  base::ThreadLocalPointer<char> tlp;
+
+  static char* const kBogusPointer = reinterpret_cast<char*>(0x1234);
+
+  char* tls_val;
+  base::WaitableEvent done(WaitableEvent::ResetPolicy::MANUAL,
+                           WaitableEvent::InitialState::NOT_SIGNALED);
+
+  GetThreadLocal getter(&tlp, &done);
+  getter.set_ptr(&tls_val);
+
+  // Check that both threads defaulted to NULL.
+  tls_val = kBogusPointer;
+  done.Reset();
+  tp1.AddWork(&getter);
+  done.Wait();
+  EXPECT_EQ(static_cast<char*>(nullptr), tls_val);
+
+  tls_val = kBogusPointer;
+  done.Reset();
+  tp2.AddWork(&getter);
+  done.Wait();
+  EXPECT_EQ(static_cast<char*>(nullptr), tls_val);
+
+  SetThreadLocal setter(&tlp, &done);
+  setter.set_value(kBogusPointer);
+
+  // Have thread 1 set their pointer value to kBogusPointer.
+  done.Reset();
+  tp1.AddWork(&setter);
+  done.Wait();
+
+  tls_val = nullptr;
+  done.Reset();
+  tp1.AddWork(&getter);
+  done.Wait();
+  EXPECT_EQ(kBogusPointer, tls_val);
+
+  // Make sure thread 2 is still NULL
+  tls_val = kBogusPointer;
+  done.Reset();
+  tp2.AddWork(&getter);
+  done.Wait();
+  EXPECT_EQ(static_cast<char*>(nullptr), tls_val);
+
+  // Set thread 2 to kBogusPointer + 1.
+  setter.set_value(kBogusPointer + 1);
+
+  done.Reset();
+  tp2.AddWork(&setter);
+  done.Wait();
+
+  tls_val = nullptr;
+  done.Reset();
+  tp2.AddWork(&getter);
+  done.Wait();
+  EXPECT_EQ(kBogusPointer + 1, tls_val);
+
+  // Make sure thread 1 is still kBogusPointer.
+  tls_val = nullptr;
+  done.Reset();
+  tp1.AddWork(&getter);
+  done.Wait();
+  EXPECT_EQ(kBogusPointer, tls_val);
+
+  tp1.JoinAll();
+  tp2.JoinAll();
+}
+
+TEST(ThreadLocalTest, Boolean) {
+  {
+    base::ThreadLocalBoolean tlb;
+    EXPECT_FALSE(tlb.Get());
+
+    tlb.Set(false);
+    EXPECT_FALSE(tlb.Get());
+
+    tlb.Set(true);
+    EXPECT_TRUE(tlb.Get());
+  }
+
+  // Our slot should have been freed, we're all reset.
+  {
+    base::ThreadLocalBoolean tlb;
+    EXPECT_FALSE(tlb.Get());
+  }
+}
+
+}  // namespace base
diff --git a/base/threading/thread_perftest.cc b/base/threading/thread_perftest.cc
new file mode 100644
index 0000000..bf89049
--- /dev/null
+++ b/base/threading/thread_perftest.cc
@@ -0,0 +1,318 @@
+// Copyright 2014 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 <stddef.h>
+
+#include <memory>
+#include <vector>
+
+#include "base/base_switches.h"
+#include "base/bind.h"
+#include "base/command_line.h"
+#include "base/location.h"
+#include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
+#include "base/single_thread_task_runner.h"
+#include "base/strings/stringprintf.h"
+#include "base/synchronization/condition_variable.h"
+#include "base/synchronization/lock.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/threading/thread.h"
+#include "base/time/time.h"
+#include "build/build_config.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/perf/perf_test.h"
+
+#if defined(OS_POSIX)
+#include <pthread.h>
+#endif
+
+namespace base {
+
+namespace {
+
+const int kNumRuns = 100000;
+
+// Base class for a threading perf-test. This sets up some threads for the
+// test and measures the clock-time in addition to time spent on each thread.
+class ThreadPerfTest : public testing::Test {
+ public:
+  ThreadPerfTest()
+      : done_(WaitableEvent::ResetPolicy::AUTOMATIC,
+              WaitableEvent::InitialState::NOT_SIGNALED) {}
+
+  // To be implemented by each test. Subclass must uses threads_ such that
+  // their cpu-time can be measured. Test must return from PingPong() _and_
+  // call FinishMeasurement from any thread to complete the test.
+  virtual void Init() {
+    if (ThreadTicks::IsSupported())
+      ThreadTicks::WaitUntilInitialized();
+  }
+  virtual void PingPong(int hops) = 0;
+  virtual void Reset() {}
+
+  void TimeOnThread(base::ThreadTicks* ticks, base::WaitableEvent* done) {
+    *ticks = base::ThreadTicks::Now();
+    done->Signal();
+  }
+
+  base::ThreadTicks ThreadNow(const base::Thread& thread) {
+    base::WaitableEvent done(WaitableEvent::ResetPolicy::AUTOMATIC,
+                             WaitableEvent::InitialState::NOT_SIGNALED);
+    base::ThreadTicks ticks;
+    thread.task_runner()->PostTask(
+        FROM_HERE, base::BindOnce(&ThreadPerfTest::TimeOnThread,
+                                  base::Unretained(this), &ticks, &done));
+    done.Wait();
+    return ticks;
+  }
+
+  void RunPingPongTest(const std::string& name, unsigned num_threads) {
+    // Create threads and collect starting cpu-time for each thread.
+    std::vector<base::ThreadTicks> thread_starts;
+    while (threads_.size() < num_threads) {
+      threads_.push_back(std::make_unique<base::Thread>("PingPonger"));
+      threads_.back()->Start();
+      if (base::ThreadTicks::IsSupported())
+        thread_starts.push_back(ThreadNow(*threads_.back()));
+    }
+
+    Init();
+
+    base::TimeTicks start = base::TimeTicks::Now();
+    PingPong(kNumRuns);
+    done_.Wait();
+    base::TimeTicks end = base::TimeTicks::Now();
+
+    // Gather the cpu-time spent on each thread. This does one extra tasks,
+    // but that should be in the noise given enough runs.
+    base::TimeDelta thread_time;
+    while (threads_.size()) {
+      if (base::ThreadTicks::IsSupported()) {
+        thread_time += ThreadNow(*threads_.back()) - thread_starts.back();
+        thread_starts.pop_back();
+      }
+      threads_.pop_back();
+    }
+
+    Reset();
+
+    double num_runs = static_cast<double>(kNumRuns);
+    double us_per_task_clock = (end - start).InMicroseconds() / num_runs;
+    double us_per_task_cpu = thread_time.InMicroseconds() / num_runs;
+
+    // Clock time per task.
+    perf_test::PrintResult(
+        "task", "", name + "_time ", us_per_task_clock, "us/hop", true);
+
+    // Total utilization across threads if available (likely higher).
+    if (base::ThreadTicks::IsSupported()) {
+      perf_test::PrintResult(
+          "task", "", name + "_cpu ", us_per_task_cpu, "us/hop", true);
+    }
+  }
+
+ protected:
+  void FinishMeasurement() { done_.Signal(); }
+  std::vector<std::unique_ptr<base::Thread>> threads_;
+
+ private:
+  base::WaitableEvent done_;
+};
+
+// Class to test task performance by posting empty tasks back and forth.
+class TaskPerfTest : public ThreadPerfTest {
+  base::Thread* NextThread(int count) {
+    return threads_[count % threads_.size()].get();
+  }
+
+  void PingPong(int hops) override {
+    if (!hops) {
+      FinishMeasurement();
+      return;
+    }
+    NextThread(hops)->task_runner()->PostTask(
+        FROM_HERE, base::BindOnce(&ThreadPerfTest::PingPong,
+                                  base::Unretained(this), hops - 1));
+  }
+};
+
+// This tries to test the 'best-case' as well as the 'worst-case' task posting
+// performance. The best-case keeps one thread alive such that it never yeilds,
+// while the worse-case forces a context switch for every task. Four threads are
+// used to ensure the threads do yeild (with just two it might be possible for
+// both threads to stay awake if they can signal each other fast enough).
+TEST_F(TaskPerfTest, TaskPingPong) {
+  RunPingPongTest("1_Task_Threads", 1);
+  RunPingPongTest("4_Task_Threads", 4);
+}
+
+
+// Same as above, but add observers to test their perf impact.
+class MessageLoopObserver : public base::MessageLoop::TaskObserver {
+ public:
+  void WillProcessTask(const base::PendingTask& pending_task) override {}
+  void DidProcessTask(const base::PendingTask& pending_task) override {}
+};
+MessageLoopObserver message_loop_observer;
+
+class TaskObserverPerfTest : public TaskPerfTest {
+ public:
+  void Init() override {
+    TaskPerfTest::Init();
+    for (size_t i = 0; i < threads_.size(); i++) {
+      threads_[i]->message_loop()->AddTaskObserver(&message_loop_observer);
+    }
+  }
+};
+
+TEST_F(TaskObserverPerfTest, TaskPingPong) {
+  RunPingPongTest("1_Task_Threads_With_Observer", 1);
+  RunPingPongTest("4_Task_Threads_With_Observer", 4);
+}
+
+// Class to test our WaitableEvent performance by signaling back and fort.
+// WaitableEvent is templated so we can also compare with other versions.
+template <typename WaitableEventType>
+class EventPerfTest : public ThreadPerfTest {
+ public:
+  void Init() override {
+    for (size_t i = 0; i < threads_.size(); i++) {
+      events_.push_back(std::make_unique<WaitableEventType>(
+          WaitableEvent::ResetPolicy::AUTOMATIC,
+          WaitableEvent::InitialState::NOT_SIGNALED));
+    }
+  }
+
+  void Reset() override { events_.clear(); }
+
+  void WaitAndSignalOnThread(size_t event) {
+    size_t next_event = (event + 1) % events_.size();
+    int my_hops = 0;
+    do {
+      events_[event]->Wait();
+      my_hops = --remaining_hops_;  // We own 'hops' between Wait and Signal.
+      events_[next_event]->Signal();
+    } while (my_hops > 0);
+    // Once we are done, all threads will signal as hops passes zero.
+    // We only signal completion once, on the thread that reaches zero.
+    if (!my_hops)
+      FinishMeasurement();
+  }
+
+  void PingPong(int hops) override {
+    remaining_hops_ = hops;
+    for (size_t i = 0; i < threads_.size(); i++) {
+      threads_[i]->task_runner()->PostTask(
+          FROM_HERE, base::BindOnce(&EventPerfTest::WaitAndSignalOnThread,
+                                    base::Unretained(this), i));
+    }
+
+    // Kick off the Signal ping-ponging.
+    events_.front()->Signal();
+  }
+
+  int remaining_hops_;
+  std::vector<std::unique_ptr<WaitableEventType>> events_;
+};
+
+// Similar to the task posting test, this just tests similar functionality
+// using WaitableEvents. We only test four threads (worst-case), but we
+// might want to craft a way to test the best-case (where the thread doesn't
+// end up blocking because the event is already signalled).
+typedef EventPerfTest<base::WaitableEvent> WaitableEventThreadPerfTest;
+TEST_F(WaitableEventThreadPerfTest, EventPingPong) {
+  RunPingPongTest("4_WaitableEvent_Threads", 4);
+}
+
+// Build a minimal event using ConditionVariable.
+class ConditionVariableEvent {
+ public:
+  ConditionVariableEvent(WaitableEvent::ResetPolicy reset_policy,
+                         WaitableEvent::InitialState initial_state)
+      : cond_(&lock_), signaled_(false) {
+    DCHECK_EQ(WaitableEvent::ResetPolicy::AUTOMATIC, reset_policy);
+    DCHECK_EQ(WaitableEvent::InitialState::NOT_SIGNALED, initial_state);
+  }
+
+  void Signal() {
+    {
+      base::AutoLock scoped_lock(lock_);
+      signaled_ = true;
+    }
+    cond_.Signal();
+  }
+
+  void Wait() {
+    base::AutoLock scoped_lock(lock_);
+    while (!signaled_)
+      cond_.Wait();
+    signaled_ = false;
+  }
+
+ private:
+  base::Lock lock_;
+  base::ConditionVariable cond_;
+  bool signaled_;
+};
+
+// This is meant to test the absolute minimal context switching time
+// using our own base synchronization code.
+typedef EventPerfTest<ConditionVariableEvent> ConditionVariablePerfTest;
+TEST_F(ConditionVariablePerfTest, EventPingPong) {
+  RunPingPongTest("4_ConditionVariable_Threads", 4);
+}
+#if defined(OS_POSIX)
+
+// Absolutely 100% minimal posix waitable event. If there is a better/faster
+// way to force a context switch, we should use that instead.
+class PthreadEvent {
+ public:
+  PthreadEvent(WaitableEvent::ResetPolicy reset_policy,
+               WaitableEvent::InitialState initial_state) {
+    DCHECK_EQ(WaitableEvent::ResetPolicy::AUTOMATIC, reset_policy);
+    DCHECK_EQ(WaitableEvent::InitialState::NOT_SIGNALED, initial_state);
+    pthread_mutex_init(&mutex_, nullptr);
+    pthread_cond_init(&cond_, nullptr);
+    signaled_ = false;
+  }
+
+  ~PthreadEvent() {
+    pthread_cond_destroy(&cond_);
+    pthread_mutex_destroy(&mutex_);
+  }
+
+  void Signal() {
+    pthread_mutex_lock(&mutex_);
+    signaled_ = true;
+    pthread_mutex_unlock(&mutex_);
+    pthread_cond_signal(&cond_);
+  }
+
+  void Wait() {
+    pthread_mutex_lock(&mutex_);
+    while (!signaled_)
+      pthread_cond_wait(&cond_, &mutex_);
+    signaled_ = false;
+    pthread_mutex_unlock(&mutex_);
+  }
+
+ private:
+  bool signaled_;
+  pthread_mutex_t mutex_;
+  pthread_cond_t cond_;
+};
+
+// This is meant to test the absolute minimal context switching time.
+// If there is any faster way to do this we should substitute it in.
+typedef EventPerfTest<PthreadEvent> PthreadEventPerfTest;
+TEST_F(PthreadEventPerfTest, EventPingPong) {
+  RunPingPongTest("4_PthreadCondVar_Threads", 4);
+}
+
+#endif
+
+}  // namespace
+
+}  // namespace base
diff --git a/base/threading/thread_restrictions.cc b/base/threading/thread_restrictions.cc
new file mode 100644
index 0000000..633bcb2
--- /dev/null
+++ b/base/threading/thread_restrictions.cc
@@ -0,0 +1,176 @@
+// 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 "base/threading/thread_restrictions.h"
+
+#if DCHECK_IS_ON()
+
+#include "base/lazy_instance.h"
+#include "base/logging.h"
+#include "base/threading/thread_local.h"
+
+namespace base {
+
+namespace {
+
+LazyInstance<ThreadLocalBoolean>::Leaky g_blocking_disallowed =
+    LAZY_INSTANCE_INITIALIZER;
+
+LazyInstance<ThreadLocalBoolean>::Leaky
+    g_singleton_disallowed = LAZY_INSTANCE_INITIALIZER;
+
+LazyInstance<ThreadLocalBoolean>::Leaky g_base_sync_primitives_disallowed =
+    LAZY_INSTANCE_INITIALIZER;
+
+}  // namespace
+
+void AssertBlockingAllowed() {
+  DCHECK(!g_blocking_disallowed.Get().Get())
+      << "Function marked as blocking was called from a scope that disallows "
+         "blocking! If this task is running inside the TaskScheduler, it needs "
+         "to have MayBlock() in its TaskTraits. Otherwise, consider making "
+         "this blocking work asynchronous or, as a last resort, you may use "
+         "ScopedAllowBlocking in a narrow scope.";
+}
+
+void DisallowBlocking() {
+  g_blocking_disallowed.Get().Set(true);
+}
+
+ScopedDisallowBlocking::ScopedDisallowBlocking()
+    : was_disallowed_(g_blocking_disallowed.Get().Get()) {
+  g_blocking_disallowed.Get().Set(true);
+}
+
+ScopedDisallowBlocking::~ScopedDisallowBlocking() {
+  DCHECK(g_blocking_disallowed.Get().Get());
+  g_blocking_disallowed.Get().Set(was_disallowed_);
+}
+
+ScopedAllowBlocking::ScopedAllowBlocking()
+    : was_disallowed_(g_blocking_disallowed.Get().Get()) {
+  g_blocking_disallowed.Get().Set(false);
+}
+
+ScopedAllowBlocking::~ScopedAllowBlocking() {
+  DCHECK(!g_blocking_disallowed.Get().Get());
+  g_blocking_disallowed.Get().Set(was_disallowed_);
+}
+
+void DisallowBaseSyncPrimitives() {
+  g_base_sync_primitives_disallowed.Get().Set(true);
+}
+
+ScopedAllowBaseSyncPrimitives::ScopedAllowBaseSyncPrimitives()
+    : was_disallowed_(g_base_sync_primitives_disallowed.Get().Get()) {
+  DCHECK(!g_blocking_disallowed.Get().Get())
+      << "To allow //base sync primitives in a scope where blocking is "
+         "disallowed use ScopedAllowBaseSyncPrimitivesOutsideBlockingScope.";
+  g_base_sync_primitives_disallowed.Get().Set(false);
+}
+
+ScopedAllowBaseSyncPrimitives::~ScopedAllowBaseSyncPrimitives() {
+  DCHECK(!g_base_sync_primitives_disallowed.Get().Get());
+  g_base_sync_primitives_disallowed.Get().Set(was_disallowed_);
+}
+
+ScopedAllowBaseSyncPrimitivesOutsideBlockingScope::
+    ScopedAllowBaseSyncPrimitivesOutsideBlockingScope()
+    : was_disallowed_(g_base_sync_primitives_disallowed.Get().Get()) {
+  g_base_sync_primitives_disallowed.Get().Set(false);
+}
+
+ScopedAllowBaseSyncPrimitivesOutsideBlockingScope::
+    ~ScopedAllowBaseSyncPrimitivesOutsideBlockingScope() {
+  DCHECK(!g_base_sync_primitives_disallowed.Get().Get());
+  g_base_sync_primitives_disallowed.Get().Set(was_disallowed_);
+}
+
+ScopedAllowBaseSyncPrimitivesForTesting::
+    ScopedAllowBaseSyncPrimitivesForTesting()
+    : was_disallowed_(g_base_sync_primitives_disallowed.Get().Get()) {
+  g_base_sync_primitives_disallowed.Get().Set(false);
+}
+
+ScopedAllowBaseSyncPrimitivesForTesting::
+    ~ScopedAllowBaseSyncPrimitivesForTesting() {
+  DCHECK(!g_base_sync_primitives_disallowed.Get().Get());
+  g_base_sync_primitives_disallowed.Get().Set(was_disallowed_);
+}
+
+namespace internal {
+
+void AssertBaseSyncPrimitivesAllowed() {
+  DCHECK(!g_base_sync_primitives_disallowed.Get().Get())
+      << "Waiting on a //base sync primitive is not allowed on this thread to "
+         "prevent jank and deadlock. If waiting on a //base sync primitive is "
+         "unavoidable, do it within the scope of a "
+         "ScopedAllowBaseSyncPrimitives. If in a test, "
+         "use ScopedAllowBaseSyncPrimitivesForTesting.";
+}
+
+void ResetThreadRestrictionsForTesting() {
+  g_blocking_disallowed.Get().Set(false);
+  g_singleton_disallowed.Get().Set(false);
+  g_base_sync_primitives_disallowed.Get().Set(false);
+}
+
+}  // namespace internal
+
+ThreadRestrictions::ScopedAllowIO::ScopedAllowIO()
+    : was_allowed_(SetIOAllowed(true)) {}
+
+ThreadRestrictions::ScopedAllowIO::~ScopedAllowIO() {
+  SetIOAllowed(was_allowed_);
+}
+
+// static
+bool ThreadRestrictions::SetIOAllowed(bool allowed) {
+  bool previous_disallowed = g_blocking_disallowed.Get().Get();
+  g_blocking_disallowed.Get().Set(!allowed);
+  return !previous_disallowed;
+}
+
+// static
+bool ThreadRestrictions::SetSingletonAllowed(bool allowed) {
+  bool previous_disallowed = g_singleton_disallowed.Get().Get();
+  g_singleton_disallowed.Get().Set(!allowed);
+  return !previous_disallowed;
+}
+
+// static
+void ThreadRestrictions::AssertSingletonAllowed() {
+  if (g_singleton_disallowed.Get().Get()) {
+    NOTREACHED() << "LazyInstance/Singleton is not allowed to be used on this "
+                 << "thread.  Most likely it's because this thread is not "
+                 << "joinable (or the current task is running with "
+                 << "TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN semantics), so "
+                 << "AtExitManager may have deleted the object on shutdown, "
+                 << "leading to a potential shutdown crash. If you need to use "
+                 << "the object from this context, it'll have to be updated to "
+                 << "use Leaky traits.";
+  }
+}
+
+// static
+void ThreadRestrictions::DisallowWaiting() {
+  DisallowBaseSyncPrimitives();
+}
+
+bool ThreadRestrictions::SetWaitAllowed(bool allowed) {
+  bool previous_disallowed = g_base_sync_primitives_disallowed.Get().Get();
+  g_base_sync_primitives_disallowed.Get().Set(!allowed);
+  return !previous_disallowed;
+}
+
+ThreadRestrictions::ScopedAllowWait::ScopedAllowWait()
+    : was_allowed_(SetWaitAllowed(true)) {}
+
+ThreadRestrictions::ScopedAllowWait::~ScopedAllowWait() {
+  SetWaitAllowed(was_allowed_);
+}
+
+}  // namespace base
+
+#endif  // DCHECK_IS_ON()
diff --git a/base/threading/thread_restrictions.h b/base/threading/thread_restrictions.h
new file mode 100644
index 0000000..57f2f21
--- /dev/null
+++ b/base/threading/thread_restrictions.h
@@ -0,0 +1,506 @@
+// 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.
+
+#ifndef BASE_THREADING_THREAD_RESTRICTIONS_H_
+#define BASE_THREADING_THREAD_RESTRICTIONS_H_
+
+#include "base/base_export.h"
+#include "base/gtest_prod_util.h"
+#include "base/logging.h"
+#include "base/macros.h"
+
+class BrowserProcessImpl;
+class HistogramSynchronizer;
+class NativeBackendKWallet;
+class KeyStorageLinux;
+
+namespace android_webview {
+class AwFormDatabaseService;
+class CookieManager;
+class ScopedAllowInitGLBindings;
+}
+
+namespace cc {
+class CompletionEvent;
+class SingleThreadTaskGraphRunner;
+}
+namespace chromeos {
+class BlockingMethodCaller;
+namespace system {
+class StatisticsProviderImpl;
+}
+}
+namespace chrome_browser_net {
+class Predictor;
+}
+namespace content {
+class BrowserGpuChannelHostFactory;
+class BrowserGpuMemoryBufferManager;
+class BrowserMainLoop;
+class BrowserProcessSubThread;
+class BrowserShutdownProfileDumper;
+class BrowserSurfaceViewManager;
+class BrowserTestBase;
+class CategorizedWorkerPool;
+class NestedMessagePumpAndroid;
+class ScopedAllowWaitForAndroidLayoutTests;
+class ScopedAllowWaitForDebugURL;
+class SessionStorageDatabase;
+class SoftwareOutputDeviceMus;
+class SynchronousCompositor;
+class SynchronousCompositorHost;
+class SynchronousCompositorSyncCallBridge;
+class TextInputClientMac;
+}  // namespace content
+namespace cronet {
+class CronetPrefsManager;
+class CronetURLRequestContext;
+}  // namespace cronet
+namespace dbus {
+class Bus;
+}
+namespace disk_cache {
+class BackendImpl;
+class InFlightIO;
+}
+namespace functions {
+class ExecScriptScopedAllowBaseSyncPrimitives;
+}
+namespace gpu {
+class GpuChannelHost;
+}
+namespace leveldb {
+class LevelDBMojoProxy;
+}
+namespace media {
+class AudioInputDevice;
+class BlockingUrlProtocol;
+}
+namespace midi {
+class TaskService;  // https://crbug.com/796830
+}
+namespace mojo {
+class CoreLibraryInitializer;
+class SyncCallRestrictions;
+namespace edk {
+class ScopedIPCSupport;
+}
+}
+namespace rlz_lib {
+class FinancialPing;
+}
+namespace ui {
+class CommandBufferClientImpl;
+class CommandBufferLocal;
+class GpuState;
+class MaterialDesignController;
+}
+namespace net {
+class MultiThreadedCertVerifierScopedAllowBaseSyncPrimitives;
+class NetworkChangeNotifierMac;
+namespace internal {
+class AddressTrackerLinux;
+}
+}
+
+namespace remoting {
+class AutoThread;
+}
+
+namespace resource_coordinator {
+class TabManagerDelegate;
+}
+
+namespace service_manager {
+class ServiceProcessLauncher;
+}
+
+namespace shell_integration {
+class LaunchXdgUtilityScopedAllowBaseSyncPrimitives;
+}
+
+namespace ui {
+class WindowResizeHelperMac;
+}
+
+namespace views {
+class ScreenMus;
+}
+
+namespace viz {
+class ServerGpuMemoryBufferManager;
+}
+
+namespace webrtc {
+class DesktopConfigurationMonitor;
+}
+
+namespace base {
+
+namespace android {
+class JavaHandlerThread;
+}
+
+namespace internal {
+class TaskTracker;
+}
+
+class GetAppOutputScopedAllowBaseSyncPrimitives;
+class SimpleThread;
+class StackSamplingProfiler;
+class Thread;
+class ThreadTestHelper;
+
+#if DCHECK_IS_ON()
+#define INLINE_IF_DCHECK_IS_OFF BASE_EXPORT
+#define EMPTY_BODY_IF_DCHECK_IS_OFF
+#else
+#define INLINE_IF_DCHECK_IS_OFF inline
+#define EMPTY_BODY_IF_DCHECK_IS_OFF \
+  {}
+#endif
+
+// A "blocking call" refers to any call that causes the calling thread to wait
+// off-CPU. It includes but is not limited to calls that wait on synchronous
+// file I/O operations: read or write a file from disk, interact with a pipe or
+// a socket, rename or delete a file, enumerate files in a directory, etc.
+// Acquiring a low contention lock is not considered a blocking call.
+
+// Asserts that blocking calls are allowed in the current scope.
+//
+// Style tip: It's best if you put AssertBlockingAllowed() checks as close to
+// the blocking call as possible. For example:
+//
+// void ReadFile() {
+//   PreWork();
+//
+//   base::AssertBlockingAllowed();
+//   fopen(...);
+//
+//   PostWork();
+// }
+//
+// void Bar() {
+//   ReadFile();
+// }
+//
+// void Foo() {
+//   Bar();
+// }
+INLINE_IF_DCHECK_IS_OFF void AssertBlockingAllowed()
+    EMPTY_BODY_IF_DCHECK_IS_OFF;
+
+// Disallows blocking on the current thread.
+INLINE_IF_DCHECK_IS_OFF void DisallowBlocking() EMPTY_BODY_IF_DCHECK_IS_OFF;
+
+// Disallows blocking calls within its scope.
+class BASE_EXPORT ScopedDisallowBlocking {
+ public:
+  ScopedDisallowBlocking() EMPTY_BODY_IF_DCHECK_IS_OFF;
+  ~ScopedDisallowBlocking() EMPTY_BODY_IF_DCHECK_IS_OFF;
+
+ private:
+#if DCHECK_IS_ON()
+  const bool was_disallowed_;
+#endif
+
+  DISALLOW_COPY_AND_ASSIGN(ScopedDisallowBlocking);
+};
+
+// ScopedAllowBlocking(ForTesting) allow blocking calls within a scope where
+// they are normally disallowed.
+//
+// Avoid using this. Prefer making blocking calls from tasks posted to
+// base::TaskScheduler with base::MayBlock().
+class BASE_EXPORT ScopedAllowBlocking {
+ private:
+  // This can only be instantiated by friends. Use ScopedAllowBlockingForTesting
+  // in unit tests to avoid the friend requirement.
+  FRIEND_TEST_ALL_PREFIXES(ThreadRestrictionsTest, ScopedAllowBlocking);
+  friend class android_webview::ScopedAllowInitGLBindings;
+  friend class content::BrowserProcessSubThread;
+  friend class cronet::CronetPrefsManager;
+  friend class cronet::CronetURLRequestContext;
+  friend class media::AudioInputDevice;
+  friend class mojo::CoreLibraryInitializer;
+  friend class resource_coordinator::TabManagerDelegate;  // crbug.com/778703
+  friend class ui::MaterialDesignController;
+  friend class ScopedAllowBlockingForTesting;
+  friend class StackSamplingProfiler;
+
+  ScopedAllowBlocking() EMPTY_BODY_IF_DCHECK_IS_OFF;
+  ~ScopedAllowBlocking() EMPTY_BODY_IF_DCHECK_IS_OFF;
+
+#if DCHECK_IS_ON()
+  const bool was_disallowed_;
+#endif
+
+  DISALLOW_COPY_AND_ASSIGN(ScopedAllowBlocking);
+};
+
+class ScopedAllowBlockingForTesting {
+ public:
+  ScopedAllowBlockingForTesting() {}
+  ~ScopedAllowBlockingForTesting() {}
+
+ private:
+#if DCHECK_IS_ON()
+  ScopedAllowBlocking scoped_allow_blocking_;
+#endif
+
+  DISALLOW_COPY_AND_ASSIGN(ScopedAllowBlockingForTesting);
+};
+
+// "Waiting on a //base sync primitive" refers to calling one of these methods:
+// - base::WaitableEvent::*Wait*
+// - base::ConditionVariable::*Wait*
+// - base::Process::WaitForExit*
+
+// Disallows waiting on a //base sync primitive on the current thread.
+INLINE_IF_DCHECK_IS_OFF void DisallowBaseSyncPrimitives()
+    EMPTY_BODY_IF_DCHECK_IS_OFF;
+
+// ScopedAllowBaseSyncPrimitives(ForTesting)(OutsideBlockingScope) allow waiting
+// on a //base sync primitive within a scope where this is normally disallowed.
+//
+// Avoid using this.
+//
+// Instead of waiting on a WaitableEvent or a ConditionVariable, put the work
+// that should happen after the wait in a callback and post that callback from
+// where the WaitableEvent or ConditionVariable would have been signaled. If
+// something needs to be scheduled after many tasks have executed, use
+// base::BarrierClosure.
+//
+// On Windows, join processes asynchronously using base::win::ObjectWatcher.
+
+// This can only be used in a scope where blocking is allowed.
+class BASE_EXPORT ScopedAllowBaseSyncPrimitives {
+ private:
+  // This can only be instantiated by friends. Use
+  // ScopedAllowBaseSyncPrimitivesForTesting in unit tests to avoid the friend
+  // requirement.
+  FRIEND_TEST_ALL_PREFIXES(ThreadRestrictionsTest,
+                           ScopedAllowBaseSyncPrimitives);
+  FRIEND_TEST_ALL_PREFIXES(ThreadRestrictionsTest,
+                           ScopedAllowBaseSyncPrimitivesResetsState);
+  FRIEND_TEST_ALL_PREFIXES(ThreadRestrictionsTest,
+                           ScopedAllowBaseSyncPrimitivesWithBlockingDisallowed);
+  friend class base::GetAppOutputScopedAllowBaseSyncPrimitives;
+  friend class content::BrowserProcessSubThread;
+  friend class content::SessionStorageDatabase;
+  friend class functions::ExecScriptScopedAllowBaseSyncPrimitives;
+  friend class leveldb::LevelDBMojoProxy;
+  friend class media::BlockingUrlProtocol;
+  friend class net::MultiThreadedCertVerifierScopedAllowBaseSyncPrimitives;
+  friend class rlz_lib::FinancialPing;
+  friend class shell_integration::LaunchXdgUtilityScopedAllowBaseSyncPrimitives;
+  friend class webrtc::DesktopConfigurationMonitor;
+
+  ScopedAllowBaseSyncPrimitives() EMPTY_BODY_IF_DCHECK_IS_OFF;
+  ~ScopedAllowBaseSyncPrimitives() EMPTY_BODY_IF_DCHECK_IS_OFF;
+
+#if DCHECK_IS_ON()
+  const bool was_disallowed_;
+#endif
+
+  DISALLOW_COPY_AND_ASSIGN(ScopedAllowBaseSyncPrimitives);
+};
+
+// This can be used in a scope where blocking is disallowed.
+class BASE_EXPORT ScopedAllowBaseSyncPrimitivesOutsideBlockingScope {
+ private:
+  // This can only be instantiated by friends. Use
+  // ScopedAllowBaseSyncPrimitivesForTesting in unit tests to avoid the friend
+  // requirement.
+  FRIEND_TEST_ALL_PREFIXES(ThreadRestrictionsTest,
+                           ScopedAllowBaseSyncPrimitivesOutsideBlockingScope);
+  FRIEND_TEST_ALL_PREFIXES(
+      ThreadRestrictionsTest,
+      ScopedAllowBaseSyncPrimitivesOutsideBlockingScopeResetsState);
+  friend class ::KeyStorageLinux;
+  friend class content::SynchronousCompositor;
+  friend class content::SynchronousCompositorHost;
+  friend class content::SynchronousCompositorSyncCallBridge;
+  friend class midi::TaskService;  // https://crbug.com/796830
+  // Not used in production yet, https://crbug.com/844078.
+  friend class service_manager::ServiceProcessLauncher;
+
+  ScopedAllowBaseSyncPrimitivesOutsideBlockingScope()
+      EMPTY_BODY_IF_DCHECK_IS_OFF;
+  ~ScopedAllowBaseSyncPrimitivesOutsideBlockingScope()
+      EMPTY_BODY_IF_DCHECK_IS_OFF;
+
+#if DCHECK_IS_ON()
+  const bool was_disallowed_;
+#endif
+
+  DISALLOW_COPY_AND_ASSIGN(ScopedAllowBaseSyncPrimitivesOutsideBlockingScope);
+};
+
+// This can be used in tests without being a friend of
+// ScopedAllowBaseSyncPrimitives(OutsideBlockingScope).
+class BASE_EXPORT ScopedAllowBaseSyncPrimitivesForTesting {
+ public:
+  ScopedAllowBaseSyncPrimitivesForTesting() EMPTY_BODY_IF_DCHECK_IS_OFF;
+  ~ScopedAllowBaseSyncPrimitivesForTesting() EMPTY_BODY_IF_DCHECK_IS_OFF;
+
+ private:
+#if DCHECK_IS_ON()
+  const bool was_disallowed_;
+#endif
+
+  DISALLOW_COPY_AND_ASSIGN(ScopedAllowBaseSyncPrimitivesForTesting);
+};
+
+namespace internal {
+
+// Asserts that waiting on a //base sync primitive is allowed in the current
+// scope.
+INLINE_IF_DCHECK_IS_OFF void AssertBaseSyncPrimitivesAllowed()
+    EMPTY_BODY_IF_DCHECK_IS_OFF;
+
+// Resets all thread restrictions on the current thread.
+INLINE_IF_DCHECK_IS_OFF void ResetThreadRestrictionsForTesting()
+    EMPTY_BODY_IF_DCHECK_IS_OFF;
+
+}  // namespace internal
+
+class BASE_EXPORT ThreadRestrictions {
+ public:
+  // Constructing a ScopedAllowIO temporarily allows IO for the current
+  // thread.  Doing this is almost certainly always incorrect.
+  //
+  // DEPRECATED. Use ScopedAllowBlocking(ForTesting).
+  class BASE_EXPORT ScopedAllowIO {
+   public:
+    ScopedAllowIO() EMPTY_BODY_IF_DCHECK_IS_OFF;
+    ~ScopedAllowIO() EMPTY_BODY_IF_DCHECK_IS_OFF;
+
+   private:
+#if DCHECK_IS_ON()
+    const bool was_allowed_;
+#endif
+
+    DISALLOW_COPY_AND_ASSIGN(ScopedAllowIO);
+  };
+
+#if DCHECK_IS_ON()
+  // Set whether the current thread to make IO calls.
+  // Threads start out in the *allowed* state.
+  // Returns the previous value.
+  //
+  // DEPRECATED. Use ScopedAllowBlocking(ForTesting) or ScopedDisallowBlocking.
+  static bool SetIOAllowed(bool allowed);
+
+  // Set whether the current thread can use singletons.  Returns the previous
+  // value.
+  static bool SetSingletonAllowed(bool allowed);
+
+  // Check whether the current thread is allowed to use singletons (Singleton /
+  // LazyInstance).  DCHECKs if not.
+  static void AssertSingletonAllowed();
+
+  // Disable waiting on the current thread. Threads start out in the *allowed*
+  // state. Returns the previous value.
+  //
+  // DEPRECATED. Use DisallowBaseSyncPrimitives.
+  static void DisallowWaiting();
+#else
+  // Inline the empty definitions of these functions so that they can be
+  // compiled out.
+  static bool SetIOAllowed(bool allowed) { return true; }
+  static bool SetSingletonAllowed(bool allowed) { return true; }
+  static void AssertSingletonAllowed() {}
+  static void DisallowWaiting() {}
+#endif
+
+ private:
+  // DO NOT ADD ANY OTHER FRIEND STATEMENTS, talk to jam or brettw first.
+  // BEGIN ALLOWED USAGE.
+  friend class android_webview::AwFormDatabaseService;
+  friend class android_webview::CookieManager;
+  friend class base::StackSamplingProfiler;
+  friend class content::BrowserMainLoop;
+  friend class content::BrowserShutdownProfileDumper;
+  friend class content::BrowserSurfaceViewManager;
+  friend class content::BrowserTestBase;
+  friend class content::NestedMessagePumpAndroid;
+  friend class content::ScopedAllowWaitForAndroidLayoutTests;
+  friend class content::ScopedAllowWaitForDebugURL;
+  friend class ::HistogramSynchronizer;
+  friend class internal::TaskTracker;
+  friend class cc::CompletionEvent;
+  friend class cc::SingleThreadTaskGraphRunner;
+  friend class content::CategorizedWorkerPool;
+  friend class remoting::AutoThread;
+  friend class ui::WindowResizeHelperMac;
+  friend class MessagePumpDefault;
+  friend class SimpleThread;
+  friend class Thread;
+  friend class ThreadTestHelper;
+  friend class PlatformThread;
+  friend class android::JavaHandlerThread;
+  friend class mojo::SyncCallRestrictions;
+  friend class mojo::edk::ScopedIPCSupport;
+  friend class ui::CommandBufferClientImpl;
+  friend class ui::CommandBufferLocal;
+  friend class ui::GpuState;
+
+  // END ALLOWED USAGE.
+  // BEGIN USAGE THAT NEEDS TO BE FIXED.
+  friend class ::chromeos::BlockingMethodCaller;  // http://crbug.com/125360
+  friend class ::chromeos::system::StatisticsProviderImpl;  // http://crbug.com/125385
+  friend class chrome_browser_net::Predictor;     // http://crbug.com/78451
+  friend class
+      content::BrowserGpuChannelHostFactory;      // http://crbug.com/125248
+  friend class
+      content::BrowserGpuMemoryBufferManager;     // http://crbug.com/420368
+  friend class content::TextInputClientMac;       // http://crbug.com/121917
+  friend class dbus::Bus;                         // http://crbug.com/125222
+  friend class disk_cache::BackendImpl;           // http://crbug.com/74623
+  friend class disk_cache::InFlightIO;            // http://crbug.com/74623
+  friend class gpu::GpuChannelHost;               // http://crbug.com/125264
+  friend class net::internal::AddressTrackerLinux;  // http://crbug.com/125097
+  friend class net::NetworkChangeNotifierMac;     // http://crbug.com/125097
+  friend class ::BrowserProcessImpl;              // http://crbug.com/125207
+  friend class ::NativeBackendKWallet;            // http://crbug.com/125331
+#if !defined(OFFICIAL_BUILD)
+  friend class content::SoftwareOutputDeviceMus;  // Interim non-production code
+#endif
+  friend class views::ScreenMus;
+  friend class viz::ServerGpuMemoryBufferManager;
+// END USAGE THAT NEEDS TO BE FIXED.
+
+#if DCHECK_IS_ON()
+  // DEPRECATED. Use ScopedAllowBaseSyncPrimitives.
+  static bool SetWaitAllowed(bool allowed);
+#else
+  static bool SetWaitAllowed(bool allowed) { return true; }
+#endif
+
+  // Constructing a ScopedAllowWait temporarily allows waiting on the current
+  // thread.  Doing this is almost always incorrect, which is why we limit who
+  // can use this through friend. If you find yourself needing to use this, find
+  // another way. Talk to jam or brettw.
+  //
+  // DEPRECATED. Use ScopedAllowBaseSyncPrimitives.
+  class BASE_EXPORT ScopedAllowWait {
+   public:
+    ScopedAllowWait() EMPTY_BODY_IF_DCHECK_IS_OFF;
+    ~ScopedAllowWait() EMPTY_BODY_IF_DCHECK_IS_OFF;
+
+   private:
+#if DCHECK_IS_ON()
+    const bool was_allowed_;
+#endif
+
+    DISALLOW_COPY_AND_ASSIGN(ScopedAllowWait);
+  };
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(ThreadRestrictions);
+};
+
+}  // namespace base
+
+#endif  // BASE_THREADING_THREAD_RESTRICTIONS_H_
diff --git a/base/threading/thread_restrictions_unittest.cc b/base/threading/thread_restrictions_unittest.cc
new file mode 100644
index 0000000..a957a9a
--- /dev/null
+++ b/base/threading/thread_restrictions_unittest.cc
@@ -0,0 +1,137 @@
+// Copyright 2017 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 "base/threading/thread_restrictions.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/test/gtest_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+
+namespace {
+
+class ThreadRestrictionsTest : public testing::Test {
+ public:
+  ThreadRestrictionsTest() = default;
+  ~ThreadRestrictionsTest() override {
+    internal::ResetThreadRestrictionsForTesting();
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ThreadRestrictionsTest);
+};
+
+}  // namespace
+
+TEST_F(ThreadRestrictionsTest, BlockingAllowedByDefault) {
+  AssertBlockingAllowed();
+}
+
+TEST_F(ThreadRestrictionsTest, ScopedDisallowBlocking) {
+  {
+    ScopedDisallowBlocking scoped_disallow_blocking;
+    EXPECT_DCHECK_DEATH({ AssertBlockingAllowed(); });
+  }
+  AssertBlockingAllowed();
+}
+
+TEST_F(ThreadRestrictionsTest, ScopedAllowBlocking) {
+  ScopedDisallowBlocking scoped_disallow_blocking;
+  {
+    ScopedAllowBlocking scoped_allow_blocking;
+    AssertBlockingAllowed();
+  }
+  EXPECT_DCHECK_DEATH({ AssertBlockingAllowed(); });
+}
+
+TEST_F(ThreadRestrictionsTest, ScopedAllowBlockingForTesting) {
+  ScopedDisallowBlocking scoped_disallow_blocking;
+  {
+    ScopedAllowBlockingForTesting scoped_allow_blocking_for_testing;
+    AssertBlockingAllowed();
+  }
+  EXPECT_DCHECK_DEATH({ AssertBlockingAllowed(); });
+}
+
+TEST_F(ThreadRestrictionsTest, BaseSyncPrimitivesAllowedByDefault) {}
+
+TEST_F(ThreadRestrictionsTest, DisallowBaseSyncPrimitives) {
+  DisallowBaseSyncPrimitives();
+  EXPECT_DCHECK_DEATH({ internal::AssertBaseSyncPrimitivesAllowed(); });
+}
+
+TEST_F(ThreadRestrictionsTest, ScopedAllowBaseSyncPrimitives) {
+  DisallowBaseSyncPrimitives();
+  ScopedAllowBaseSyncPrimitives scoped_allow_base_sync_primitives;
+  internal::AssertBaseSyncPrimitivesAllowed();
+}
+
+TEST_F(ThreadRestrictionsTest, ScopedAllowBaseSyncPrimitivesResetsState) {
+  DisallowBaseSyncPrimitives();
+  { ScopedAllowBaseSyncPrimitives scoped_allow_base_sync_primitives; }
+  EXPECT_DCHECK_DEATH({ internal::AssertBaseSyncPrimitivesAllowed(); });
+}
+
+TEST_F(ThreadRestrictionsTest,
+       ScopedAllowBaseSyncPrimitivesWithBlockingDisallowed) {
+  ScopedDisallowBlocking scoped_disallow_blocking;
+  DisallowBaseSyncPrimitives();
+
+  // This should DCHECK because blocking is not allowed in this scope
+  // and OutsideBlockingScope is not passed to the constructor.
+  EXPECT_DCHECK_DEATH(
+      { ScopedAllowBaseSyncPrimitives scoped_allow_base_sync_primitives; });
+}
+
+TEST_F(ThreadRestrictionsTest,
+       ScopedAllowBaseSyncPrimitivesOutsideBlockingScope) {
+  ScopedDisallowBlocking scoped_disallow_blocking;
+  DisallowBaseSyncPrimitives();
+  ScopedAllowBaseSyncPrimitivesOutsideBlockingScope
+      scoped_allow_base_sync_primitives;
+  internal::AssertBaseSyncPrimitivesAllowed();
+}
+
+TEST_F(ThreadRestrictionsTest,
+       ScopedAllowBaseSyncPrimitivesOutsideBlockingScopeResetsState) {
+  DisallowBaseSyncPrimitives();
+  {
+    ScopedAllowBaseSyncPrimitivesOutsideBlockingScope
+        scoped_allow_base_sync_primitives;
+  }
+  EXPECT_DCHECK_DEATH({ internal::AssertBaseSyncPrimitivesAllowed(); });
+}
+
+TEST_F(ThreadRestrictionsTest, ScopedAllowBaseSyncPrimitivesForTesting) {
+  DisallowBaseSyncPrimitives();
+  ScopedAllowBaseSyncPrimitivesForTesting
+      scoped_allow_base_sync_primitives_for_testing;
+  internal::AssertBaseSyncPrimitivesAllowed();
+}
+
+TEST_F(ThreadRestrictionsTest,
+       ScopedAllowBaseSyncPrimitivesForTestingResetsState) {
+  DisallowBaseSyncPrimitives();
+  {
+    ScopedAllowBaseSyncPrimitivesForTesting
+        scoped_allow_base_sync_primitives_for_testing;
+  }
+  EXPECT_DCHECK_DEATH({ internal::AssertBaseSyncPrimitivesAllowed(); });
+}
+
+TEST_F(ThreadRestrictionsTest,
+       ScopedAllowBaseSyncPrimitivesForTestingWithBlockingDisallowed) {
+  ScopedDisallowBlocking scoped_disallow_blocking;
+  DisallowBaseSyncPrimitives();
+  // This should not DCHECK.
+  ScopedAllowBaseSyncPrimitivesForTesting
+      scoped_allow_base_sync_primitives_for_testing;
+}
+
+}  // namespace base
diff --git a/base/threading/thread_task_runner_handle.cc b/base/threading/thread_task_runner_handle.cc
new file mode 100644
index 0000000..314b303
--- /dev/null
+++ b/base/threading/thread_task_runner_handle.cc
@@ -0,0 +1,106 @@
+// Copyright 2016 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 "base/threading/thread_task_runner_handle.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/lazy_instance.h"
+#include "base/logging.h"
+#include "base/memory/ptr_util.h"
+#include "base/run_loop.h"
+#include "base/threading/sequenced_task_runner_handle.h"
+#include "base/threading/thread_local.h"
+
+namespace base {
+
+namespace {
+
+base::LazyInstance<base::ThreadLocalPointer<ThreadTaskRunnerHandle>>::Leaky
+    thread_task_runner_tls = LAZY_INSTANCE_INITIALIZER;
+
+}  // namespace
+
+// static
+scoped_refptr<SingleThreadTaskRunner> ThreadTaskRunnerHandle::Get() {
+  ThreadTaskRunnerHandle* current = thread_task_runner_tls.Pointer()->Get();
+  CHECK(current) << "Error: This caller requires a single-threaded context "
+                    "(i.e. the current task needs to run from a "
+                    "SingleThreadTaskRunner).";
+  return current->task_runner_;
+}
+
+// static
+bool ThreadTaskRunnerHandle::IsSet() {
+  return !!thread_task_runner_tls.Pointer()->Get();
+}
+
+// static
+ScopedClosureRunner ThreadTaskRunnerHandle::OverrideForTesting(
+    scoped_refptr<SingleThreadTaskRunner> overriding_task_runner) {
+  // OverrideForTesting() is not compatible with a SequencedTaskRunnerHandle
+  // being set (but SequencedTaskRunnerHandle::IsSet() includes
+  // ThreadTaskRunnerHandle::IsSet() so that's discounted as the only valid
+  // excuse for it to be true). Sadly this means that tests that merely need a
+  // SequencedTaskRunnerHandle on their main thread can be forced to use a
+  // ThreadTaskRunnerHandle if they're also using test task runners (that
+  // OverrideForTesting() when running their tasks from said main thread). To
+  // solve this: sequence_task_runner_handle.cc and thread_task_runner_handle.cc
+  // would have to be merged into a single impl file and share TLS state. This
+  // was deemed unecessary for now as most tests should use higher level
+  // constructs and not have to instantiate task runner handles on their own.
+  DCHECK(!SequencedTaskRunnerHandle::IsSet() || IsSet());
+
+  if (!IsSet()) {
+    auto top_level_ttrh = std::make_unique<ThreadTaskRunnerHandle>(
+        std::move(overriding_task_runner));
+    return ScopedClosureRunner(base::BindOnce(
+        [](std::unique_ptr<ThreadTaskRunnerHandle> ttrh_to_release) {},
+        std::move(top_level_ttrh)));
+  }
+
+  ThreadTaskRunnerHandle* ttrh = thread_task_runner_tls.Pointer()->Get();
+  // Swap the two (and below bind |overriding_task_runner|, which is now the
+  // previous one, as the |task_runner_to_restore|).
+  ttrh->task_runner_.swap(overriding_task_runner);
+
+  auto no_running_during_override =
+      std::make_unique<RunLoop::ScopedDisallowRunningForTesting>();
+
+  return ScopedClosureRunner(base::BindOnce(
+      [](scoped_refptr<SingleThreadTaskRunner> task_runner_to_restore,
+         SingleThreadTaskRunner* expected_task_runner_before_restore,
+         std::unique_ptr<RunLoop::ScopedDisallowRunningForTesting>
+             no_running_during_override) {
+        ThreadTaskRunnerHandle* ttrh = thread_task_runner_tls.Pointer()->Get();
+
+        DCHECK_EQ(expected_task_runner_before_restore, ttrh->task_runner_.get())
+            << "Nested overrides must expire their ScopedClosureRunners "
+               "in LIFO order.";
+
+        ttrh->task_runner_.swap(task_runner_to_restore);
+      },
+      std::move(overriding_task_runner),
+      base::Unretained(ttrh->task_runner_.get()),
+      std::move(no_running_during_override)));
+}
+
+ThreadTaskRunnerHandle::ThreadTaskRunnerHandle(
+    scoped_refptr<SingleThreadTaskRunner> task_runner)
+    : task_runner_(std::move(task_runner)) {
+  DCHECK(task_runner_->BelongsToCurrentThread());
+  // No SequencedTaskRunnerHandle (which includes ThreadTaskRunnerHandles)
+  // should already be set for this thread.
+  DCHECK(!SequencedTaskRunnerHandle::IsSet());
+  thread_task_runner_tls.Pointer()->Set(this);
+}
+
+ThreadTaskRunnerHandle::~ThreadTaskRunnerHandle() {
+  DCHECK(task_runner_->BelongsToCurrentThread());
+  DCHECK_EQ(thread_task_runner_tls.Pointer()->Get(), this);
+  thread_task_runner_tls.Pointer()->Set(nullptr);
+}
+
+}  // namespace base
diff --git a/base/threading/thread_task_runner_handle.h b/base/threading/thread_task_runner_handle.h
new file mode 100644
index 0000000..f6b71d7
--- /dev/null
+++ b/base/threading/thread_task_runner_handle.h
@@ -0,0 +1,57 @@
+// Copyright 2016 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.
+
+#ifndef BASE_THREADING_THREAD_TASK_RUNNER_HANDLE_H_
+#define BASE_THREADING_THREAD_TASK_RUNNER_HANDLE_H_
+
+#include "base/base_export.h"
+#include "base/callback_helpers.h"
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/single_thread_task_runner.h"
+
+namespace base {
+
+// ThreadTaskRunnerHandle stores a reference to a thread's TaskRunner
+// in thread-local storage.  Callers can then retrieve the TaskRunner
+// for the current thread by calling ThreadTaskRunnerHandle::Get().
+// At most one TaskRunner may be bound to each thread at a time.
+// Prefer SequencedTaskRunnerHandle to this unless thread affinity is required.
+class BASE_EXPORT ThreadTaskRunnerHandle {
+ public:
+  // Gets the SingleThreadTaskRunner for the current thread.
+  static scoped_refptr<SingleThreadTaskRunner> Get();
+
+  // Returns true if the SingleThreadTaskRunner is already created for
+  // the current thread.
+  static bool IsSet();
+
+  // Overrides ThreadTaskRunnerHandle::Get()'s |task_runner_| to point at
+  // |overriding_task_runner| until the returned ScopedClosureRunner goes out of
+  // scope (instantiates a ThreadTaskRunnerHandle for that scope if |!IsSet()|).
+  // Nested overrides are allowed but callers must ensure the
+  // ScopedClosureRunners expire in LIFO (stack) order. Note: nesting
+  // ThreadTaskRunnerHandles isn't generally desired but it's useful in unit
+  // tests where multiple task runners can share the main thread for simplicity
+  // and determinism.
+  static ScopedClosureRunner OverrideForTesting(
+      scoped_refptr<SingleThreadTaskRunner> overriding_task_runner)
+      WARN_UNUSED_RESULT;
+
+  // Binds |task_runner| to the current thread. |task_runner| must belong
+  // to the current thread for this to succeed.
+  explicit ThreadTaskRunnerHandle(
+      scoped_refptr<SingleThreadTaskRunner> task_runner);
+  ~ThreadTaskRunnerHandle();
+
+ private:
+  scoped_refptr<SingleThreadTaskRunner> task_runner_;
+
+  DISALLOW_COPY_AND_ASSIGN(ThreadTaskRunnerHandle);
+};
+
+}  // namespace base
+
+#endif  // BASE_THREADING_THREAD_TASK_RUNNER_HANDLE_H_
diff --git a/base/threading/thread_task_runner_handle_unittest.cc b/base/threading/thread_task_runner_handle_unittest.cc
new file mode 100644
index 0000000..1aa02d1
--- /dev/null
+++ b/base/threading/thread_task_runner_handle_unittest.cc
@@ -0,0 +1,122 @@
+// Copyright 2017 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 "base/threading/thread_task_runner_handle.h"
+
+#include "base/memory/ref_counted.h"
+#include "base/test/gtest_util.h"
+#include "base/test/test_simple_task_runner.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+
+TEST(ThreadTaskRunnerHandleTest, Basic) {
+  scoped_refptr<SingleThreadTaskRunner> task_runner(new TestSimpleTaskRunner);
+
+  EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet());
+  {
+    ThreadTaskRunnerHandle ttrh1(task_runner);
+    EXPECT_TRUE(ThreadTaskRunnerHandle::IsSet());
+    EXPECT_EQ(task_runner, ThreadTaskRunnerHandle::Get());
+  }
+  EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet());
+}
+
+TEST(ThreadTaskRunnerHandleTest, DeathOnImplicitOverride) {
+  scoped_refptr<SingleThreadTaskRunner> task_runner(new TestSimpleTaskRunner);
+  scoped_refptr<SingleThreadTaskRunner> overidding_task_runner(
+      new TestSimpleTaskRunner);
+
+  ThreadTaskRunnerHandle ttrh(task_runner);
+  EXPECT_DCHECK_DEATH(
+      { ThreadTaskRunnerHandle overriding_ttrh(overidding_task_runner); });
+}
+
+TEST(ThreadTaskRunnerHandleTest, OverrideForTestingExistingTTRH) {
+  scoped_refptr<SingleThreadTaskRunner> task_runner_1(new TestSimpleTaskRunner);
+  scoped_refptr<SingleThreadTaskRunner> task_runner_2(new TestSimpleTaskRunner);
+  scoped_refptr<SingleThreadTaskRunner> task_runner_3(new TestSimpleTaskRunner);
+  scoped_refptr<SingleThreadTaskRunner> task_runner_4(new TestSimpleTaskRunner);
+
+  EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet());
+  {
+    // TTRH in place prior to override.
+    ThreadTaskRunnerHandle ttrh1(task_runner_1);
+    EXPECT_TRUE(ThreadTaskRunnerHandle::IsSet());
+    EXPECT_EQ(task_runner_1, ThreadTaskRunnerHandle::Get());
+
+    {
+      // Override.
+      ScopedClosureRunner undo_override_2 =
+          ThreadTaskRunnerHandle::OverrideForTesting(task_runner_2);
+      EXPECT_TRUE(ThreadTaskRunnerHandle::IsSet());
+      EXPECT_EQ(task_runner_2, ThreadTaskRunnerHandle::Get());
+
+      {
+        // Nested override.
+        ScopedClosureRunner undo_override_3 =
+            ThreadTaskRunnerHandle::OverrideForTesting(task_runner_3);
+        EXPECT_TRUE(ThreadTaskRunnerHandle::IsSet());
+        EXPECT_EQ(task_runner_3, ThreadTaskRunnerHandle::Get());
+      }
+
+      // Back to single override.
+      EXPECT_TRUE(ThreadTaskRunnerHandle::IsSet());
+      EXPECT_EQ(task_runner_2, ThreadTaskRunnerHandle::Get());
+
+      {
+        // Backup to double override with another TTRH.
+        ScopedClosureRunner undo_override_4 =
+            ThreadTaskRunnerHandle::OverrideForTesting(task_runner_4);
+        EXPECT_TRUE(ThreadTaskRunnerHandle::IsSet());
+        EXPECT_EQ(task_runner_4, ThreadTaskRunnerHandle::Get());
+      }
+    }
+
+    // Back to simple TTRH.
+    EXPECT_TRUE(ThreadTaskRunnerHandle::IsSet());
+    EXPECT_EQ(task_runner_1, ThreadTaskRunnerHandle::Get());
+  }
+  EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet());
+}
+
+TEST(ThreadTaskRunnerHandleTest, OverrideForTestingNoExistingTTRH) {
+  scoped_refptr<SingleThreadTaskRunner> task_runner_1(new TestSimpleTaskRunner);
+  scoped_refptr<SingleThreadTaskRunner> task_runner_2(new TestSimpleTaskRunner);
+
+  EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet());
+  {
+    // Override with no TTRH in place.
+    ScopedClosureRunner undo_override_1 =
+        ThreadTaskRunnerHandle::OverrideForTesting(task_runner_1);
+    EXPECT_TRUE(ThreadTaskRunnerHandle::IsSet());
+    EXPECT_EQ(task_runner_1, ThreadTaskRunnerHandle::Get());
+
+    {
+      // Nested override works the same.
+      ScopedClosureRunner undo_override_2 =
+          ThreadTaskRunnerHandle::OverrideForTesting(task_runner_2);
+      EXPECT_TRUE(ThreadTaskRunnerHandle::IsSet());
+      EXPECT_EQ(task_runner_2, ThreadTaskRunnerHandle::Get());
+    }
+
+    // Back to single override.
+    EXPECT_TRUE(ThreadTaskRunnerHandle::IsSet());
+    EXPECT_EQ(task_runner_1, ThreadTaskRunnerHandle::Get());
+  }
+  EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet());
+}
+
+TEST(ThreadTaskRunnerHandleTest, DeathOnTTRHOverOverride) {
+  scoped_refptr<SingleThreadTaskRunner> task_runner(new TestSimpleTaskRunner);
+  scoped_refptr<SingleThreadTaskRunner> overidding_task_runner(
+      new TestSimpleTaskRunner);
+
+  ScopedClosureRunner undo_override =
+      ThreadTaskRunnerHandle::OverrideForTesting(task_runner);
+  EXPECT_DCHECK_DEATH(
+      { ThreadTaskRunnerHandle overriding_ttrh(overidding_task_runner); });
+}
+
+}  // namespace base
diff --git a/base/threading/thread_unittest.cc b/base/threading/thread_unittest.cc
new file mode 100644
index 0000000..d90b1f9
--- /dev/null
+++ b/base/threading/thread_unittest.cc
@@ -0,0 +1,579 @@
+// 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 "base/threading/thread.h"
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <utility>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/debug/leak_annotations.h"
+#include "base/macros.h"
+#include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_loop_current.h"
+#include "base/run_loop.h"
+#include "base/single_thread_task_runner.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/test/gtest_util.h"
+#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
+#include "base/threading/platform_thread.h"
+#include "base/time/time.h"
+#include "build/build_config.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+using base::Thread;
+
+typedef PlatformTest ThreadTest;
+
+namespace {
+
+void ToggleValue(bool* value) {
+  ANNOTATE_BENIGN_RACE(value, "Test-only data race on boolean "
+                       "in base/thread_unittest");
+  *value = !*value;
+}
+
+class SleepInsideInitThread : public Thread {
+ public:
+  SleepInsideInitThread() : Thread("none") {
+    init_called_ = false;
+    ANNOTATE_BENIGN_RACE(
+        this, "Benign test-only data race on vptr - http://crbug.com/98219");
+  }
+  ~SleepInsideInitThread() override { Stop(); }
+
+  void Init() override {
+    base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(500));
+    init_called_ = true;
+  }
+  bool InitCalled() { return init_called_; }
+
+ private:
+  bool init_called_;
+
+  DISALLOW_COPY_AND_ASSIGN(SleepInsideInitThread);
+};
+
+enum ThreadEvent {
+  // Thread::Init() was called.
+  THREAD_EVENT_INIT = 0,
+
+  // The MessageLoop for the thread was deleted.
+  THREAD_EVENT_MESSAGE_LOOP_DESTROYED,
+
+  // Thread::CleanUp() was called.
+  THREAD_EVENT_CLEANUP,
+
+  // Keep at end of list.
+  THREAD_NUM_EVENTS
+};
+
+typedef std::vector<ThreadEvent> EventList;
+
+class CaptureToEventList : public Thread {
+ public:
+  // This Thread pushes events into the vector |event_list| to show
+  // the order they occured in. |event_list| must remain valid for the
+  // lifetime of this thread.
+  explicit CaptureToEventList(EventList* event_list)
+      : Thread("none"),
+        event_list_(event_list) {
+  }
+
+  ~CaptureToEventList() override { Stop(); }
+
+  void Init() override { event_list_->push_back(THREAD_EVENT_INIT); }
+
+  void CleanUp() override { event_list_->push_back(THREAD_EVENT_CLEANUP); }
+
+ private:
+  EventList* event_list_;
+
+  DISALLOW_COPY_AND_ASSIGN(CaptureToEventList);
+};
+
+// Observer that writes a value into |event_list| when a message loop has been
+// destroyed.
+class CapturingDestructionObserver
+    : public base::MessageLoopCurrent::DestructionObserver {
+ public:
+  // |event_list| must remain valid throughout the observer's lifetime.
+  explicit CapturingDestructionObserver(EventList* event_list)
+      : event_list_(event_list) {
+  }
+
+  // DestructionObserver implementation:
+  void WillDestroyCurrentMessageLoop() override {
+    event_list_->push_back(THREAD_EVENT_MESSAGE_LOOP_DESTROYED);
+    event_list_ = nullptr;
+  }
+
+ private:
+  EventList* event_list_;
+
+  DISALLOW_COPY_AND_ASSIGN(CapturingDestructionObserver);
+};
+
+// Task that adds a destruction observer to the current message loop.
+void RegisterDestructionObserver(
+    base::MessageLoopCurrent::DestructionObserver* observer) {
+  base::MessageLoopCurrent::Get()->AddDestructionObserver(observer);
+}
+
+// Task that calls GetThreadId() of |thread|, stores the result into |id|, then
+// signal |event|.
+void ReturnThreadId(base::Thread* thread,
+                    base::PlatformThreadId* id,
+                    base::WaitableEvent* event) {
+  *id = thread->GetThreadId();
+  event->Signal();
+}
+
+}  // namespace
+
+TEST_F(ThreadTest, StartWithOptions_StackSize) {
+  Thread a("StartWithStackSize");
+  // Ensure that the thread can work with only 12 kb and still process a
+  // message. At the same time, we should scale with the bitness of the system
+  // where 12 kb is definitely not enough.
+  // 12 kb = 3072 Slots on a 32-bit system, so we'll scale based off of that.
+  Thread::Options options;
+#if defined(ADDRESS_SANITIZER) || !defined(NDEBUG)
+  // ASan bloats the stack variables and overflows the 3072 slot stack. Some
+  // debug builds also grow the stack too much.
+  options.stack_size = 2 * 3072 * sizeof(uintptr_t);
+#else
+  options.stack_size = 3072 * sizeof(uintptr_t);
+#endif
+  EXPECT_TRUE(a.StartWithOptions(options));
+  EXPECT_TRUE(a.message_loop());
+  EXPECT_TRUE(a.IsRunning());
+
+  base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
+                            base::WaitableEvent::InitialState::NOT_SIGNALED);
+  a.task_runner()->PostTask(
+      FROM_HERE,
+      base::BindOnce(&base::WaitableEvent::Signal, base::Unretained(&event)));
+  event.Wait();
+}
+
+// Intentional test-only race for otherwise untestable code, won't fix.
+// https://crbug.com/634383
+#if !defined(THREAD_SANITIZER)
+TEST_F(ThreadTest, StartWithOptions_NonJoinable) {
+  Thread* a = new Thread("StartNonJoinable");
+  // Non-joinable threads have to be leaked for now (see
+  // Thread::Options::joinable for details).
+  ANNOTATE_LEAKING_OBJECT_PTR(a);
+
+  Thread::Options options;
+  options.joinable = false;
+  EXPECT_TRUE(a->StartWithOptions(options));
+  EXPECT_TRUE(a->message_loop());
+  EXPECT_TRUE(a->IsRunning());
+
+  // Without this call this test is racy. The above IsRunning() succeeds because
+  // of an early-return condition while between Start() and StopSoon(), after
+  // invoking StopSoon() below this early-return condition is no longer
+  // satisfied and the real |is_running_| bit has to be checked. It could still
+  // be false if the message loop hasn't started for real in practice. This is
+  // only a requirement for this test because the non-joinable property forces
+  // it to use StopSoon() and not wait for a complete Stop().
+  EXPECT_TRUE(a->WaitUntilThreadStarted());
+
+  // Make the thread block until |block_event| is signaled.
+  base::WaitableEvent block_event(
+      base::WaitableEvent::ResetPolicy::AUTOMATIC,
+      base::WaitableEvent::InitialState::NOT_SIGNALED);
+  a->task_runner()->PostTask(FROM_HERE,
+                             base::BindOnce(&base::WaitableEvent::Wait,
+                                            base::Unretained(&block_event)));
+
+  a->StopSoon();
+  EXPECT_TRUE(a->IsRunning());
+
+  // Unblock the task and give a bit of extra time to unwind QuitWhenIdle().
+  block_event.Signal();
+  base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(20));
+
+  // The thread should now have stopped on its own.
+  EXPECT_FALSE(a->IsRunning());
+}
+#endif
+
+TEST_F(ThreadTest, TwoTasksOnJoinableThread) {
+  bool was_invoked = false;
+  {
+    Thread a("TwoTasksOnJoinableThread");
+    EXPECT_TRUE(a.Start());
+    EXPECT_TRUE(a.message_loop());
+
+    // Test that all events are dispatched before the Thread object is
+    // destroyed.  We do this by dispatching a sleep event before the
+    // event that will toggle our sentinel value.
+    a.task_runner()->PostTask(
+        FROM_HERE, base::BindOnce(static_cast<void (*)(base::TimeDelta)>(
+                                      &base::PlatformThread::Sleep),
+                                  base::TimeDelta::FromMilliseconds(20)));
+    a.task_runner()->PostTask(FROM_HERE,
+                              base::BindOnce(&ToggleValue, &was_invoked));
+  }
+  EXPECT_TRUE(was_invoked);
+}
+
+TEST_F(ThreadTest, DestroyWhileRunningIsSafe) {
+  Thread a("DestroyWhileRunningIsSafe");
+  EXPECT_TRUE(a.Start());
+  EXPECT_TRUE(a.WaitUntilThreadStarted());
+}
+
+// TODO(gab): Enable this test when destroying a non-joinable Thread instance
+// is supported (proposal @ https://crbug.com/629139#c14).
+TEST_F(ThreadTest, DISABLED_DestroyWhileRunningNonJoinableIsSafe) {
+  {
+    Thread a("DestroyWhileRunningNonJoinableIsSafe");
+    Thread::Options options;
+    options.joinable = false;
+    EXPECT_TRUE(a.StartWithOptions(options));
+    EXPECT_TRUE(a.WaitUntilThreadStarted());
+  }
+
+  // Attempt to catch use-after-frees from the non-joinable thread in the
+  // scope of this test if any.
+  base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(20));
+}
+
+TEST_F(ThreadTest, StopSoon) {
+  Thread a("StopSoon");
+  EXPECT_TRUE(a.Start());
+  EXPECT_TRUE(a.message_loop());
+  EXPECT_TRUE(a.IsRunning());
+  a.StopSoon();
+  a.Stop();
+  EXPECT_FALSE(a.message_loop());
+  EXPECT_FALSE(a.IsRunning());
+}
+
+TEST_F(ThreadTest, StopTwiceNop) {
+  Thread a("StopTwiceNop");
+  EXPECT_TRUE(a.Start());
+  EXPECT_TRUE(a.message_loop());
+  EXPECT_TRUE(a.IsRunning());
+  a.StopSoon();
+  // Calling StopSoon() a second time should be a nop.
+  a.StopSoon();
+  a.Stop();
+  // Same with Stop().
+  a.Stop();
+  EXPECT_FALSE(a.message_loop());
+  EXPECT_FALSE(a.IsRunning());
+  // Calling them when not running should also nop.
+  a.StopSoon();
+  a.Stop();
+}
+
+// TODO(gab): Enable this test in conjunction with re-enabling the sequence
+// check in Thread::Stop() as part of http://crbug.com/629139.
+TEST_F(ThreadTest, DISABLED_StopOnNonOwningThreadIsDeath) {
+  Thread a("StopOnNonOwningThreadDeath");
+  EXPECT_TRUE(a.StartAndWaitForTesting());
+
+  Thread b("NonOwningThread");
+  b.Start();
+  EXPECT_DCHECK_DEATH({
+    // Stopping |a| on |b| isn't allowed.
+    b.task_runner()->PostTask(
+        FROM_HERE, base::BindOnce(&Thread::Stop, base::Unretained(&a)));
+    // Block here so the DCHECK on |b| always happens in this scope.
+    base::PlatformThread::Sleep(base::TimeDelta::Max());
+  });
+}
+
+TEST_F(ThreadTest, TransferOwnershipAndStop) {
+  std::unique_ptr<Thread> a =
+      std::make_unique<Thread>("TransferOwnershipAndStop");
+  EXPECT_TRUE(a->StartAndWaitForTesting());
+  EXPECT_TRUE(a->IsRunning());
+
+  Thread b("TakingOwnershipThread");
+  b.Start();
+
+  base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
+                            base::WaitableEvent::InitialState::NOT_SIGNALED);
+
+  // a->DetachFromSequence() should allow |b| to use |a|'s Thread API.
+  a->DetachFromSequence();
+  b.task_runner()->PostTask(
+      FROM_HERE, base::BindOnce(
+                     [](std::unique_ptr<Thread> thread_to_stop,
+                        base::WaitableEvent* event_to_signal) -> void {
+                       thread_to_stop->Stop();
+                       event_to_signal->Signal();
+                     },
+                     std::move(a), base::Unretained(&event)));
+
+  event.Wait();
+}
+
+TEST_F(ThreadTest, StartTwice) {
+  Thread a("StartTwice");
+
+  EXPECT_FALSE(a.message_loop());
+  EXPECT_FALSE(a.IsRunning());
+
+  EXPECT_TRUE(a.Start());
+  EXPECT_TRUE(a.message_loop());
+  EXPECT_TRUE(a.IsRunning());
+
+  a.Stop();
+  EXPECT_FALSE(a.message_loop());
+  EXPECT_FALSE(a.IsRunning());
+
+  EXPECT_TRUE(a.Start());
+  EXPECT_TRUE(a.message_loop());
+  EXPECT_TRUE(a.IsRunning());
+
+  a.Stop();
+  EXPECT_FALSE(a.message_loop());
+  EXPECT_FALSE(a.IsRunning());
+}
+
+// Intentional test-only race for otherwise untestable code, won't fix.
+// https://crbug.com/634383
+#if !defined(THREAD_SANITIZER)
+TEST_F(ThreadTest, StartTwiceNonJoinableNotAllowed) {
+  LOG(ERROR) << __FUNCTION__;
+  Thread* a = new Thread("StartTwiceNonJoinable");
+  // Non-joinable threads have to be leaked for now (see
+  // Thread::Options::joinable for details).
+  ANNOTATE_LEAKING_OBJECT_PTR(a);
+
+  Thread::Options options;
+  options.joinable = false;
+  EXPECT_TRUE(a->StartWithOptions(options));
+  EXPECT_TRUE(a->message_loop());
+  EXPECT_TRUE(a->IsRunning());
+
+  // Signaled when last task on |a| is processed.
+  base::WaitableEvent last_task_event(
+      base::WaitableEvent::ResetPolicy::AUTOMATIC,
+      base::WaitableEvent::InitialState::NOT_SIGNALED);
+  a->task_runner()->PostTask(
+      FROM_HERE, base::BindOnce(&base::WaitableEvent::Signal,
+                                base::Unretained(&last_task_event)));
+
+  // StopSoon() is non-blocking, Yield() to |a|, wait for last task to be
+  // processed and a little more for QuitWhenIdle() to unwind before considering
+  // the thread "stopped".
+  a->StopSoon();
+  base::PlatformThread::YieldCurrentThread();
+  last_task_event.Wait();
+  base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(20));
+
+  // This test assumes that the above was sufficient to let the thread fully
+  // stop.
+  ASSERT_FALSE(a->IsRunning());
+
+  // Restarting it should not be allowed.
+  EXPECT_DCHECK_DEATH(a->Start());
+}
+#endif
+
+TEST_F(ThreadTest, ThreadName) {
+  Thread a("ThreadName");
+  EXPECT_TRUE(a.Start());
+  EXPECT_EQ("ThreadName", a.thread_name());
+}
+
+TEST_F(ThreadTest, ThreadId) {
+  Thread a("ThreadId0");
+  Thread b("ThreadId1");
+  a.Start();
+  b.Start();
+
+  // Post a task that calls GetThreadId() on the created thread.
+  base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
+                            base::WaitableEvent::InitialState::NOT_SIGNALED);
+  base::PlatformThreadId id_from_new_thread;
+  a.task_runner()->PostTask(
+      FROM_HERE,
+      base::BindOnce(ReturnThreadId, &a, &id_from_new_thread, &event));
+
+  // Call GetThreadId() on the current thread before calling event.Wait() so
+  // that this test can find a race issue with TSAN.
+  base::PlatformThreadId id_from_current_thread = a.GetThreadId();
+
+  // Check if GetThreadId() returns consistent value in both threads.
+  event.Wait();
+  EXPECT_EQ(id_from_current_thread, id_from_new_thread);
+
+  // A started thread should have a valid ID.
+  EXPECT_NE(base::kInvalidThreadId, a.GetThreadId());
+  EXPECT_NE(base::kInvalidThreadId, b.GetThreadId());
+
+  // Each thread should have a different thread ID.
+  EXPECT_NE(a.GetThreadId(), b.GetThreadId());
+}
+
+TEST_F(ThreadTest, ThreadIdWithRestart) {
+  Thread a("ThreadIdWithRestart");
+  base::PlatformThreadId previous_id = base::kInvalidThreadId;
+
+  for (size_t i = 0; i < 16; ++i) {
+    EXPECT_TRUE(a.Start());
+    base::PlatformThreadId current_id = a.GetThreadId();
+    EXPECT_NE(previous_id, current_id);
+    previous_id = current_id;
+    a.Stop();
+  }
+}
+
+// Make sure Init() is called after Start() and before
+// WaitUntilThreadInitialized() returns.
+TEST_F(ThreadTest, SleepInsideInit) {
+  SleepInsideInitThread t;
+  EXPECT_FALSE(t.InitCalled());
+  t.StartAndWaitForTesting();
+  EXPECT_TRUE(t.InitCalled());
+}
+
+// Make sure that the destruction sequence is:
+//
+//  (1) Thread::CleanUp()
+//  (2) MessageLoop::~MessageLoop()
+//      MessageLoopCurrent::DestructionObservers called.
+TEST_F(ThreadTest, CleanUp) {
+  EventList captured_events;
+  CapturingDestructionObserver loop_destruction_observer(&captured_events);
+
+  {
+    // Start a thread which writes its event into |captured_events|.
+    CaptureToEventList t(&captured_events);
+    EXPECT_TRUE(t.Start());
+    EXPECT_TRUE(t.message_loop());
+    EXPECT_TRUE(t.IsRunning());
+
+    // Register an observer that writes into |captured_events| once the
+    // thread's message loop is destroyed.
+    t.task_runner()->PostTask(
+        FROM_HERE,
+        base::BindOnce(&RegisterDestructionObserver,
+                       base::Unretained(&loop_destruction_observer)));
+
+    // Upon leaving this scope, the thread is deleted.
+  }
+
+  // Check the order of events during shutdown.
+  ASSERT_EQ(static_cast<size_t>(THREAD_NUM_EVENTS), captured_events.size());
+  EXPECT_EQ(THREAD_EVENT_INIT, captured_events[0]);
+  EXPECT_EQ(THREAD_EVENT_CLEANUP, captured_events[1]);
+  EXPECT_EQ(THREAD_EVENT_MESSAGE_LOOP_DESTROYED, captured_events[2]);
+}
+
+TEST_F(ThreadTest, ThreadNotStarted) {
+  Thread a("Inert");
+  EXPECT_FALSE(a.task_runner());
+}
+
+TEST_F(ThreadTest, MultipleWaitUntilThreadStarted) {
+  Thread a("MultipleWaitUntilThreadStarted");
+  EXPECT_TRUE(a.Start());
+  // It's OK to call WaitUntilThreadStarted() multiple times.
+  EXPECT_TRUE(a.WaitUntilThreadStarted());
+  EXPECT_TRUE(a.WaitUntilThreadStarted());
+}
+
+TEST_F(ThreadTest, FlushForTesting) {
+  Thread a("FlushForTesting");
+
+  // Flushing a non-running thread should be a no-op.
+  a.FlushForTesting();
+
+  ASSERT_TRUE(a.Start());
+
+  // Flushing a thread with no tasks shouldn't block.
+  a.FlushForTesting();
+
+  constexpr base::TimeDelta kSleepPerTestTask =
+      base::TimeDelta::FromMilliseconds(50);
+  constexpr size_t kNumSleepTasks = 5;
+
+  const base::TimeTicks ticks_before_post = base::TimeTicks::Now();
+
+  for (size_t i = 0; i < kNumSleepTasks; ++i) {
+    a.task_runner()->PostTask(
+        FROM_HERE,
+        base::BindOnce(&base::PlatformThread::Sleep, kSleepPerTestTask));
+  }
+
+  // All tasks should have executed, as reflected by the elapsed time.
+  a.FlushForTesting();
+  EXPECT_GE(base::TimeTicks::Now() - ticks_before_post,
+            kNumSleepTasks * kSleepPerTestTask);
+
+  a.Stop();
+
+  // Flushing a stopped thread should be a no-op.
+  a.FlushForTesting();
+}
+
+namespace {
+
+// A Thread which uses a MessageLoop on the stack. It won't start a real
+// underlying thread (instead its messages can be processed by a RunLoop on the
+// stack).
+class ExternalMessageLoopThread : public Thread {
+ public:
+  ExternalMessageLoopThread() : Thread("ExternalMessageLoopThread") {}
+
+  ~ExternalMessageLoopThread() override { Stop(); }
+
+  void InstallMessageLoop() { SetMessageLoop(&external_message_loop_); }
+
+  void VerifyUsingExternalMessageLoop(
+      bool expected_using_external_message_loop) {
+    EXPECT_EQ(expected_using_external_message_loop,
+              using_external_message_loop());
+  }
+
+ private:
+  base::MessageLoop external_message_loop_;
+
+  DISALLOW_COPY_AND_ASSIGN(ExternalMessageLoopThread);
+};
+
+}  // namespace
+
+TEST_F(ThreadTest, ExternalMessageLoop) {
+  ExternalMessageLoopThread a;
+  EXPECT_FALSE(a.message_loop());
+  EXPECT_FALSE(a.IsRunning());
+  a.VerifyUsingExternalMessageLoop(false);
+
+  a.InstallMessageLoop();
+  EXPECT_TRUE(a.message_loop());
+  EXPECT_TRUE(a.IsRunning());
+  a.VerifyUsingExternalMessageLoop(true);
+
+  bool ran = false;
+  a.task_runner()->PostTask(
+      FROM_HERE, base::BindOnce([](bool* toggled) { *toggled = true; }, &ran));
+  base::RunLoop().RunUntilIdle();
+  EXPECT_TRUE(ran);
+
+  a.Stop();
+  EXPECT_FALSE(a.message_loop());
+  EXPECT_FALSE(a.IsRunning());
+  a.VerifyUsingExternalMessageLoop(true);
+
+  // Confirm that running any remaining tasks posted from Stop() goes smoothly
+  // (e.g. https://codereview.chromium.org/2135413003/#ps300001 crashed if
+  // StopSoon() posted Thread::ThreadQuitHelper() while |run_loop_| was null).
+  base::RunLoop().RunUntilIdle();
+}
diff --git a/base/threading/watchdog.cc b/base/threading/watchdog.cc
new file mode 100644
index 0000000..6c384b1
--- /dev/null
+++ b/base/threading/watchdog.cc
@@ -0,0 +1,187 @@
+// 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 "base/threading/watchdog.h"
+
+#include "base/compiler_specific.h"
+#include "base/logging.h"
+#include "base/threading/platform_thread.h"
+
+namespace base {
+
+namespace {
+
+// When the debugger breaks (when we alarm), all the other alarms that are
+// armed will expire (also alarm).  To diminish this effect, we track any
+// delay due to debugger breaks, and we *try* to adjust the effective start
+// time of other alarms to step past the debugging break.
+// Without this safety net, any alarm will typically trigger a host of follow
+// on alarms from callers that specify old times.
+
+struct StaticData {
+  // Lock for access of static data...
+  Lock lock;
+
+  // When did we last alarm and get stuck (for a while) in a debugger?
+  TimeTicks last_debugged_alarm_time;
+
+  // How long did we sit on a break in the debugger?
+  TimeDelta last_debugged_alarm_delay;
+};
+
+StaticData* GetStaticData() {
+  static auto* static_data = new StaticData();
+  return static_data;
+}
+
+}  // namespace
+
+// Start thread running in a Disarmed state.
+Watchdog::Watchdog(const TimeDelta& duration,
+                   const std::string& thread_watched_name,
+                   bool enabled)
+  : enabled_(enabled),
+    lock_(),
+    condition_variable_(&lock_),
+    state_(DISARMED),
+    duration_(duration),
+    thread_watched_name_(thread_watched_name),
+    delegate_(this) {
+  if (!enabled_)
+    return;  // Don't start thread, or doing anything really.
+  enabled_ = PlatformThread::Create(0,  // Default stack size.
+                                    &delegate_,
+                                    &handle_);
+  DCHECK(enabled_);
+}
+
+// Notify watchdog thread, and wait for it to finish up.
+Watchdog::~Watchdog() {
+  if (!enabled_)
+    return;
+  if (!IsJoinable())
+    Cleanup();
+  condition_variable_.Signal();
+  PlatformThread::Join(handle_);
+}
+
+void Watchdog::Cleanup() {
+  if (!enabled_)
+    return;
+  {
+    AutoLock lock(lock_);
+    state_ = SHUTDOWN;
+  }
+  condition_variable_.Signal();
+}
+
+bool Watchdog::IsJoinable() {
+  if (!enabled_)
+    return true;
+  AutoLock lock(lock_);
+  return (state_ == JOINABLE);
+}
+
+void Watchdog::Arm() {
+  ArmAtStartTime(TimeTicks::Now());
+}
+
+void Watchdog::ArmSomeTimeDeltaAgo(const TimeDelta& time_delta) {
+  ArmAtStartTime(TimeTicks::Now() - time_delta);
+}
+
+// Start clock for watchdog.
+void Watchdog::ArmAtStartTime(const TimeTicks start_time) {
+  {
+    AutoLock lock(lock_);
+    start_time_ = start_time;
+    state_ = ARMED;
+  }
+  // Force watchdog to wake up, and go to sleep with the timer ticking with the
+  // proper duration.
+  condition_variable_.Signal();
+}
+
+// Disable watchdog so that it won't do anything when time expires.
+void Watchdog::Disarm() {
+  AutoLock lock(lock_);
+  state_ = DISARMED;
+  // We don't need to signal, as the watchdog will eventually wake up, and it
+  // will check its state and time, and act accordingly.
+}
+
+void Watchdog::Alarm() {
+  DVLOG(1) << "Watchdog alarmed for " << thread_watched_name_;
+}
+
+//------------------------------------------------------------------------------
+// Internal private methods that the watchdog thread uses.
+
+void Watchdog::ThreadDelegate::ThreadMain() {
+  SetThreadName();
+  TimeDelta remaining_duration;
+  StaticData* static_data = GetStaticData();
+  while (1) {
+    AutoLock lock(watchdog_->lock_);
+    while (DISARMED == watchdog_->state_)
+      watchdog_->condition_variable_.Wait();
+    if (SHUTDOWN == watchdog_->state_) {
+      watchdog_->state_ = JOINABLE;
+      return;
+    }
+    DCHECK(ARMED == watchdog_->state_);
+    remaining_duration = watchdog_->duration_ -
+        (TimeTicks::Now() - watchdog_->start_time_);
+    if (remaining_duration.InMilliseconds() > 0) {
+      // Spurios wake?  Timer drifts?  Go back to sleep for remaining time.
+      watchdog_->condition_variable_.TimedWait(remaining_duration);
+      continue;
+    }
+    // We overslept, so this seems like a real alarm.
+    // Watch out for a user that stopped the debugger on a different alarm!
+    {
+      AutoLock static_lock(static_data->lock);
+      if (static_data->last_debugged_alarm_time > watchdog_->start_time_) {
+        // False alarm: we started our clock before the debugger break (last
+        // alarm time).
+        watchdog_->start_time_ += static_data->last_debugged_alarm_delay;
+        if (static_data->last_debugged_alarm_time > watchdog_->start_time_)
+          // Too many alarms must have taken place.
+          watchdog_->state_ = DISARMED;
+        continue;
+      }
+    }
+    watchdog_->state_ = DISARMED;  // Only alarm at most once.
+    TimeTicks last_alarm_time = TimeTicks::Now();
+    {
+      AutoUnlock unlock(watchdog_->lock_);
+      watchdog_->Alarm();  // Set a break point here to debug on alarms.
+    }
+    TimeDelta last_alarm_delay = TimeTicks::Now() - last_alarm_time;
+    if (last_alarm_delay <= TimeDelta::FromMilliseconds(2))
+      continue;
+    // Ignore race of two alarms/breaks going off at roughly the same time.
+    AutoLock static_lock(static_data->lock);
+    // This was a real debugger break.
+    static_data->last_debugged_alarm_time = last_alarm_time;
+    static_data->last_debugged_alarm_delay = last_alarm_delay;
+  }
+}
+
+void Watchdog::ThreadDelegate::SetThreadName() const {
+  std::string name = watchdog_->thread_watched_name_ + " Watchdog";
+  PlatformThread::SetName(name);
+  DVLOG(1) << "Watchdog active: " << name;
+}
+
+// static
+void Watchdog::ResetStaticData() {
+  StaticData* static_data = GetStaticData();
+  AutoLock lock(static_data->lock);
+  // See https://crbug.com/734232 for why this cannot be zero-initialized.
+  static_data->last_debugged_alarm_time = TimeTicks::Min();
+  static_data->last_debugged_alarm_delay = TimeDelta();
+}
+
+}  // namespace base
diff --git a/base/threading/watchdog.h b/base/threading/watchdog.h
new file mode 100644
index 0000000..f806984
--- /dev/null
+++ b/base/threading/watchdog.h
@@ -0,0 +1,96 @@
+// 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.
+
+// The Watchdog class creates a second thread that can Alarm if a specific
+// duration of time passes without proper attention.  The duration of time is
+// specified at construction time.  The Watchdog may be used many times by
+// simply calling Arm() (to start timing) and Disarm() (to reset the timer).
+// The Watchdog is typically used under a debugger, where the stack traces on
+// other threads can be examined if/when the Watchdog alarms.
+
+// Some watchdogs will be enabled or disabled via command line switches. To
+// facilitate such code, an "enabled" argument for the constuctor can be used
+// to permanently disable the watchdog.  Disabled watchdogs don't even spawn
+// a second thread, and their methods call (Arm() and Disarm()) return very
+// quickly.
+
+#ifndef BASE_THREADING_WATCHDOG_H_
+#define BASE_THREADING_WATCHDOG_H_
+
+#include <string>
+
+#include "base/base_export.h"
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "base/synchronization/condition_variable.h"
+#include "base/synchronization/lock.h"
+#include "base/threading/platform_thread.h"
+#include "base/time/time.h"
+
+namespace base {
+
+class BASE_EXPORT Watchdog {
+ public:
+  // Constructor specifies how long the Watchdog will wait before alarming.
+  Watchdog(const TimeDelta& duration,
+           const std::string& thread_watched_name,
+           bool enabled);
+  virtual ~Watchdog();
+
+  // Notify watchdog thread to finish up. Sets the state_ to SHUTDOWN.
+  void Cleanup();
+
+  // Returns true if we state_ is JOINABLE (which indicates that Watchdog has
+  // exited).
+  bool IsJoinable();
+
+  // Start timing, and alarm when time expires (unless we're disarm()ed.)
+  void Arm();  // Arm  starting now.
+  void ArmSomeTimeDeltaAgo(const TimeDelta& time_delta);
+  void ArmAtStartTime(const TimeTicks start_time);
+
+  // Reset time, and do not set off the alarm.
+  void Disarm();
+
+  // Alarm is called if the time expires after an Arm() without someone calling
+  // Disarm().  This method can be overridden to create testable classes.
+  virtual void Alarm();
+
+  // Reset static data to initial state. Useful for tests, to ensure
+  // they are independent.
+  static void ResetStaticData();
+
+ private:
+  class ThreadDelegate : public PlatformThread::Delegate {
+   public:
+    explicit ThreadDelegate(Watchdog* watchdog) : watchdog_(watchdog) {
+    }
+    void ThreadMain() override;
+
+   private:
+    void SetThreadName() const;
+
+    Watchdog* watchdog_;
+  };
+
+  enum State {ARMED, DISARMED, SHUTDOWN, JOINABLE };
+
+  bool enabled_;
+
+  Lock lock_;  // Mutex for state_.
+  ConditionVariable condition_variable_;
+  State state_;
+  const TimeDelta duration_;  // How long after start_time_ do we alarm?
+  const std::string thread_watched_name_;
+  PlatformThreadHandle handle_;
+  ThreadDelegate delegate_;  // Store it, because it must outlive the thread.
+
+  TimeTicks start_time_;  // Start of epoch, and alarm after duration_.
+
+  DISALLOW_COPY_AND_ASSIGN(Watchdog);
+};
+
+}  // namespace base
+
+#endif  // BASE_THREADING_WATCHDOG_H_
diff --git a/base/threading/watchdog_unittest.cc b/base/threading/watchdog_unittest.cc
new file mode 100644
index 0000000..f534a86
--- /dev/null
+++ b/base/threading/watchdog_unittest.cc
@@ -0,0 +1,141 @@
+// 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 "base/threading/watchdog.h"
+
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/synchronization/spin_wait.h"
+#include "base/threading/platform_thread.h"
+#include "base/time/time.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+
+namespace {
+
+//------------------------------------------------------------------------------
+// Provide a derived class to facilitate testing.
+
+class WatchdogCounter : public Watchdog {
+ public:
+  WatchdogCounter(const TimeDelta& duration,
+                  const std::string& thread_watched_name,
+                  bool enabled)
+      : Watchdog(duration, thread_watched_name, enabled),
+        alarm_counter_(0) {
+  }
+
+  ~WatchdogCounter() override = default;
+
+  void Alarm() override {
+    alarm_counter_++;
+    Watchdog::Alarm();
+  }
+
+  int alarm_counter() { return alarm_counter_; }
+
+ private:
+  int alarm_counter_;
+
+  DISALLOW_COPY_AND_ASSIGN(WatchdogCounter);
+};
+
+class WatchdogTest : public testing::Test {
+ public:
+  void SetUp() override { Watchdog::ResetStaticData(); }
+};
+
+}  // namespace
+
+//------------------------------------------------------------------------------
+// Actual tests
+
+// Minimal constructor/destructor test.
+TEST_F(WatchdogTest, StartupShutdownTest) {
+  Watchdog watchdog1(TimeDelta::FromMilliseconds(300), "Disabled", false);
+  Watchdog watchdog2(TimeDelta::FromMilliseconds(300), "Enabled", true);
+}
+
+// Test ability to call Arm and Disarm repeatedly.
+TEST_F(WatchdogTest, ArmDisarmTest) {
+  Watchdog watchdog1(TimeDelta::FromMilliseconds(300), "Disabled", false);
+  watchdog1.Arm();
+  watchdog1.Disarm();
+  watchdog1.Arm();
+  watchdog1.Disarm();
+
+  Watchdog watchdog2(TimeDelta::FromMilliseconds(300), "Enabled", true);
+  watchdog2.Arm();
+  watchdog2.Disarm();
+  watchdog2.Arm();
+  watchdog2.Disarm();
+}
+
+// Make sure a basic alarm fires when the time has expired.
+TEST_F(WatchdogTest, AlarmTest) {
+  WatchdogCounter watchdog(TimeDelta::FromMilliseconds(10), "Enabled", true);
+  watchdog.Arm();
+  SPIN_FOR_TIMEDELTA_OR_UNTIL_TRUE(TimeDelta::FromMinutes(5),
+                                   watchdog.alarm_counter() > 0);
+  EXPECT_EQ(1, watchdog.alarm_counter());
+}
+
+// Make sure a basic alarm fires when the time has expired.
+TEST_F(WatchdogTest, AlarmPriorTimeTest) {
+  WatchdogCounter watchdog(TimeDelta(), "Enabled2", true);
+  // Set a time in the past.
+  watchdog.ArmSomeTimeDeltaAgo(TimeDelta::FromSeconds(2));
+  // It should instantly go off, but certainly in less than 5 minutes.
+  SPIN_FOR_TIMEDELTA_OR_UNTIL_TRUE(TimeDelta::FromMinutes(5),
+                                   watchdog.alarm_counter() > 0);
+
+  EXPECT_EQ(1, watchdog.alarm_counter());
+}
+
+// Make sure a disable alarm does nothing, even if we arm it.
+TEST_F(WatchdogTest, ConstructorDisabledTest) {
+  WatchdogCounter watchdog(TimeDelta::FromMilliseconds(10), "Disabled", false);
+  watchdog.Arm();
+  // Alarm should not fire, as it was disabled.
+  PlatformThread::Sleep(TimeDelta::FromMilliseconds(500));
+  EXPECT_EQ(0, watchdog.alarm_counter());
+}
+
+// Make sure Disarming will prevent firing, even after Arming.
+TEST_F(WatchdogTest, DisarmTest) {
+  WatchdogCounter watchdog(TimeDelta::FromSeconds(1), "Enabled3", true);
+
+  TimeTicks start = TimeTicks::Now();
+  watchdog.Arm();
+  // Sleep a bit, but not past the alarm point.
+  PlatformThread::Sleep(TimeDelta::FromMilliseconds(100));
+  watchdog.Disarm();
+  TimeTicks end = TimeTicks::Now();
+
+  if (end - start > TimeDelta::FromMilliseconds(500)) {
+    LOG(WARNING) << "100ms sleep took over 500ms, making the results of this "
+                 << "timing-sensitive test suspicious.  Aborting now.";
+    return;
+  }
+
+  // Alarm should not have fired before it was disarmed.
+  EXPECT_EQ(0, watchdog.alarm_counter());
+
+  // Sleep past the point where it would have fired if it wasn't disarmed,
+  // and verify that it didn't fire.
+  PlatformThread::Sleep(TimeDelta::FromSeconds(1));
+  EXPECT_EQ(0, watchdog.alarm_counter());
+
+  // ...but even after disarming, we can still use the alarm...
+  // Set a time greater than the timeout into the past.
+  watchdog.ArmSomeTimeDeltaAgo(TimeDelta::FromSeconds(10));
+  // It should almost instantly go off, but certainly in less than 5 minutes.
+  SPIN_FOR_TIMEDELTA_OR_UNTIL_TRUE(TimeDelta::FromMinutes(5),
+                                   watchdog.alarm_counter() > 0);
+
+  EXPECT_EQ(1, watchdog.alarm_counter());
+}
+
+}  // namespace base