// Copyright (c) 2015 The Chromium Embedded Framework 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 "include/base/cef_bind.h"
#include "include/cef_pack_resources.h"
#include "include/cef_request_context_handler.h"
#include "include/wrapper/cef_closure_task.h"
#include "include/wrapper/cef_stream_resource_handler.h"
#include "tests/ceftests/routing_test_handler.h"
#include "tests/gtest/include/gtest/gtest.h"
#include "tests/shared/browser/client_app_browser.h"
#include "tests/shared/browser/resource_util.h"

namespace {

// Browser-side app delegate.
class PluginBrowserTest : public client::ClientAppBrowser::Delegate {
 public:
  PluginBrowserTest() {}

  void OnBeforeCommandLineProcessing(
      CefRefPtr<client::ClientAppBrowser> app,
      CefRefPtr<CefCommandLine> command_line) override {
    // Allow all plugin loading by default.
    command_line->AppendSwitchWithValue("plugin-policy", "allow");
  }

 private:
  IMPLEMENT_REFCOUNTING(PluginBrowserTest);
};

const char kPdfTestOrigin[] = "http://tests/";
const char kPdfHtmlUrl[] = "http://tests/pdf.html";
const char kPdfDirectUrl[] = "http://tests/pdf.pdf";

// Delay waiting for iframe tests to load the PDF file.
#if defined(OS_LINUX)
const int64 kPdfLoadDelayMs = 7000;
#else
const int64 kPdfLoadDelayMs = 5000;
#endif

// Browser-side test handler.
class PluginTestHandler : public RoutingTestHandler,
                          public CefContextMenuHandler {
 public:
  enum Mode {
    // No specified context or handler (implicitly uses the global context).
    GLOBAL_DEFAULT,

    // Global context with no handler.
    GLOBAL_NO_HANDLER,

    // Global context with handler that allows plugin load.
    GLOBAL_ALLOW,

    // Global context with handler that blocks plugin load. Then, load the
    // plugin via the context menu.
    GLOBAL_BLOCK_LOAD,

    // Global context with handler that blocks plugin load. Then, hide the
    // plugin via the context menu.
    GLOBAL_BLOCK_HIDE,

    // Global context with handler that disables plugin load. Then, hide the
    // plugin via the context menu.
    GLOBAL_DISABLE_HIDE,

    // Global context with handler that removes the plugin from the
    // `navigator.plugins` list and consequently disables plugin load.
    GLOBAL_NO_LIST,

    // Custom context with no handler.
    CUSTOM_NO_HANDLER,

    // Custom context with handler that allows plugin load.
    CUSTOM_ALLOW,

    // Custom context with handler that blocks plugin load. Then, load the
    // plugin via the context menu.
    CUSTOM_BLOCK_LOAD,

    // Custom context with handler that blocks plugin load. Then, hide the
    // plugin via the context menu.
    CUSTOM_BLOCK_HIDE,

    // Custom context with handler that disables plugin load. Then, hide the
    // plugin via the context menu.
    CUSTOM_DISABLE_HIDE,

    // Custom context with handler that removes the plugin from the
    // `navigator.plugins` list and consequently disables plugin load.
    CUSTOM_NO_LIST,
  };

  class RequestContextHandler : public CefRequestContextHandler {
   public:
    explicit RequestContextHandler(PluginTestHandler* handler)
        : handler_(handler) {}

    bool OnBeforePluginLoad(const CefString& mime_type,
                            const CefString& plugin_url,
                            bool is_main_frame,
                            const CefString& top_origin_url,
                            CefRefPtr<CefWebPluginInfo> plugin_info,
                            PluginPolicy* plugin_policy) override {
      const std::string& mime_type_str = mime_type;
      EXPECT_STREQ("application/pdf", mime_type_str.c_str());
      EXPECT_STREQ("chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/",
                   plugin_info->GetPath().ToString().c_str());

      if (top_origin_url.empty()) {
        if (!handler_->got_on_before_plugin_empty_origin_) {
          // Checking for PDF support in the plugin frame (navigator.plugins
          // listing, pdf load, etc).
          handler_->got_on_before_plugin_empty_origin_.yes();
        } else if (handler_->HasNoList()) {
          // When listing is disabled there should be an additional check in the
          // main frame for the navigator.plugins listing.
          if (!handler_->got_on_before_plugin_empty_origin2_) {
            EXPECT_TRUE(is_main_frame);
            handler_->got_on_before_plugin_empty_origin2_.yes();
          }
        }

        if (handler_->HasNoList()) {
          // Remove the PDF plugin from the `navigator.plugins` list.
          *plugin_policy = PLUGIN_POLICY_DISABLE;
          return true;
        }

        // Ignore requests for building the plugin list.
        return false;
      }

      // Should only get requests for the test origin.
      EXPECT_STREQ(kPdfTestOrigin, top_origin_url.ToString().c_str());

      if (!handler_->got_on_before_plugin_load_pdf_)
        handler_->got_on_before_plugin_load_pdf_.yes();
      else
        NOTREACHED();

      if (handler_->HasAllow()) {
        *plugin_policy = PLUGIN_POLICY_ALLOW;
        return true;
      } else if (handler_->HasBlock()) {
        *plugin_policy = PLUGIN_POLICY_BLOCK;
        return true;
      } else if (handler_->HasDisable()) {
        *plugin_policy = PLUGIN_POLICY_DISABLE;
        return true;
      }

      return false;
    }

    void Detach() { handler_ = nullptr; }

   private:
    PluginTestHandler* handler_;

    IMPLEMENT_REFCOUNTING(RequestContextHandler);
  };

  PluginTestHandler(Mode mode, const std::string& url)
      : mode_(mode), url_(url) {}

  // Loading the PDF directly in the main frame instead of a sub-frame.
  bool HasDirectPluginLoad() const { return url_ == kPdfDirectUrl; }

  // Has a specified RequestContext but not necessarily a custom handler.
  bool HasRequestContext() const { return mode_ != GLOBAL_DEFAULT; }

  // Has a specified RequestContext and custom handler.
  bool HasRequestContextHandler() const {
    return mode_ != GLOBAL_DEFAULT && mode_ != GLOBAL_NO_HANDLER &&
           mode_ != CUSTOM_NO_HANDLER;
  }

  // Using the global request context, either directly or with a custom handler.
  bool HasGlobalRequestContext() const {
    return mode_ >= GLOBAL_DEFAULT && mode_ <= GLOBAL_NO_LIST;
  }

  // Should allow the plugin load via the custom handler.
  bool HasAllow() const {
    return mode_ == GLOBAL_ALLOW || mode_ == CUSTOM_ALLOW;
  }

  // Should block the plugin load via the custom handler.
  bool HasBlock() const {
    return mode_ == GLOBAL_BLOCK_LOAD || mode_ == GLOBAL_BLOCK_HIDE ||
           mode_ == CUSTOM_BLOCK_LOAD || mode_ == CUSTOM_BLOCK_HIDE;
  }

  // Should disable the plugin load via the custom handler.
  bool HasDisable() const {
    return mode_ == GLOBAL_DISABLE_HIDE || mode_ == CUSTOM_DISABLE_HIDE;
  }

  // Should exclude the plugin from the `navigator.plugins` list.
  bool HasNoList() const {
    return mode_ == GLOBAL_NO_LIST || mode_ == CUSTOM_NO_LIST;
  }

  // Should load the plugin via the context menu.
  bool HasContextLoad() const {
    return mode_ == GLOBAL_BLOCK_LOAD || mode_ == CUSTOM_BLOCK_LOAD;
  }

  // Should hide the plugin via the context menu.
  bool HasContextHide() const {
    return mode_ == GLOBAL_BLOCK_HIDE || mode_ == GLOBAL_DISABLE_HIDE ||
           mode_ == CUSTOM_BLOCK_HIDE || mode_ == CUSTOM_DISABLE_HIDE;
  }

  std::string GetPluginNode() const {
    return "document.getElementsByTagName('embed')[0]";
  }

  void WaitForNavigatorPlugins(CefRefPtr<CefFrame> frame) const {
    // Test if the `navigator.plugins` list includes the PDF extension.
    const std::string& code =
        " if (navigator.plugins['Chrome PDF Viewer'].filename == "
        "       'mhjfbmdgcfjbbpaeojofohoefgiehjai') {"
        "  window.testQuery({request:'pdf_plugin_found'});"
        "} else {"
        "  window.testQuery({request:'pdf_plugin_missing'});"
        "}";
    frame->ExecuteJavaScript(code, frame->GetURL(), 0);
  }

  void WaitForPlaceholderLoad(CefRefPtr<CefFrame> frame) {
    // Keep track of the frame that contains the placeholder.
    placeholder_frame_ = frame;

    // Waits for the placeholder to load. This is indicated by the presence
    // of the plugin node.
    const std::string& code =
        "(function waitForNode(i) {"
        "   setTimeout(function() {"
        "     var plugin = " +
        GetPluginNode() +
        ";"
        "     if (plugin) {"
        "        window.testQuery({request:'placeholder_loaded'});"
        "        return;"
        "     }"
        "     if (--i) {"
        "       waitForNode(i);"
        "     } else {"
        "       console.log('Timeout waiting for plugin load');"
        "     }"
        "   }, 250)"
        "})(4);";
    frame->ExecuteJavaScript(code, frame->GetURL(), 0);
  }

  void WaitForPlaceholderHide() {
    // Waits for the placeholder to be hidden (style set to display:none).
    // See PluginPlaceholderBase::HidePlugin.
    const std::string& code =
        "var plugin = " + GetPluginNode() +
        ";"
        "var observer = new MutationObserver(function(mutations) {"
        "  mutations.forEach(function(mutationRecord) {"
        "    window.testQuery({request:'placeholder_hidden'});"
        "    observer.disconnect();"
        "  });"
        "});"
        "observer.observe(plugin, "
        "  { attributes : true, attributeFilter : ['style'] });";
    placeholder_frame_->ExecuteJavaScript(code, placeholder_frame_->GetURL(),
                                          0);
    placeholder_frame_ = nullptr;
  }

  void WaitForPluginLoad(CefRefPtr<CefFrame> frame) {
    if (got_context_menu_dismissed_) {
      // After context menu display. Destroy the test.
      CefPostDelayedTask(TID_UI,
                         base::Bind(&PluginTestHandler::DestroyTest, this),
                         kPdfLoadDelayMs);
    } else {
      // Trigger the context menu.
      CefPostDelayedTask(TID_UI,
                         base::Bind(&PluginTestHandler::TriggerContextMenu,
                                    this, frame->GetBrowser()),
                         kPdfLoadDelayMs);
    }
  }

  void EndTest() {
    CefPostTask(TID_UI, base::Bind(&PluginTestHandler::DestroyTest, this));
  }

  CefRefPtr<CefContextMenuHandler> GetContextMenuHandler() override {
    return this;
  }

  void RunTest() override {
    CefRefPtr<CefRequestContext> request_context;

    if (HasRequestContext()) {
      if (HasRequestContextHandler())
        context_handler_ = new RequestContextHandler(this);

      if (HasGlobalRequestContext()) {
        // Use the global request context.
        request_context = CefRequestContext::CreateContext(
            CefRequestContext::GetGlobalContext(), context_handler_.get());
      } else {
        // Create the request context that will use an in-memory cache.
        CefRequestContextSettings settings;
        request_context =
            CefRequestContext::CreateContext(settings, context_handler_.get());
      }
    }

    // Create the browser.
    CreateBrowser(url_, request_context);

    // Time out the test after a reasonable period of time.
    SetTestTimeout(5000 + kPdfLoadDelayMs);
  }

  CefRefPtr<CefResourceHandler> GetResourceHandler(
      CefRefPtr<CefBrowser> browser,
      CefRefPtr<CefFrame> frame,
      CefRefPtr<CefRequest> request) override {
    const std::string& url = request->GetURL();
    if (url == kPdfHtmlUrl) {
      CefRefPtr<CefStreamReader> stream =
          client::GetBinaryResourceReader("pdf.html");
      return new CefStreamResourceHandler("text/html", stream);
    } else if (url == kPdfDirectUrl) {
      CefRefPtr<CefStreamReader> stream =
          client::GetBinaryResourceReader("pdf.pdf");
      return new CefStreamResourceHandler("application/pdf", stream);
    }

    return nullptr;
  }

  void OnLoadEnd(CefRefPtr<CefBrowser> browser,
                 CefRefPtr<CefFrame> frame,
                 int httpStatusCode) override {
    bool is_pdf1 = false;
    const std::string& url = frame->GetURL();
    if (url == kPdfHtmlUrl) {
      if (!got_on_load_end_html_)
        got_on_load_end_html_.yes();
      else
        NOTREACHED();
    } else if (url == kPdfDirectUrl) {
      if (!got_on_load_end_pdf1_) {
        got_on_load_end_pdf1_.yes();
        is_pdf1 = true;
      } else if (!got_on_load_end_pdf2_) {
        got_on_load_end_pdf2_.yes();
      } else {
        NOTREACHED();
      }
    } else {
      NOTREACHED();
    }

    if (HasNoList()) {
      // If the plugin is not listed then the PDF documents will never load.
      EXPECT_STREQ(kPdfHtmlUrl, url.c_str());
      WaitForNavigatorPlugins(frame);
    } else if (is_pdf1) {
      // The first PDF document has loaded.
      WaitForNavigatorPlugins(frame);
    }
  }

  bool OnQuery(CefRefPtr<CefBrowser> browser,
               CefRefPtr<CefFrame> frame,
               int64 query_id,
               const CefString& request,
               bool persistent,
               CefRefPtr<Callback> callback) override {
    if (request == "pdf_plugin_found" || request == "pdf_plugin_missing") {
      if (request == "pdf_plugin_found")
        got_pdf_plugin_found_.yes();
      else
        got_pdf_plugin_missing_.yes();

      if (HasNoList()) {
        // The plugin will not load. End the test.
        EndTest();
      } else if (HasBlock() || HasDisable()) {
        // Wait for the plugin placeholder for the first PDF file to load. The
        // test will continue from OnQuery.
        WaitForPlaceholderLoad(frame);
      } else {
        // Wait for the first PDF file to load.
        WaitForPluginLoad(frame);
      }
    } else if (request == "placeholder_loaded") {
      EXPECT_FALSE(got_placeholder_loaded_);
      EXPECT_FALSE(got_placeholder_hidden_);
      got_placeholder_loaded_.yes();

      // The plugin placeholder has loaded. Trigger the context menu.
      TriggerContextMenu(frame->GetBrowser());
    } else if (request == "placeholder_hidden") {
      EXPECT_TRUE(got_placeholder_loaded_);
      EXPECT_FALSE(got_placeholder_hidden_);
      got_placeholder_hidden_.yes();

      if (HasContextLoad()) {
        // Wait for the PDF plugin to load.
        WaitForPluginLoad(frame);
      } else {
        // The plugin placeholder has been hidden. End the test.
        EndTest();
      }
    } else {
      NOTREACHED();
    }

    return true;
  }

  void TriggerContextMenu(CefRefPtr<CefBrowser> browser) {
    CefMouseEvent mouse_event;

    // Somewhere in the first plugin.
    mouse_event.x = 100;
    mouse_event.y = 100;

    // Send right-click mouse down and mouse up to tigger context menu.
    browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_RIGHT, false, 1);
    browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_RIGHT, true, 1);
  }

  bool RunContextMenu(CefRefPtr<CefBrowser> browser,
                      CefRefPtr<CefFrame> frame,
                      CefRefPtr<CefContextMenuParams> params,
                      CefRefPtr<CefMenuModel> model,
                      CefRefPtr<CefRunContextMenuCallback> callback) override {
    EXPECT_FALSE(got_run_context_menu_);
    got_run_context_menu_.yes();

    if (HasContextLoad() || HasContextHide()) {
      // Should have 4 elements -- plugin name, separator, run, hide.
      EXPECT_EQ(4, model->GetCount());

      // Wait for the placeholder to be hidden.
      WaitForPlaceholderHide();

      int command_id;
      if (HasContextLoad()) {
        // Execute the run command.
        command_id = model->GetCommandIdAt(2);
      } else {
        // Execute the hide command.
        command_id = model->GetCommandIdAt(3);
      }

      EXPECT_GE(command_id, MENU_ID_CUSTOM_FIRST);
      EXPECT_LE(command_id, MENU_ID_CUSTOM_LAST);

      callback->Continue(command_id, static_cast<EventFlags>(0));
    } else {
      // Do nothing with the context menu.
      callback->Cancel();
    }
    return true;
  }

  void OnContextMenuDismissed(CefRefPtr<CefBrowser> browser,
                              CefRefPtr<CefFrame> frame) override {
    EXPECT_FALSE(got_context_menu_dismissed_);
    got_context_menu_dismissed_.yes();

    if (HasContextHide()) {
      // Nothing to do here. The test will continue from OnQuery.
      // TODO: Once block-then-load is working this should also be the case for
      // HasContextLoad().
      return;
    }

    EndTest();
  }

  void DestroyTest() override {
    if (context_handler_.get()) {
      context_handler_->Detach();
      context_handler_ = nullptr;
    }

    if (HasContextLoad()) {
      EXPECT_TRUE(got_placeholder_loaded_);
      // TODO: Once block-then-load is working this value should be true.
      EXPECT_FALSE(got_placeholder_hidden_);
    } else if (HasContextHide()) {
      EXPECT_TRUE(got_placeholder_loaded_);
      EXPECT_TRUE(got_placeholder_hidden_);
    } else {
      EXPECT_FALSE(got_placeholder_loaded_);
      EXPECT_FALSE(got_placeholder_hidden_);
    }
    EXPECT_FALSE(placeholder_frame_);

    if (HasRequestContextHandler())
      EXPECT_TRUE(got_on_before_plugin_empty_origin_);
    else
      EXPECT_FALSE(got_on_before_plugin_empty_origin_);

    if (HasNoList()) {
      EXPECT_TRUE(got_on_before_plugin_empty_origin2_);
      EXPECT_FALSE(got_pdf_plugin_found_);
      EXPECT_TRUE(got_pdf_plugin_missing_);
      EXPECT_FALSE(got_run_context_menu_);
      EXPECT_FALSE(got_context_menu_dismissed_);
    } else {
      EXPECT_FALSE(got_on_before_plugin_empty_origin2_);
      EXPECT_TRUE(got_pdf_plugin_found_);
      EXPECT_FALSE(got_pdf_plugin_missing_);
      EXPECT_TRUE(got_run_context_menu_);
      EXPECT_TRUE(got_context_menu_dismissed_);
    }

    if (url_ == kPdfHtmlUrl) {
      // The HTML file will load the PDF twice in iframes.
      EXPECT_TRUE(got_on_load_end_html_);

      if (!HasNoList()) {
        EXPECT_TRUE(got_on_load_end_pdf1_);
        EXPECT_TRUE(got_on_load_end_pdf2_);

        if (HasRequestContextHandler()) {
          EXPECT_TRUE(got_on_before_plugin_load_pdf_);
        }
      }
    } else if (url_ == kPdfDirectUrl) {
      // Load the PDF file directly.
      EXPECT_FALSE(got_on_load_end_html_);
      EXPECT_TRUE(got_on_load_end_pdf1_);
      EXPECT_FALSE(got_on_load_end_pdf2_);

      if (HasRequestContextHandler()) {
        EXPECT_TRUE(got_on_before_plugin_load_pdf_);
      }
    } else {
      NOTREACHED();
    }

    if (!HasRequestContextHandler() || HasNoList()) {
      EXPECT_FALSE(got_on_before_plugin_load_pdf_);
    }

    TestHandler::DestroyTest();
  }

  const Mode mode_;
  const std::string url_;

  CefRefPtr<CefFrame> placeholder_frame_;

  TrackCallback got_on_before_plugin_empty_origin_;
  TrackCallback got_on_before_plugin_empty_origin2_;
  TrackCallback got_on_before_plugin_load_pdf_;
  TrackCallback got_on_load_end_html_;
  TrackCallback got_on_load_end_pdf1_;
  TrackCallback got_on_load_end_pdf2_;
  TrackCallback got_pdf_plugin_found_;
  TrackCallback got_pdf_plugin_missing_;
  TrackCallback got_placeholder_loaded_;
  TrackCallback got_placeholder_hidden_;
  TrackCallback got_run_context_menu_;
  TrackCallback got_context_menu_dismissed_;

  CefRefPtr<RequestContextHandler> context_handler_;

  IMPLEMENT_REFCOUNTING(PluginTestHandler);
};

}  // namespace

