// 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 "third_party/blink/renderer/platform/bindings/dom_wrapper_world.h"

#include "base/single_thread_task_runner.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_initializer.h"
#include "third_party/blink/renderer/core/workers/worker_backing_thread.h"
#include "third_party/blink/renderer/core/workers/worker_backing_thread_startup_data.h"
#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
#include "third_party/blink/renderer/platform/cross_thread_functional.h"
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
#include "third_party/blink/renderer/platform/web_thread_supporting_gc.h"

namespace blink {
namespace {

Vector<scoped_refptr<DOMWrapperWorld>> CreateIsolatedWorlds(
    v8::Isolate* isolate) {
  Vector<scoped_refptr<DOMWrapperWorld>> worlds;
  worlds.push_back(DOMWrapperWorld::EnsureIsolatedWorld(
      isolate, DOMWrapperWorld::kMainWorldId + 1));
  worlds.push_back(DOMWrapperWorld::EnsureIsolatedWorld(
      isolate, DOMWrapperWorld::kDOMWrapperWorldEmbedderWorldIdLimit - 1));
  EXPECT_TRUE(worlds[0]->IsIsolatedWorld());
  EXPECT_TRUE(worlds[1]->IsIsolatedWorld());
  return worlds;
}

Vector<scoped_refptr<DOMWrapperWorld>> CreateWorlds(v8::Isolate* isolate) {
  Vector<scoped_refptr<DOMWrapperWorld>> worlds;
  worlds.push_back(
      DOMWrapperWorld::Create(isolate, DOMWrapperWorld::WorldType::kWorker));
  worlds.push_back(
      DOMWrapperWorld::Create(isolate, DOMWrapperWorld::WorldType::kWorker));
  worlds.push_back(
      DOMWrapperWorld::Create(isolate, DOMWrapperWorld::WorldType::kWorker));
  EXPECT_TRUE(worlds[0]->IsWorkerWorld());
  EXPECT_TRUE(worlds[1]->IsWorkerWorld());
  EXPECT_TRUE(worlds[2]->IsWorkerWorld());

  // World ids should be unique.
  HashSet<int> world_ids;
  EXPECT_TRUE(world_ids.insert(worlds[0]->GetWorldId()).is_new_entry);
  EXPECT_TRUE(world_ids.insert(worlds[1]->GetWorldId()).is_new_entry);
  EXPECT_TRUE(world_ids.insert(worlds[2]->GetWorldId()).is_new_entry);

  return worlds;
}

void WorkerThreadFunc(
    WorkerBackingThread* thread,
    scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner) {
  thread->InitializeOnBackingThread(
      WorkerBackingThreadStartupData::CreateDefault());

  // Worlds on the main thread should not be visible from the worker thread.
  Vector<scoped_refptr<DOMWrapperWorld>> retrieved_worlds;
  DOMWrapperWorld::AllWorldsInCurrentThread(retrieved_worlds);
  EXPECT_TRUE(retrieved_worlds.IsEmpty());

  // Create worlds on the worker thread and verify them.
  Vector<scoped_refptr<DOMWrapperWorld>> worlds =
      CreateWorlds(thread->GetIsolate());
  DOMWrapperWorld::AllWorldsInCurrentThread(retrieved_worlds);
  EXPECT_EQ(worlds.size(), retrieved_worlds.size());
  retrieved_worlds.clear();

  // Dispose of remaining worlds.
  for (scoped_refptr<DOMWrapperWorld>& world : worlds) {
    if (world->IsWorkerWorld())
      world->Dispose();
  }
  worlds.clear();

  thread->ShutdownOnBackingThread();
  PostCrossThreadTask(*main_thread_task_runner, FROM_HERE,
                      CrossThreadBind(&test::ExitRunLoop));
}

TEST(DOMWrapperWorldTest, Basic) {
  // Create the main world and verify it.
  DOMWrapperWorld& main_world = DOMWrapperWorld::MainWorld();
  EXPECT_TRUE(main_world.IsMainWorld());
  EXPECT_FALSE(DOMWrapperWorld::NonMainWorldsExistInMainThread());
  Vector<scoped_refptr<DOMWrapperWorld>> retrieved_worlds;
  DOMWrapperWorld::AllWorldsInCurrentThread(retrieved_worlds);
  EXPECT_EQ(1u, retrieved_worlds.size());
  EXPECT_TRUE(retrieved_worlds[0]->IsMainWorld());
  retrieved_worlds.clear();

  // Create isolated worlds and verify them.
  V8TestingScope scope;
  Vector<scoped_refptr<DOMWrapperWorld>> isolated_worlds =
      CreateIsolatedWorlds(scope.GetIsolate());
  EXPECT_TRUE(DOMWrapperWorld::NonMainWorldsExistInMainThread());
  DOMWrapperWorld::AllWorldsInCurrentThread(retrieved_worlds);
  EXPECT_EQ(isolated_worlds.size() + 1, retrieved_worlds.size());

  // Create other worlds and verify them.
  Vector<scoped_refptr<DOMWrapperWorld>> worlds =
      CreateWorlds(scope.GetIsolate());
  EXPECT_TRUE(DOMWrapperWorld::NonMainWorldsExistInMainThread());
  retrieved_worlds.clear();
  DOMWrapperWorld::AllWorldsInCurrentThread(retrieved_worlds);
  EXPECT_EQ(isolated_worlds.size() + worlds.size() + 1,
            retrieved_worlds.size());
  retrieved_worlds.clear();

  // Start a worker thread and create worlds on that.
  std::unique_ptr<WorkerBackingThread> thread = WorkerBackingThread::Create(
      ThreadCreationParams(WebThreadType::kTestThread)
          .SetThreadNameForTest("DOMWrapperWorld test thread"));
  scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner =
      Thread::Current()->GetTaskRunner();
  thread->BackingThread().PostTask(
      FROM_HERE,
      CrossThreadBind(&WorkerThreadFunc, CrossThreadUnretained(thread.get()),
                      std::move(main_thread_task_runner)));
  test::EnterRunLoop();

  // Worlds on the worker thread should not be visible from the main thread.
  EXPECT_TRUE(DOMWrapperWorld::NonMainWorldsExistInMainThread());
  DOMWrapperWorld::AllWorldsInCurrentThread(retrieved_worlds);
  EXPECT_EQ(isolated_worlds.size() + worlds.size() + 1,
            retrieved_worlds.size());
  retrieved_worlds.clear();

  // Dispose of the isolated worlds.
  isolated_worlds.clear();
  EXPECT_TRUE(DOMWrapperWorld::NonMainWorldsExistInMainThread());
  DOMWrapperWorld::AllWorldsInCurrentThread(retrieved_worlds);
  EXPECT_EQ(worlds.size() + 1, retrieved_worlds.size());
  retrieved_worlds.clear();

  // Dispose of the other worlds.
  for (scoped_refptr<DOMWrapperWorld>& world : worlds) {
    if (world->IsWorkerWorld())
      world->Dispose();
  }
  worlds.clear();
  EXPECT_FALSE(DOMWrapperWorld::NonMainWorldsExistInMainThread());
  DOMWrapperWorld::AllWorldsInCurrentThread(retrieved_worlds);
  EXPECT_EQ(1u, retrieved_worlds.size());
}

}  // namespace
}  // namespace blink
