// 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.

#ifndef ELECTRON_SHELL_BROWSER_EXTENSIONS_ELECTRON_EXTENSIONS_BROWSER_CLIENT_H_
#define ELECTRON_SHELL_BROWSER_EXTENSIONS_ELECTRON_EXTENSIONS_BROWSER_CLIENT_H_

#include <memory>
#include <string>
#include <vector>

#include "content/public/browser/frame_tree_node_id.h"
#include "extensions/browser/extensions_browser_client.h"
#include "extensions/browser/kiosk/kiosk_delegate.h"
#include "extensions/browser/safe_browsing_delegate.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/mojom/fetch_api.mojom.h"
#include "url/origin.h"

namespace extensions {
class ExtensionsAPIClient;
class KioskDelegate;
class ProcessManagerDelegate;
class ElectronProcessManagerDelegate;
class ProcessMap;
class SafeBrowsingDelegate;
class ElectronComponentExtensionResourceManager;
}  // namespace extensions

namespace mojo {
template <typename T>
class PendingReceiver;
template <typename T>
class PendingRemote;
}  // namespace mojo

namespace electron {

// An ExtensionsBrowserClient that supports a single content::BrowserContext
// with no related incognito context.
class ElectronExtensionsBrowserClient
    : public extensions::ExtensionsBrowserClient {
 public:
  ElectronExtensionsBrowserClient();
  ~ElectronExtensionsBrowserClient() override;

  // disable copy
  ElectronExtensionsBrowserClient(const ElectronExtensionsBrowserClient&) =
      delete;
  ElectronExtensionsBrowserClient& operator=(
      const ElectronExtensionsBrowserClient&) = delete;

  // ExtensionsBrowserClient overrides:
  void Init() override;
  bool IsShuttingDown() override;
  bool AreExtensionsDisabled(const base::CommandLine& command_line,
                             content::BrowserContext* context) override;
  bool IsValidContext(void* context) override;
  bool IsSameContext(content::BrowserContext* first,
                     content::BrowserContext* second) override;
  bool HasOffTheRecordContext(content::BrowserContext* context) override;
  content::BrowserContext* GetOffTheRecordContext(
      content::BrowserContext* context) override;
  content::BrowserContext* GetOriginalContext(
      content::BrowserContext* context) override;
  content::BrowserContext* GetContextRedirectedToOriginal(
      content::BrowserContext* context) override;
  content::BrowserContext* GetContextRedirectedToOriginalWithoutAshInternals(
      content::BrowserContext* context) override;
  content::BrowserContext* GetContextOwnInstance(
      content::BrowserContext* context) override;
  content::BrowserContext* GetContextForOriginalOnly(
      content::BrowserContext* context) override;
  bool AreExtensionsDisabledForContext(
      content::BrowserContext* context) override;
  bool IsGuestSession(content::BrowserContext* context) const override;
  bool IsExtensionIncognitoEnabled(
      const std::string& extension_id,
      content::BrowserContext* context) const override;
  bool IsExtensionIncognitoEnabled(
      const extensions::Extension* extension,
      content::BrowserContext* context) const override;
  bool CanExtensionCrossIncognito(
      const extensions::Extension* extension,
      content::BrowserContext* context) const override;
  base::FilePath GetBundleResourcePath(
      const network::ResourceRequest& request,
      const base::FilePath& extension_resources_path,
      int* resource_id) const override;
  void LoadResourceFromResourceBundle(
      const network::ResourceRequest& request,
      mojo::PendingReceiver<network::mojom::URLLoader> loader,
      const base::FilePath& resource_relative_path,
      int resource_id,
      scoped_refptr<net::HttpResponseHeaders> headers,
      mojo::PendingRemote<network::mojom::URLLoaderClient> client,
      content::BrowserContext* browser_context) override;
  bool AllowCrossRendererResourceLoad(
      const network::ResourceRequest& request,
      network::mojom::RequestDestination destination,
      ui::PageTransition page_transition,
      content::ChildProcessId child_id,
      bool is_incognito,
      const extensions::Extension* extension,
      const extensions::ExtensionSet& extensions,
      const extensions::ProcessMap& process_map,
      const GURL& upstream_url) override;
  void GetEarlyExtensionPrefsObservers(
      content::BrowserContext* context,
      std::vector<extensions::EarlyExtensionPrefsObserver*>* observers)
      const override;
  extensions::ProcessManagerDelegate* GetProcessManagerDelegate()
      const override;
  mojo::PendingRemote<network::mojom::URLLoaderFactory>
  GetControlledFrameEmbedderURLLoader(
      const url::Origin& app_origin,
      content::FrameTreeNodeId frame_tree_node_id,
      content::BrowserContext* browser_context) override;
  std::unique_ptr<extensions::ExtensionHostDelegate>
  CreateExtensionHostDelegate() override;
  bool DidVersionUpdate(content::BrowserContext* context) override;
  void PermitExternalProtocolHandler() override;
  bool IsInDemoMode() override;
  bool IsScreensaverInDemoMode(const std::string& app_id) override;
  bool IsRunningInForcedAppMode() override;
  bool IsAppModeForcedForApp(
      const extensions::ExtensionId& extension_id) override;
  bool IsLoggedInAsPublicAccount() override;
  extensions::ExtensionSystemProvider* GetExtensionSystemFactory() override;
  std::unique_ptr<extensions::RuntimeAPIDelegate> CreateRuntimeAPIDelegate(
      content::BrowserContext* context) const override;
  const extensions::ComponentExtensionResourceManager*
  GetComponentExtensionResourceManager() override;
  void BroadcastEventToRenderers(
      extensions::events::HistogramValue histogram_value,
      const std::string& event_name,
      base::ListValue args,
      bool dispatch_to_off_the_record_profiles) override;
  extensions::ExtensionCache* GetExtensionCache() override;
  bool IsBackgroundUpdateAllowed() override;
  bool IsMinBrowserVersionSupported(const std::string& min_version) override;
  void CreateExtensionWebContentsObserver(
      content::WebContents* web_contents) override;
  extensions::ExtensionWebContentsObserver* GetExtensionWebContentsObserver(
      content::WebContents* web_contents) override;
  bool IsValidTabId(content::BrowserContext* browser_context,
                    int tab_id,
                    bool include_incognito,
                    content::WebContents** web_contents) const override;
  extensions::ScriptExecutor* GetScriptExecutorForTab(
      content::WebContents& web_contents) override;
  extensions::KioskDelegate* GetKioskDelegate() override;
  std::string GetApplicationLocale() override;
  void RegisterBrowserInterfaceBindersForFrame(
      mojo::BinderMapWithContext<content::RenderFrameHost*>* map,
      content::RenderFrameHost* render_frame_host,
      const extensions::Extension* extension) const override;
  extensions::SafeBrowsingDelegate* GetSafeBrowsingDelegate() override;

  // Sets the API client.
  void SetAPIClientForTest(extensions::ExtensionsAPIClient* api_client);

 private:
  // Support for extension APIs.
  std::unique_ptr<extensions::ExtensionsAPIClient> api_client_;

  // Support for ProcessManager.
  std::unique_ptr<extensions::ElectronProcessManagerDelegate>
      process_manager_delegate_;

  // The extension cache used for download and installation.
  std::unique_ptr<extensions::ExtensionCache> extension_cache_;

  std::unique_ptr<extensions::KioskDelegate> kiosk_delegate_;

  std::unique_ptr<extensions::SafeBrowsingDelegate> safe_browsing_delegate_;

  std::unique_ptr<extensions::ElectronComponentExtensionResourceManager>
      resource_manager_;
};

}  // namespace electron

#endif  // ELECTRON_SHELL_BROWSER_EXTENSIONS_ELECTRON_EXTENSIONS_BROWSER_CLIENT_H_
