// 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 "chrome/browser/ui/webui/net_internals/net_internals_ui_browsertest.h"

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/io_thread.h"
#include "chrome/browser/net/chrome_net_log.h"
#include "chrome/browser/prerender/prerender_manager.h"
#include "chrome/browser/prerender/prerender_manager_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/webui/net_internals/net_internals_ui.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui_message_handler.h"
#include "net/base/address_list.h"
#include "net/base/net_errors.h"
#include "net/base/net_log.h"
#include "net/base/net_log_logger.h"
#include "net/dns/host_cache.h"
#include "net/dns/host_resolver.h"
#include "net/dns/mock_host_resolver.h"
#include "net/http/http_network_session.h"
#include "net/http/http_transaction_factory.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"

using content::BrowserThread;
using content::WebUIMessageHandler;

namespace {

// Called on IO thread.  Adds an entry to the cache for the specified hostname.
// Either |net_error| must be net::OK, or |address| must be NULL.
void AddCacheEntryOnIOThread(net::URLRequestContextGetter* context_getter,
                             const std::string& hostname,
                             const std::string& ip_literal,
                             int net_error,
                             int expire_days_from_now) {
  ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
  net::URLRequestContext* context = context_getter->GetURLRequestContext();
  net::HostCache* cache = context->host_resolver()->GetHostCache();
  ASSERT_TRUE(cache);

  net::HostCache::Key key(hostname, net::ADDRESS_FAMILY_UNSPECIFIED, 0);
  base::TimeDelta ttl = base::TimeDelta::FromDays(expire_days_from_now);

  net::AddressList address_list;
  if (net_error == net::OK) {
    // If |net_error| does not indicate an error, convert |ip_literal| to a
    // net::AddressList, so it can be used with the cache.
    int rv = net::ParseAddressList(ip_literal, hostname, &address_list);
    ASSERT_EQ(net::OK, rv);
  } else {
    ASSERT_TRUE(ip_literal.empty());
  }

  // Add entry to the cache.
  cache->Set(net::HostCache::Key(hostname, net::ADDRESS_FAMILY_UNSPECIFIED, 0),
             net::HostCache::Entry(net_error, address_list),
             base::TimeTicks::Now(),
             ttl);
}

}  // namespace

////////////////////////////////////////////////////////////////////////////////
// NetInternalsTest::MessageHandler
////////////////////////////////////////////////////////////////////////////////

// Class to handle messages from the renderer needed by certain tests.
class NetInternalsTest::MessageHandler : public content::WebUIMessageHandler {
 public:
  explicit MessageHandler(NetInternalsTest* net_internals_test);

 private:
  virtual void RegisterMessages() override;

  // Runs NetInternalsTest.callback with the given value.
  void RunJavascriptCallback(base::Value* value);

  // Takes a string and provides the corresponding URL from the test server,
  // which must already have been started.
  void GetTestServerURL(const base::ListValue* list_value);

  // Called on UI thread.  Adds an entry to the cache for the specified
  // hostname by posting a task to the IO thread.  Takes the host name,
  // ip address, net error code, and expiration time in days from now
  // as parameters.  If the error code indicates failure, the ip address
  // must be an empty string.
  void AddCacheEntry(const base::ListValue* list_value);

  // Opens the given URL in a new tab.
  void LoadPage(const base::ListValue* list_value);

  // Opens a page in a new tab that prerenders the given URL.
  void PrerenderPage(const base::ListValue* list_value);

  // Navigates to the prerender in the background tab. This assumes that
  // there is a "Click()" function in the background tab which will navigate
  // there, and that the background tab exists at slot 1.
  void NavigateToPrerender(const base::ListValue* list_value);

  // Creates an incognito browser.  Once creation is complete, passes a
  // message to the Javascript test harness.
  void CreateIncognitoBrowser(const base::ListValue* list_value);

  // Closes an incognito browser created with CreateIncognitoBrowser.
  void CloseIncognitoBrowser(const base::ListValue* list_value);

  // Creates a simple log with a NetLogLogger, and returns it to the
  // Javascript callback.
  void GetNetLogLoggerLog(const base::ListValue* list_value);

  Browser* browser() { return net_internals_test_->browser(); }

  NetInternalsTest* net_internals_test_;
  Browser* incognito_browser_;

  DISALLOW_COPY_AND_ASSIGN(MessageHandler);
};

NetInternalsTest::MessageHandler::MessageHandler(
    NetInternalsTest* net_internals_test)
    : net_internals_test_(net_internals_test),
      incognito_browser_(NULL) {
}

