// 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/command_line.h"
#include "content/browser/child_process_launcher.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/shell/browser/shell.h"

namespace {

class MockChildProcessLauncherClient
    : public content::ChildProcessLauncher::Client {
 public:
  MockChildProcessLauncherClient()
      : client_(nullptr), simulate_failure_(false) {}

  void OnProcessLaunched() override {
    if (simulate_failure_)
      client_->OnProcessLaunchFailed();
    else
      client_->OnProcessLaunched();
  };
  void OnProcessLaunchFailed() override { client_->OnProcessLaunchFailed(); };

  content::ChildProcessLauncher::Client* client_;
  bool simulate_failure_;
};

}

namespace content {

class ChildProcessLauncherBrowserTest : public ContentBrowserTest {};

class StatsTableBrowserTest : public ChildProcessLauncherBrowserTest {
 public:
  void SetUpCommandLine(base::CommandLine* command_line) override {
    command_line->AppendSwitch(switches::kEnableStatsTable);
  }
};

IN_PROC_BROWSER_TEST_F(StatsTableBrowserTest, StartWithStatTable) {
  NavigateToURL(shell(), GURL("about:blank"));
}

IN_PROC_BROWSER_TEST_F(ChildProcessLauncherBrowserTest, ChildSpawnFail) {
  GURL url("about:blank");
  Shell* window = shell();
  MockChildProcessLauncherClient* client(nullptr);

  // Navigate once and simulate a process failing to spawn.
  TestNavigationObserver nav_observer1(window->web_contents(), 1);
  client = new MockChildProcessLauncherClient;
  window->LoadURL(url);
  client->client_ = static_cast<RenderProcessHostImpl*>(
      window->web_contents()->GetRenderProcessHost())
      ->child_process_launcher_->ReplaceClientForTest(client);
  client->simulate_failure_ = true;
  nav_observer1.Wait();
  delete client;
  NavigationEntry* last_entry =
      shell()->web_contents()->GetController().GetLastCommittedEntry();
  // Make sure we didn't navigate.
  CHECK(!last_entry);

  // Navigate again and let the process spawn correctly.
  TestNavigationObserver nav_observer2(window->web_contents(), 1);
  window->LoadURL(url);
  nav_observer2.Wait();
  last_entry = shell()->web_contents()->GetController().GetLastCommittedEntry();
  // Make sure that we navigated to the proper URL.
  CHECK(last_entry && last_entry->GetPageType() == PAGE_TYPE_NORMAL);
  CHECK(shell()->web_contents()->GetLastCommittedURL() == url);

  // Navigate again, using the same renderer.
  url = GURL("data:text/html,dataurl");
  TestNavigationObserver nav_observer3(window->web_contents(), 1);
  window->LoadURL(url);
  nav_observer3.Wait();
  last_entry = shell()->web_contents()->GetController().GetLastCommittedEntry();
  // Make sure that we navigated to the proper URL.
  CHECK(last_entry && last_entry->GetPageType() == PAGE_TYPE_NORMAL);
  CHECK(shell()->web_contents()->GetLastCommittedURL() == url);
}

}  // namespace content
