// 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 "content/browser/renderer_interface_binders.h"

#include <memory>
#include <utility>

#include "base/bind.h"
#include "base/command_line.h"
#include "base/no_destructor.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/content_index/content_index_service_impl.h"
#include "content/browser/cookie_store/cookie_store_context.h"
#include "content/browser/locks/lock_manager.h"
#include "content/browser/native_file_system/native_file_system_manager_impl.h"
#include "content/browser/notifications/platform_notification_context_impl.h"
#include "content/browser/payments/payment_manager.h"
#include "content/browser/permissions/permission_service_context.h"
#include "content/browser/quota_dispatcher_host.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/storage_partition_impl.h"
#include "content/browser/websockets/websocket_connector_impl.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "media/mojo/mojom/video_decode_perf_history.mojom.h"
#include "media/mojo/services/video_decode_perf_history.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "services/device/public/mojom/constants.mojom.h"
#include "services/device/public/mojom/vibration_manager.mojom.h"
#include "services/service_manager/public/cpp/binder_registry.h"
#include "services/service_manager/public/cpp/connector.h"
#include "services/shape_detection/public/mojom/barcodedetection_provider.mojom.h"
#include "services/shape_detection/public/mojom/constants.mojom.h"
#include "services/shape_detection/public/mojom/facedetection_provider.mojom.h"
#include "services/shape_detection/public/mojom/textdetection.mojom.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/mojom/cache_storage/cache_storage.mojom.h"
#include "third_party/blink/public/mojom/cookie_store/cookie_store.mojom.h"
#include "third_party/blink/public/mojom/native_file_system/native_file_system_manager.mojom.h"
#include "third_party/blink/public/mojom/notifications/notification_service.mojom.h"
#include "url/origin.h"

namespace content {
namespace {

// A holder for a parameterized BinderRegistry for content-layer interfaces
// exposed to web workers.
class RendererInterfaceBinders {
 public:
  RendererInterfaceBinders() { InitializeParameterizedBinderRegistry(); }

  // Bind an interface request |interface_pipe| for |interface_name| received
  // from a web worker with origin |origin| hosted in the renderer |host|.
  void BindInterface(const std::string& interface_name,
                     mojo::ScopedMessagePipeHandle interface_pipe,
                     RenderProcessHost* host,
                     const url::Origin& origin) {
    if (parameterized_binder_registry_.TryBindInterface(
            interface_name, &interface_pipe, host, origin)) {
      return;
    }

    GetContentClient()->browser()->BindInterfaceRequestFromWorker(
        host, origin, interface_name, std::move(interface_pipe));
  }

  // Try binding an interface request |interface_pipe| for |interface_name|
  // received from |frame|.
  bool TryBindInterface(const std::string& interface_name,
                        mojo::ScopedMessagePipeHandle* interface_pipe,
                        RenderFrameHost* frame) {
    return parameterized_binder_registry_.TryBindInterface(
        interface_name, interface_pipe, frame->GetProcess(),
        frame->GetLastCommittedOrigin());
  }

 private:
  void InitializeParameterizedBinderRegistry();

  static void CreateWebSocketConnector(
      blink::mojom::WebSocketConnectorRequest request,
      RenderProcessHost* host,
      const url::Origin& origin);

