chromium/chromecast/browser/cast_web_service.h

// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROMECAST_BROWSER_CAST_WEB_SERVICE_H_
#define CHROMECAST_BROWSER_CAST_WEB_SERVICE_H_

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

#include "base/containers/flat_map.h"
#include "base/containers/flat_set.h"
#include "base/functional/callback.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "chromecast/browser/cast_web_view.h"
#include "chromecast/browser/cast_web_view_factory.h"
#include "chromecast/browser/mojom/cast_web_service.mojom.h"
#include "chromecast/external_mojo/external_service_support/reconnecting_remote.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "url/origin.h"

namespace base {
class SequencedTaskRunner;
}  // namespace base

namespace content {
class BrowserContext;
class StoragePartition;
}  // namespace content

namespace chromecast {

class CastWindowManager;
class LRURendererCache;

// This class dispenses CastWebView objects which are used to wrap WebContents
// in cast_shell. This class temporarily takes ownership of CastWebViews when
// they go out of scope, allowing us to keep the pages alive for extra time if
// needed. CastWebService allows us to synchronously destroy all pages when the
// system is shutting down, preventing use of freed browser resources.
class CastWebService : public mojom::CastWebService {
 public:
  CastWebService(content::BrowserContext* browser_context,
                 CastWindowManager* window_manager);
  CastWebService(const CastWebService&) = delete;
  CastWebService& operator=(const CastWebService&) = delete;
  ~CastWebService() override;

  // Allow a client to use its own CastWebViewFactory implementation instead of
  // |default_web_view_factory_| below.
  void OverrideWebViewFactory(CastWebViewFactory* web_view_factory);

  // These are temporary methods to allow in-process embedders to directly own
  // the CastWebView. This will be removed once the lifetime of CastWebview is
  // scoped by the CastWebContents mojo::Remote.
  CastWebView::Scoped CreateWebViewInternal(
      mojom::CastWebViewParamsPtr params);

  // This implementation varies by platform (Aura vs Android).
  std::unique_ptr<CastContentWindow> CreateWindow(
      mojom::CastWebViewParamsPtr params);

  content::BrowserContext* browser_context() { return browser_context_; }
  LRURendererCache* overlay_renderer_cache() {
    return overlay_renderer_cache_.get();
  }
  ReconnectingRemote<mojom::CastWebService>* proxy() { return &proxy_; }

  bool IsCastWebUIOrigin(const url::Origin& origin);

  // mojom::CastWebService implementation:
  void CreateWebView(
      mojom::CastWebViewParamsPtr params,
      mojo::PendingReceiver<mojom::CastWebContents> web_contents,
      mojo::PendingReceiver<mojom::CastContentWindow> window) override;
  void RegisterWebUiClient(mojo::PendingRemote<mojom::WebUiClient> client,
                           const std::vector<std::string>& hosts) override;
  void FlushDomLocalStorage() override;
  void ClearLocalStorage(ClearLocalStorageCallback callback) override;

  // Immediately deletes all owned CastWebViews. This should happen before
  // CastWebService is deleted, to prevent UAF of shared browser objects.
  void DeleteOwnedWebViews();

 private:
  void OwnerDestroyed(CastWebView* web_view);
  void DeleteWebView(CastWebView* web_view);

  content::BrowserContext* const browser_context_;
  // This is used on Aura platforms.
  CastWindowManager* const window_manager_;

  // This is injected into clients which live in the browser or in a remote
  // process. This is temporary until the clients exclusively live in an
  // external process.
  ReconnectingRemote<mojom::CastWebService> proxy_{this};

  CastWebViewFactory default_web_view_factory_;

  CastWebViewFactory* override_web_view_factory_ = nullptr;

  // These CastWebViews are owned by CastWebService. This happens in two
  // scenarios:
  //
  // 1. The CastWebView was created via the Mojo service. This CastWebView will
  // be deleted when the mojo::Remote disconnects.
  //
  // 2. The CastWebView is in the process of extended shutdown. It is
  // temporarily held here for a short time after the original owner releases
  // the CastWebView. After the desired shutdown time elapses, the CastWebView
  // is deleted.
  base::flat_set<std::unique_ptr<CastWebView>> web_views_;

  const std::unique_ptr<LRURendererCache> overlay_renderer_cache_;
  bool immediately_delete_webviews_ = false;

  std::vector<std::string> cast_webui_hosts_;

  const scoped_refptr<base::SequencedTaskRunner> task_runner_;
  base::WeakPtr<CastWebService> weak_ptr_;

  SEQUENCE_CHECKER(sequence_checker_);
  base::WeakPtrFactory<CastWebService> weak_factory_;
};

}  // namespace chromecast

#endif  // CHROMECAST_BROWSER_CAST_WEB_SERVICE_H_