#define RUN_TEST(name, type, url)                            \
  TEST(PluginTest, name) {                                   \
    CefRefPtr<PluginTestHandler> handler =                   \
        new PluginTestHandler(PluginTestHandler::type, url); \
    handler->ExecuteTest();                                  \
    ReleaseAndWaitForDestructor(handler);                    \
  }

RUN_TEST(GlobalDefaultPdfDirect, GLOBAL_DEFAULT, kPdfDirectUrl)
RUN_TEST(GlobalDefaultPdfHtml, GLOBAL_DEFAULT, kPdfHtmlUrl)

RUN_TEST(GlobalNoHandlerPdfDirect, GLOBAL_NO_HANDLER, kPdfDirectUrl)
RUN_TEST(GlobalNoHandlerPdfHtml, GLOBAL_NO_HANDLER, kPdfHtmlUrl)
RUN_TEST(GlobalAllowPdfDirect, GLOBAL_ALLOW, kPdfDirectUrl)
RUN_TEST(GlobalAllowPdfHtml, GLOBAL_ALLOW, kPdfHtmlUrl)
RUN_TEST(GlobalBlockThenLoadPdfDirect, GLOBAL_BLOCK_LOAD, kPdfDirectUrl)
RUN_TEST(GlobalBlockThenLoadPdfHtml, GLOBAL_BLOCK_LOAD, kPdfHtmlUrl)
RUN_TEST(GlobalBlockThenHidePdfDirect, GLOBAL_BLOCK_HIDE, kPdfDirectUrl)
RUN_TEST(GlobalBlockThenHidePdfHtml, GLOBAL_BLOCK_HIDE, kPdfHtmlUrl)
RUN_TEST(GlobalDisableThenHidePdfDirect, GLOBAL_DISABLE_HIDE, kPdfDirectUrl)
RUN_TEST(GlobalDisableThenHidePdfHtml, GLOBAL_DISABLE_HIDE, kPdfHtmlUrl)
RUN_TEST(GlobalNoListHtml, GLOBAL_NO_LIST, kPdfHtmlUrl)