  service_manager::BinderRegistryWithArgs<RenderProcessHost*,
                                          const url::Origin&>
      parameterized_binder_registry_;
};

// Forwards service requests to Service Manager since the renderer cannot launch
// out-of-process services on is own.
template <typename Interface>
void ForwardServiceRequest(const char* service_name,
                           mojo::InterfaceRequest<Interface> request,
                           RenderProcessHost* host,
                           const url::Origin& origin) {
  auto* connector = BrowserContext::GetConnectorFor(host->GetBrowserContext());
  connector->BindInterface(service_name, std::move(request));
}

// Register renderer-exposed interfaces. Each registered interface binder is
// exposed to all renderer-hosted execution context types (document/frame,
// dedicated worker, shared worker and service worker) where the appropriate
// capability spec in the content_browser manifest includes the interface. For
// interface requests from frames, binders registered on the frame itself
// override binders registered here.
void RendererInterfaceBinders::InitializeParameterizedBinderRegistry() {
  parameterized_binder_registry_.AddInterface(base::Bind(
      &ForwardServiceRequest<shape_detection::mojom::BarcodeDetectionProvider>,
      shape_detection::mojom::kServiceName));
  parameterized_binder_registry_.AddInterface(base::Bind(
      &ForwardServiceRequest<shape_detection::mojom::FaceDetectionProvider>,
      shape_detection::mojom::kServiceName));
  parameterized_binder_registry_.AddInterface(
      base::Bind(&ForwardServiceRequest<shape_detection::mojom::TextDetection>,
                 shape_detection::mojom::kServiceName));
  parameterized_binder_registry_.AddInterface(
      base::Bind(&ForwardServiceRequest<device::mojom::VibrationManager>,
                 device::mojom::kServiceName));

  // Used for shared workers and service workers to create a websocket.
  // In other cases, RenderFrameHostImpl for documents or DedicatedWorkerHost
  // for dedicated workers handles interface requests in order to associate
  // websockets with a frame. Shared workers and service workers don't have to
  // do it because they don't have a frame.
  // TODO(nhiroki): Consider moving this into SharedWorkerHost and
  // ServiceWorkerProviderHost.
  parameterized_binder_registry_.AddInterface(
      base::BindRepeating(CreateWebSocketConnector));

  parameterized_binder_registry_.AddInterface(
      base::Bind([](payments::mojom::PaymentManagerRequest request,
                    RenderProcessHost* host, const url::Origin& origin) {
        static_cast<StoragePartitionImpl*>(host->GetStoragePartition())
            ->GetPaymentAppContext()
            ->CreatePaymentManager(std::move(request));
      }));
  parameterized_binder_registry_.AddInterface(base::BindRepeating(
      [](blink::mojom::CacheStorageRequest request, RenderProcessHost* host,
         const url::Origin& origin) {
        static_cast<RenderProcessHostImpl*>(host)->BindCacheStorage(
            std::move(request), origin);
      }));
  parameterized_binder_registry_.AddInterface(base::BindRepeating(
      [](blink::mojom::IDBFactoryRequest request, RenderProcessHost* host,
         const url::Origin& origin) {
        static_cast<RenderProcessHostImpl*>(host)->BindIndexedDB(
            std::move(request), origin);
      }));
  // TODO(https://crbug.com/873661): Pass origin to FileSystemMananger.
  parameterized_binder_registry_.AddInterface(base::BindRepeating(
      [](blink::mojom::FileSystemManagerRequest request,
         RenderProcessHost* host, const url::Origin& origin) {
        static_cast<RenderProcessHostImpl*>(host)->BindFileSystemManager(
            origin, std::move(request));
      }));
  if (base::FeatureList::IsEnabled(blink::features::kNativeFileSystemAPI)) {
    parameterized_binder_registry_.AddInterface(base::BindRepeating(
        [](blink::mojom::NativeFileSystemManagerRequest request,
           RenderProcessHost* host, const url::Origin& origin) {
          // This code path is only for workers, hence always pass in
          // MSG_ROUTING_NONE as frame ID. Frames themselves go through
          // RenderFrameHostImpl instead.
          NativeFileSystemManagerImpl::BindRequestFromUIThread(
              static_cast<StoragePartitionImpl*>(host->GetStoragePartition()),
              NativeFileSystemManagerImpl::BindingContext(
                  origin,
                  // TODO(https://crbug.com/989323): Obtain and use a better URL
                  // for workers instead of the origin as source url. This URL
                  // will be used for SafeBrowsing checks and for the Quarantine
                  // Service.
                  origin.GetURL(), host->GetID(), MSG_ROUTING_NONE),
              std::move(request));
        }));
  }
  parameterized_binder_registry_.AddInterface(
      base::Bind([](blink::mojom::PermissionServiceRequest request,
                    RenderProcessHost* host, const url::Origin& origin) {
        static_cast<RenderProcessHostImpl*>(host)
            ->permission_service_context()
            .CreateServiceForWorker(std::move(request), origin);
      }));
  parameterized_binder_registry_.AddInterface(base::BindRepeating(
      [](blink::mojom::LockManagerRequest request, RenderProcessHost* host,
         const url::Origin& origin) {
        static_cast<StoragePartitionImpl*>(host->GetStoragePartition())
            ->GetLockManager()
            ->CreateService(std::move(request), origin);
      }));

  parameterized_binder_registry_.AddInterface(base::BindRepeating(
      [](blink::mojom::NotificationServiceRequest request,
         RenderProcessHost* host, const url::Origin& origin) {
        static_cast<StoragePartitionImpl*>(host->GetStoragePartition())
            ->GetPlatformNotificationContext()
            ->CreateService(origin, std::move(request));
      }));
  parameterized_binder_registry_.AddInterface(
      base::BindRepeating(&QuotaDispatcherHost::CreateForWorker));
  parameterized_binder_registry_.AddInterface(base::BindRepeating(
      [](blink::mojom::CookieStoreRequest request, RenderProcessHost* host,
         const url::Origin& origin) {
        static_cast<StoragePartitionImpl*>(host->GetStoragePartition())
            ->GetCookieStoreContext()
            ->CreateService(std::move(request), origin);
      }));
  parameterized_binder_registry_.AddInterface(base::BindRepeating(
      [](media::mojom::VideoDecodePerfHistoryRequest request,
         RenderProcessHost* host, const url::Origin& origin) {
        host->GetBrowserContext()->GetVideoDecodePerfHistory()->BindRequest(
            std::move(request));
      }));
  parameterized_binder_registry_.AddInterface(
      base::BindRepeating(&ContentIndexServiceImpl::Create));
}

RendererInterfaceBinders& GetRendererInterfaceBinders() {
  static base::NoDestructor<RendererInterfaceBinders> binders;
  return *binders;
}

void RendererInterfaceBinders::CreateWebSocketConnector(
    blink::mojom::WebSocketConnectorRequest request,
    RenderProcessHost* host,
    const url::Origin& origin) {
  // TODO(jam): is it ok to not send extraHeaders for sockets created from
  // shared and service workers?
  mojo::MakeStrongBinding(std::make_unique<WebSocketConnectorImpl>(
                              host->GetID(), MSG_ROUTING_NONE, origin),
                          std::move(request));
}

}  // namespace

void BindWorkerInterface(const std::string& interface_name,
                         mojo::ScopedMessagePipeHandle interface_pipe,
                         RenderProcessHost* host,
                         const url::Origin& origin) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  GetRendererInterfaceBinders().BindInterface(
      interface_name, std::move(interface_pipe), host, origin);
}

bool TryBindFrameInterface(const std::string& interface_name,
                           mojo::ScopedMessagePipeHandle* interface_pipe,
                           RenderFrameHost* frame) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  return GetRendererInterfaceBinders().TryBindInterface(interface_name,
                                                        interface_pipe, frame);
}

}  // namespace content
