// 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 "content/public/test/test_browser_thread.h"

#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop.h"
#include "base/threading/thread.h"
#include "build/build_config.h"
#include "content/browser/browser_thread_impl.h"
#include "content/browser/notification_service_impl.h"

#if defined(OS_WIN)
#include "base/win/scoped_com_initializer.h"
#endif

namespace content {

class TestBrowserThreadImpl : public BrowserThreadImpl {
 public:
  explicit TestBrowserThreadImpl(BrowserThread::ID identifier)
      : BrowserThreadImpl(identifier) {}

  TestBrowserThreadImpl(BrowserThread::ID identifier,
                        base::MessageLoop* message_loop)
      : BrowserThreadImpl(identifier, message_loop) {}

  ~TestBrowserThreadImpl() override { Stop(); }

  void Init() override {
#if defined(OS_WIN)
    com_initializer_ = std::make_unique<base::win::ScopedCOMInitializer>();
#endif

    notification_service_ = std::make_unique<NotificationServiceImpl>();
    BrowserThreadImpl::Init();
  }

  void CleanUp() override {
    BrowserThreadImpl::CleanUp();
    notification_service_.reset();
#if defined(OS_WIN)
    com_initializer_.reset();
#endif
  }

 private:
#if defined(OS_WIN)
  std::unique_ptr<base::win::ScopedCOMInitializer> com_initializer_;
#endif

  std::unique_ptr<NotificationService> notification_service_;

  DISALLOW_COPY_AND_ASSIGN(TestBrowserThreadImpl);
};

TestBrowserThread::TestBrowserThread(BrowserThread::ID identifier)
    : impl_(new TestBrowserThreadImpl(identifier)), identifier_(identifier) {}

TestBrowserThread::TestBrowserThread(BrowserThread::ID identifier,
                                     base::MessageLoop* message_loop)
    : impl_(new TestBrowserThreadImpl(identifier, message_loop)),
      identifier_(identifier) {}

TestBrowserThread::~TestBrowserThread() {
  // The upcoming BrowserThreadImpl::ResetGlobalsForTesting() call requires that
  // |impl_| have triggered the shutdown phase for its BrowserThread::ID. This
  // either happens when the thread is stopped (if real) or destroyed (when fake
  // -- i.e. using an externally provided MessageLoop).
  impl_.reset();

  // Resets BrowserThreadImpl's globals so that |impl_| is no longer bound to
  // |identifier_|. This is fine since the underlying MessageLoop has already
  // been flushed and deleted in Stop(). In the case of an externally provided
  // MessageLoop however, this means that TaskRunners obtained through
  // |BrowserThreadImpl::GetTaskRunnerForThread(identifier_)| will no longer
  // recognize their BrowserThreadImpl for RunsTasksInCurrentSequence(). This
  // happens most often when such verifications are made from
  // MessageLoop::DestructionObservers. Callers that care to work around that
  // should instead use this shutdown sequence:
  //   1) TestBrowserThread::Stop()
  //   2) ~MessageLoop()
  //   3) ~TestBrowserThread()
  // (~TestBrowserThreadBundle() does this).
  BrowserThreadImpl::ResetGlobalsForTesting(identifier_);
}

bool TestBrowserThread::Start() {
  return impl_->Start();
}

bool TestBrowserThread::StartAndWaitForTesting() {
  return impl_->StartAndWaitForTesting();
}

bool TestBrowserThread::StartIOThread() {
  base::Thread::Options options;
  options.message_loop_type = base::MessageLoop::TYPE_IO;
  return impl_->StartWithOptions(options);
}

void TestBrowserThread::InitIOThreadDelegate() {
  impl_->InitIOThreadDelegate();
}

void TestBrowserThread::Stop() {
  impl_->Stop();
}

bool TestBrowserThread::IsRunning() {
  return impl_->IsRunning();
}

}  // namespace content