void NetInternalsTest::MessageHandler::RegisterMessages() {
  web_ui()->RegisterMessageCallback("getTestServerURL",
      base::Bind(&NetInternalsTest::MessageHandler::GetTestServerURL,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("addCacheEntry",
      base::Bind(&NetInternalsTest::MessageHandler::AddCacheEntry,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("loadPage",
      base::Bind(&NetInternalsTest::MessageHandler::LoadPage,
                  base::Unretained(this)));
  web_ui()->RegisterMessageCallback("prerenderPage",
      base::Bind(&NetInternalsTest::MessageHandler::PrerenderPage,
                  base::Unretained(this)));
  web_ui()->RegisterMessageCallback("navigateToPrerender",
      base::Bind(&NetInternalsTest::MessageHandler::NavigateToPrerender,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("createIncognitoBrowser",
      base::Bind(&NetInternalsTest::MessageHandler::CreateIncognitoBrowser,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("closeIncognitoBrowser",
      base::Bind(&NetInternalsTest::MessageHandler::CloseIncognitoBrowser,
                 base::Unretained(this)));
  web_ui()->RegisterMessageCallback("getNetLogLoggerLog",
      base::Bind(
          &NetInternalsTest::MessageHandler::GetNetLogLoggerLog,
          base::Unretained(this)));
}

void NetInternalsTest::MessageHandler::RunJavascriptCallback(
    base::Value* value) {
  web_ui()->CallJavascriptFunction("NetInternalsTest.callback", *value);
}

void NetInternalsTest::MessageHandler::GetTestServerURL(
    const base::ListValue* list_value) {
  ASSERT_TRUE(net_internals_test_->StartTestServer());
  std::string path;
  ASSERT_TRUE(list_value->GetString(0, &path));
  GURL url = net_internals_test_->test_server()->GetURL(path);
  scoped_ptr<base::Value> url_value(new base::StringValue(url.spec()));
  RunJavascriptCallback(url_value.get());
}

void NetInternalsTest::MessageHandler::AddCacheEntry(
    const base::ListValue* list_value) {
  std::string hostname;
  std::string ip_literal;
  double net_error;
  double expire_days_from_now;
  ASSERT_TRUE(list_value->GetString(0, &hostname));
  ASSERT_TRUE(list_value->GetString(1, &ip_literal));
  ASSERT_TRUE(list_value->GetDouble(2, &net_error));
  ASSERT_TRUE(list_value->GetDouble(3, &expire_days_from_now));
  ASSERT_TRUE(browser());

  BrowserThread::PostTask(
      BrowserThread::IO, FROM_HERE,
      base::Bind(&AddCacheEntryOnIOThread,
                 make_scoped_refptr(browser()->profile()->GetRequestContext()),
                 hostname,
                 ip_literal,
                 static_cast<int>(net_error),
                 static_cast<int>(expire_days_from_now)));
}

void NetInternalsTest::MessageHandler::LoadPage(
    const base::ListValue* list_value) {
  std::string url;
  ASSERT_TRUE(list_value->GetString(0, &url));
  LOG(WARNING) << "url: [" << url << "]";
  ui_test_utils::NavigateToURLWithDisposition(
      browser(),
      GURL(url),
      NEW_BACKGROUND_TAB,
      ui_test_utils::BROWSER_TEST_NONE);
}

void NetInternalsTest::MessageHandler::PrerenderPage(
    const base::ListValue* list_value) {
  std::string prerender_url;
  ASSERT_TRUE(list_value->GetString(0, &prerender_url));
  GURL loader_url =
      net_internals_test_->CreatePrerenderLoaderUrl(GURL(prerender_url));
  ui_test_utils::NavigateToURLWithDisposition(
      browser(),
      GURL(loader_url),
      NEW_BACKGROUND_TAB,
      ui_test_utils::BROWSER_TEST_NONE);
}

void NetInternalsTest::MessageHandler::NavigateToPrerender(
    const base::ListValue* list_value) {
  std::string url;
  ASSERT_TRUE(list_value->GetString(0, &url));
  content::RenderFrameHost* frame =
      browser()->tab_strip_model()->GetWebContentsAt(1)->GetMainFrame();
  frame->ExecuteJavaScript(
      base::ASCIIToUTF16(base::StringPrintf("Click('%s')", url.c_str())));
}

void NetInternalsTest::MessageHandler::CreateIncognitoBrowser(
    const base::ListValue* list_value) {
  ASSERT_FALSE(incognito_browser_);
  incognito_browser_ = net_internals_test_->CreateIncognitoBrowser();

  // Tell the test harness that creation is complete.
  base::StringValue command_value("onIncognitoBrowserCreatedForTest");
  web_ui()->CallJavascriptFunction("g_browser.receive", command_value);
}

void NetInternalsTest::MessageHandler::CloseIncognitoBrowser(
    const base::ListValue* list_value) {
  ASSERT_TRUE(incognito_browser_);
  incognito_browser_->tab_strip_model()->CloseAllTabs();
  // Closing all a Browser's tabs will ultimately result in its destruction,
  // thought it may not have been destroyed yet.
  incognito_browser_ = NULL;
}

void NetInternalsTest::MessageHandler::GetNetLogLoggerLog(
    const base::ListValue* list_value) {
  base::ScopedTempDir temp_directory;
  ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
  base::FilePath temp_file;
  ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_directory.path(),
                                             &temp_file));
  FILE* temp_file_handle = base::OpenFile(temp_file, "w");
  ASSERT_TRUE(temp_file_handle);

  scoped_ptr<base::Value> constants(NetInternalsUI::GetConstants());
  scoped_ptr<net::NetLogLogger> net_log_logger(new net::NetLogLogger(
      temp_file_handle, *constants));
  net_log_logger->StartObserving(g_browser_process->net_log());
  g_browser_process->net_log()->AddGlobalEntry(
      net::NetLog::TYPE_NETWORK_IP_ADDRESSES_CHANGED);
  net::BoundNetLog bound_net_log = net::BoundNetLog::Make(
      g_browser_process->net_log(),
      net::NetLog::SOURCE_URL_REQUEST);
  bound_net_log.BeginEvent(net::NetLog::TYPE_REQUEST_ALIVE);
  net_log_logger->StopObserving();
  net_log_logger.reset();

  std::string log_contents;
  ASSERT_TRUE(base::ReadFileToString(temp_file, &log_contents));
  ASSERT_GT(log_contents.length(), 0u);

  scoped_ptr<base::Value> log_contents_value(
      new base::StringValue(log_contents));
  RunJavascriptCallback(log_contents_value.get());
}

////////////////////////////////////////////////////////////////////////////////
// NetInternalsTest
////////////////////////////////////////////////////////////////////////////////

NetInternalsTest::NetInternalsTest()
    : test_server_started_(false) {
  message_handler_.reset(new MessageHandler(this));
}

NetInternalsTest::~NetInternalsTest() {
}

void NetInternalsTest::SetUpCommandLine(CommandLine* command_line) {
  WebUIBrowserTest::SetUpCommandLine(command_line);
  // Needed to test the prerender view.
  command_line->AppendSwitchASCII(switches::kPrerenderMode,
                                  switches::kPrerenderModeSwitchValueEnabled);
}

void NetInternalsTest::SetUpOnMainThread() {
  WebUIBrowserTest::SetUpOnMainThread();
  // Increase the memory allowed in a prerendered page above normal settings,
  // as debug builds use more memory and often go over the usual limit.
  Profile* profile = browser()->profile();
  prerender::PrerenderManager* prerender_manager =
      prerender::PrerenderManagerFactory::GetForProfile(profile);
  prerender_manager->mutable_config().max_bytes = 1000 * 1024 * 1024;
  if (!prerender_manager->cookie_store_loaded()) {
    base::RunLoop loop;
    prerender_manager->set_on_cookie_store_loaded_cb_for_testing(
        loop.QuitClosure());
    loop.Run();
  }
}

content::WebUIMessageHandler* NetInternalsTest::GetMockMessageHandler() {
  return message_handler_.get();
}

GURL NetInternalsTest::CreatePrerenderLoaderUrl(
    const GURL& prerender_url) {
  EXPECT_TRUE(StartTestServer());
  std::vector<net::SpawnedTestServer::StringPair> replacement_text;
  replacement_text.push_back(
      make_pair("REPLACE_WITH_PRERENDER_URL", prerender_url.spec()));
  std::string replacement_path;
  EXPECT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements(
      "files/prerender/prerender_loader.html",
      replacement_text,
      &replacement_path));
  GURL url_loader = test_server()->GetURL(replacement_path);
  return url_loader;
}

bool NetInternalsTest::StartTestServer() {
  if (test_server_started_)
    return true;
  test_server_started_ = test_server()->Start();
  return test_server_started_;
}
