Reland "Refactor BrowserThreadImpl, BrowserProcessSubThread, and BrowserMainLoop"

This is a reland of d260e9cf660f062b203692601cf9b6ccb27f3d1e

It was reverted because of crbug.com/824716, these weren't new crashes
but known crashes mislabeled as a fallout of this change.
http://cl/190471699 fixes the crash backend to not rely on
"content::BrowserThreadImpl::IOThreadRun" being in the signature.

Only diff in this CL is to use base::debug::Alias() in methods that we
don't want optimized (i.e. IOThreadRun) out as CHECK_GT was seen as
optimized out in some of the reported crashes (even though the same
pattern as before was used by this CL..?)

Original change's description:
> Refactor BrowserThreadImpl, BrowserProcessSubThread, and BrowserMainLoop
>
> This brings back the invariant that BrowserThread::IO isn't available
> before BrowserMainLoop::CreateThreads(). This was broken to fix issue
> 729596 to bring up the thread earlier for ServiceManager but it is
> important that code that posts to BrowserThread::IO statically have an
> happens-after relationship to BrowserMainLoop::CreateThreads(). Exposing
> it statically earlier put that invariant at risk.
>
> Thankfully fixing issue 815225 resulted in finally reaching the long
> sought goal of only having BrowserThread::UI/IO. Now that the IO thread
> is also kicked off before it's named statically, BrowserThreadImpl no
> longer needs to be a base::Thread, hence this refactoring.
>
> Before this CL:
>  * BrowserThreadImpl was a base::Thread
>    (could be a fake thread if SetMessageLoop was used)
>  * BrowserProcessSubThread was a BrowserThreadImpl
>    (performed a bit more initialization)
>  * BrowserProcessSubThread was only used in production (in
>    BrowserMainLoop)
>  * BrowserThreadImpl was used for fake threads (BrowserMainLoop for
>    BrowserThread::UI) and for testing (TestBrowserThread(Impl)).
>  * BrowserThreadImpl overrode Init/Run/CleanUp() from base::Thread to
>    perform some sanity checks as well as drive IOThread's Delegate (ref.
>    BrowserThread::SetIOThreadDelegate())
>  * BrowserProcessSubThread re-overrode Init/Run/CleanUp() to perform
>    per-thread //content initialization (tests missed out on that per
>    TestBrowserThread bypassing BrowserProcessSubThread by directly
>    subclassing BrowserThreadImpl).
>
> With this CL:
>  * BrowserThreadImpl is merely a scoped object that binds a provided
>    SingleThreadTaskRunner to a BrowserThread::ID.
>  * BrowserProcessSubThread is a base::Thread and performs all of the
>    initialization and cleanup specific to //content (this means it now
>    also manages BrowserThread::SetIOThreadDelegate())
>  * BrowserProcessSubThread can be brought up early before being bound to
>    a BrowserThread::ID (BrowserMainLoop handles that through
>    BrowserProcessSubThread ::RegisterAsBrowserThread())
>
> Unfortunate exceptions required for this CL:
>  * IOThread::Init() (invoked through BrowserThreadDelegate) perfoms
>    blocking operations this was previously performed before installed
>    the ThreadRestrictions on BrowserThread::IO. But now that //content
>    is initialized after bringing up the thread, a
>    base::ScopedAllowBlocking is required in scope of IOThread::Init().
>  * TestBrowserThread previously bypassing BrowserProcessSubThread by
>    directly subclassing BrowserThreadImpl meant it wasn't subject to
>    ThreadRestrictions (unfortunate becomes it denies allowance
>    verification to product code running in unit tests). Adding it back
>    causes DCHECKs, as such
>    BrowserProcessSubThread::AllowBlockingForTesting was added to allow
>    this CL to pass CQ.
>
> Of note:
>  * BrowserProcessSubThread is still written as though it supports many
>    BrowserThread::IDs but in practice it's mostly always
>    BrowserThread::IO (except in ThreadWatcherTest I think). This change
>    was big enough that I didn't bother also breaking that
>    generalization.
>  * BrowserThreadImpl's constructor was made private to ensure only
>    BrowserProcessSubThread and a few select callers get to drive it (to
>    avoid previous missed initialization issues)
>  * Atomics to manage BrowserThread::SetIOThreadDelegate were removed.
>    Restriction was instead added that this only be called before
>    initialization and after shutdown (this was already the case).
>
> Follow-ups to this CL:
>  * //ios duplicates this logic and will need to undergo the same change
>    as a follow-up
>  * Fixing ios will allow removal of base::Thread::SetMessageLoop hack :)
>  * Removing BrowserThreadGlobals::lock_ to address crbug.com/821034 will
>    be much easier
>  * BrowserThread post APIs should DCHECK rather than no-op if using a
>    BrowserThread::ID before it's registered.
>
> Bug: 815225, 821034, 729596
> Change-Id: If1038f23079df72203b1e95c7d26647f8824a726
> Reviewed-on: https://chromium-review.googlesource.com/969104
> Reviewed-by: John Abd-El-Malek <[email protected]>
> Commit-Queue: Gabriel Charette <[email protected]>
> Cr-Commit-Position: refs/heads/master@{#544440}

[email protected]

Bug: 815225, 821034, 729596, 824716
Change-Id: I9a180975c69a008f8519d1d3d44663aa58a74a92
Reviewed-on: https://chromium-review.googlesource.com/980793
Reviewed-by: John Abd-El-Malek <[email protected]>
Reviewed-by: Gabriel Charette <[email protected]>
Commit-Queue: Gabriel Charette <[email protected]>
Cr-Commit-Position: refs/heads/master@{#546104}
diff --git a/content/browser/browser_process_sub_thread.h b/content/browser/browser_process_sub_thread.h
index 8122cdb..f4b8799 100644
--- a/content/browser/browser_process_sub_thread.h
+++ b/content/browser/browser_process_sub_thread.h
@@ -8,8 +8,9 @@
 #include <memory>
 
 #include "base/macros.h"
+#include "base/threading/thread.h"
+#include "base/threading/thread_checker.h"
 #include "build/build_config.h"
-#include "content/browser/browser_thread_impl.h"
 #include "content/common/content_export.h"
 #include "content/public/browser/browser_thread.h"
 
@@ -28,29 +29,57 @@
 namespace content {
 
 // ----------------------------------------------------------------------------
-// BrowserProcessSubThread
-//
-// This simple thread object is used for the specialized threads that the
-// BrowserProcess spins up.
+// A BrowserProcessSubThread is a physical thread backing a BrowserThread.
 //
 // Applications must initialize the COM library before they can call
 // COM library functions other than CoGetMalloc and memory allocation
 // functions, so this class initializes COM for those users.
-class CONTENT_EXPORT BrowserProcessSubThread : public BrowserThreadImpl {
+class CONTENT_EXPORT BrowserProcessSubThread : public base::Thread {
  public:
+  // Constructs a BrowserProcessSubThread for |identifier|.
   explicit BrowserProcessSubThread(BrowserThread::ID identifier);
-  BrowserProcessSubThread(BrowserThread::ID identifier,
-                          base::MessageLoop* message_loop);
   ~BrowserProcessSubThread() override;
 
+  // Registers this thread to represent |identifier_| in the browser_thread.h
+  // API. This thread must already be running when this is called. This can only
+  // be called once per BrowserProcessSubThread instance.
+  void RegisterAsBrowserThread();
+
+  // Ideally there wouldn't be a special blanket allowance to block the
+  // BrowserThreads in tests but TestBrowserThreadImpl previously bypassed
+  // BrowserProcessSubThread and hence wasn't subject to ThreadRestrictions...
+  // Flipping that around in favor of explicit scoped allowances would be
+  // preferable but a non-trivial amount of work. Can only be called before
+  // starting this BrowserProcessSubThread.
+  void AllowBlockingForTesting();
+
  protected:
   void Init() override;
+  void Run(base::RunLoop* run_loop) override;
   void CleanUp() override;
 
  private:
-  // These methods encapsulate cleanup that needs to happen on the IO thread
-  // before we call the embedder's CleanUp function.
-  void IOThreadPreCleanUp();
+  // Second Init() phase that must happen on this thread but can only happen
+  // after it's promoted to a BrowserThread in |RegisterAsBrowserThread()|.
+  void CompleteInitializationOnBrowserThread();
+
+  // These methods merely forwards to Thread::Run() but are useful to identify
+  // which BrowserThread this represents in stack traces.
+  void UIThreadRun(base::RunLoop* run_loop);
+  void IOThreadRun(base::RunLoop* run_loop);
+
+  // This method encapsulates cleanup that needs to happen on the IO thread.
+  void IOThreadCleanUp();
+
+  const BrowserThread::ID identifier_;
+
+  // BrowserThreads are not allowed to do file I/O nor wait on synchronization
+  // primivives except when explicitly allowed in tests.
+  bool is_blocking_allowed_for_testing_ = false;
+
+  // The BrowserThread registration for this |identifier_|, initialized in
+  // RegisterAsBrowserThread().
+  std::unique_ptr<BrowserThreadImpl> browser_thread_;
 
 #if defined (OS_WIN)
   std::unique_ptr<base::win::ScopedCOMInitializer> com_initializer_;
@@ -59,6 +88,8 @@
   // Each specialized thread has its own notification service.
   std::unique_ptr<NotificationService> notification_service_;
 
+  THREAD_CHECKER(browser_thread_checker_);
+
   DISALLOW_COPY_AND_ASSIGN(BrowserProcessSubThread);
 };