// 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 "libcef/browser/plugins/plugin_service_filter.h"

#include "include/cef_request_context_handler.h"
#include "libcef/browser/browser_context.h"
#include "libcef/browser/thread_util.h"
#include "libcef/browser/web_plugin_impl.h"
#include "libcef/common/content_client.h"

#include "extensions/common/constants.h"

CefPluginServiceFilter::CefPluginServiceFilter() {}

bool CefPluginServiceFilter::IsPluginAvailable(
    int render_process_id,
    int render_frame_id,
    const GURL& url,
    bool is_main_frame,
    const url::Origin& main_frame_origin,
    content::WebPluginInfo* plugin) {
  CEF_REQUIRE_UIT();
  DCHECK_GT(render_process_id, 0);

  chrome::mojom::PluginStatus status = chrome::mojom::PluginStatus::kAllowed;

  // Perform origin check here because we're passing an empty origin value to
  // IsPluginAvailable() below.
  const GURL& policy_url = main_frame_origin.GetURL();
  if (!policy_url.is_empty() &&
      policy_url.scheme() == extensions::kExtensionScheme) {
    // Always allow extension origins to load plugins.
    // TODO(extensions): Revisit this decision once CEF supports more than just
    // the PDF extension.
    return true;
  }

  // Blink requires this method to return a consistent value during renderer
  // process initialization and page load, so we always call IsPluginAvailable()
  // with an empty origin. If we return false then the plugin will not be listed
  // in navigator.plugins and navigating to the plugin mime type will trigger
  // the download code path. If we return true then individual plugin instance
  // loads will be evaluated in CefContentRendererClient::OverrideCreatePlugin,
  // which will result in a call to CefPluginInfoMessageFilter::PluginsLoaded to
  // retrieve the actual load decision with a non-empty origin. That will
  // determine whether the plugin load is allowed or the plugin placeholder is
  // displayed.
  return IsPluginAvailable(render_process_id, render_frame_id, url,
                           is_main_frame, url::Origin(), plugin, &status);
}

bool CefPluginServiceFilter::CanLoadPlugin(int render_process_id,
                                           const base::FilePath& path) {
  return true;
}

bool CefPluginServiceFilter::IsPluginAvailable(
    int render_process_id,
    int render_frame_id,
    const GURL& url,
    bool is_main_frame,
    const url::Origin& main_frame_origin,
    content::WebPluginInfo* plugin,
    chrome::mojom::PluginStatus* status) {
  CEF_REQUIRE_UIT();
  DCHECK_GT(render_process_id, 0);

  if (*status == chrome::mojom::PluginStatus::kNotFound) {
    // The plugin does not exist so no need to query the handler.
    return false;
  }

  if (plugin->path == CefString(CefContentClient::kPDFPluginPath)) {
    // Always allow the internal PDF plugin to load.
    *status = chrome::mojom::PluginStatus::kAllowed;
    return true;
  }

  const GURL& policy_url = main_frame_origin.GetURL();
  if (!policy_url.is_empty() &&
      policy_url.scheme() == extensions::kExtensionScheme) {
    // Always allow extension origins to load plugins.
    // TODO(extensions): Revisit this decision once CEF supports more than just
    // the PDF extension.
    *status = chrome::mojom::PluginStatus::kAllowed;
    return true;
  }

  auto browser_context = CefBrowserContext::GetForIDs(
      render_process_id, render_frame_id, -1, false);
  CefRefPtr<CefRequestContextHandler> handler;
  if (browser_context) {
    handler = browser_context->GetHandler(render_process_id, render_frame_id,
                                          -1, false);
  }

  if (!handler) {
    // No handler so go with the default plugin load decision.
    return *status != chrome::mojom::PluginStatus::kDisabled;
  }

  // Check for a cached plugin load decision.
  if (browser_context->HasPluginLoadDecision(render_process_id, plugin->path,
                                             is_main_frame, main_frame_origin,
                                             status)) {
    return *status != chrome::mojom::PluginStatus::kDisabled;
  }

  CefRefPtr<CefWebPluginInfoImpl> pluginInfo(new CefWebPluginInfoImpl(*plugin));

  cef_plugin_policy_t plugin_policy = PLUGIN_POLICY_ALLOW;
  switch (*status) {
    case chrome::mojom::PluginStatus::kAllowed:
      plugin_policy = PLUGIN_POLICY_ALLOW;
      break;
    case chrome::mojom::PluginStatus::kBlocked:
    case chrome::mojom::PluginStatus::kBlockedByPolicy:
    case chrome::mojom::PluginStatus::kOutdatedBlocked:
    case chrome::mojom::PluginStatus::kOutdatedDisallowed:
    case chrome::mojom::PluginStatus::kUnauthorized:
      plugin_policy = PLUGIN_POLICY_BLOCK;
      break;
    case chrome::mojom::PluginStatus::kDisabled:
      plugin_policy = PLUGIN_POLICY_DISABLE;
      break;
    case chrome::mojom::PluginStatus::kPlayImportantContent:
      plugin_policy = PLUGIN_POLICY_DETECT_IMPORTANT;
      break;
    default:
      NOTREACHED();
      break;
  }

  if (handler->OnBeforePluginLoad(plugin->mime_types[0].mime_type,
                                  url.possibly_invalid_spec(), is_main_frame,
                                  policy_url.possibly_invalid_spec(),
                                  pluginInfo.get(), &plugin_policy)) {
    switch (plugin_policy) {
      case PLUGIN_POLICY_ALLOW:
        *status = chrome::mojom::PluginStatus::kAllowed;
        break;
      case PLUGIN_POLICY_DETECT_IMPORTANT:
        *status = chrome::mojom::PluginStatus::kPlayImportantContent;
        break;
      case PLUGIN_POLICY_BLOCK:
        *status = chrome::mojom::PluginStatus::kBlocked;
        break;
      case PLUGIN_POLICY_DISABLE:
        *status = chrome::mojom::PluginStatus::kDisabled;
        break;
    }
  }

  // Cache the plugin load decision.
  browser_context->AddPluginLoadDecision(render_process_id, plugin->path,
                                         is_main_frame, main_frame_origin,
                                         *status);

  return *status != chrome::mojom::PluginStatus::kDisabled;
}