RUN_TEST(CustomNoHandlerPdfDirect, CUSTOM_NO_HANDLER, kPdfDirectUrl)
RUN_TEST(CustomNoHandlerPdfHtml, CUSTOM_NO_HANDLER, kPdfHtmlUrl)
RUN_TEST(CustomAllowPdfDirect, CUSTOM_ALLOW, kPdfDirectUrl)
RUN_TEST(CustomAllowPdfHtml, CUSTOM_ALLOW, kPdfHtmlUrl)
RUN_TEST(CustomBlockThenLoadPdfDirect, CUSTOM_BLOCK_LOAD, kPdfDirectUrl)
RUN_TEST(CustomBlockThenLoadPdfHtml, CUSTOM_BLOCK_LOAD, kPdfHtmlUrl)
RUN_TEST(CustomBlockThenHidePdfDirect, CUSTOM_BLOCK_HIDE, kPdfDirectUrl)
RUN_TEST(CustomBlockThenHidePdfHtml, CUSTOM_BLOCK_HIDE, kPdfHtmlUrl)
RUN_TEST(CustomDisableThenHidePdfDirect, CUSTOM_DISABLE_HIDE, kPdfDirectUrl)
RUN_TEST(CustomDisableThenHidePdfHtml, CUSTOM_DISABLE_HIDE, kPdfHtmlUrl)
RUN_TEST(CustomNoListHtml, CUSTOM_NO_LIST, kPdfHtmlUrl)

// Entry point for creating plugin browser test objects.
// Called from client_app_delegates.cc.
void CreatePluginBrowserTests(
    client::ClientAppBrowser::DelegateSet& delegates) {
  delegates.insert(new PluginBrowserTest);
}
