chromium/android_webview/browser/aw_permission_manager.h

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

#ifndef ANDROID_WEBVIEW_BROWSER_AW_PERMISSION_MANAGER_H_
#define ANDROID_WEBVIEW_BROWSER_AW_PERMISSION_MANAGER_H_

#include <map>
#include <memory>

#include "android_webview/browser/aw_context_permissions_delegate.h"
#include "base/containers/id_map.h"
#include "base/containers/lru_cache.h"
#include "base/functional/callback_forward.h"
#include "base/memory/raw_ref.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "content/public/browser/permission_controller_delegate.h"
#include "content/public/browser/permission_result.h"

namespace blink {
enum class PermissionType;
}

namespace android_webview {

class AwBrowserPermissionRequestDelegate;
class LastRequestResultCache;

class AwPermissionManager : public content::PermissionControllerDelegate {
 public:
  explicit AwPermissionManager(
      const AwContextPermissionsDelegate& context_delegate);

  AwPermissionManager(const AwPermissionManager&) = delete;
  AwPermissionManager& operator=(const AwPermissionManager&) = delete;

  ~AwPermissionManager() override;

  // PermissionControllerDelegate implementation.
  void RequestPermissions(
      content::RenderFrameHost* render_frame_host,
      const content::PermissionRequestDescription& request_description,
      base::OnceCallback<
          void(const std::vector<blink::mojom::PermissionStatus>&)> callback)
      override;
  void ResetPermission(blink::PermissionType permission,
                       const GURL& requesting_origin,
                       const GURL& embedding_origin) override;
  void RequestPermissionsFromCurrentDocument(
      content::RenderFrameHost* render_frame_host,
      const content::PermissionRequestDescription& request_description,
      base::OnceCallback<
          void(const std::vector<blink::mojom::PermissionStatus>&)> callback)
      override;
  blink::mojom::PermissionStatus GetPermissionStatus(
      blink::PermissionType permission,
      const GURL& requesting_origin,
      const GURL& embedding_origin) override;
  content::PermissionResult GetPermissionResultForOriginWithoutContext(
      blink::PermissionType permission,
      const url::Origin& requesting_origin,
      const url::Origin& embedding_origin) override;
  blink::mojom::PermissionStatus GetPermissionStatusForCurrentDocument(
      blink::PermissionType permission,
      content::RenderFrameHost* render_frame_host,
      bool should_include_device_status) override;
  blink::mojom::PermissionStatus GetPermissionStatusForWorker(
      blink::PermissionType permission,
      content::RenderProcessHost* render_process_host,
      const GURL& worker_origin) override;
  blink::mojom::PermissionStatus GetPermissionStatusForEmbeddedRequester(
      blink::PermissionType permission,
      content::RenderFrameHost* render_frame_host,
      const url::Origin& requesting_origin) override;
  void SetOriginCanReadEnumerateDevicesAudioLabels(const url::Origin& origin,
                                                   bool audio);
  void SetOriginCanReadEnumerateDevicesVideoLabels(const url::Origin& origin,
                                                   bool video);
  bool ShouldShowEnumerateDevicesAudioLabels(const url::Origin& origin);
  bool ShouldShowEnumerateDevicesVideoLabels(const url::Origin& origin);
  void ClearEnumerateDevicesCachedPermission(const url::Origin& origin,
                                             bool remove_audio,
                                             bool remove_video);

 protected:
  void CancelPermissionRequest(int request_id);
  void CancelPermissionRequests();

 private:
  class PendingRequest;
  using PendingRequestsMap = base::IDMap<std::unique_ptr<PendingRequest>>;

  virtual int GetRenderProcessID(content::RenderFrameHost* render_frame_host);
  virtual int GetRenderFrameID(content::RenderFrameHost* render_frame_host);
  virtual GURL LastCommittedMainOrigin(
      content::RenderFrameHost* render_frame_host);
  virtual AwBrowserPermissionRequestDelegate* GetDelegate(int render_process_id,
                                                          int render_frame_id);

  blink::mojom::PermissionStatus GetPermissionStatusInternal(
      blink::PermissionType permission,
      const GURL& requesting_origin,
      const GURL& embedding_origin,
      content::WebContents* web_contents);

  blink::mojom::PermissionStatus GetGeolocationPermission(
      const GURL& requesting_origin,
      content::WebContents* web_contents);

  // The weak pointer to this is used to clean up any information which is
  // stored in the pending request or result cache maps. However, the callback
  // should be run regardless of whether the class is still alive so the method
  // is static.
  static void OnRequestResponse(
      const base::WeakPtr<AwPermissionManager>& manager,
      int request_id,
      blink::PermissionType permission,
      bool allowed);

  // A little helper func to cache storage access API grants. It will associate
  // them with the top level origin since we currently only grant SAA results
  // based off of top level DALs.
  // The bool |allowed| is returned again by this function so that we can
  // chain it with OnRequestResponse to resolve permission requests.
  static bool CacheAutoSAA(const base::WeakPtr<AwPermissionManager>& manager,
                           const url::Origin& origin,
                           bool allowed);

  base::raw_ref<const AwContextPermissionsDelegate> context_delegate_;
  PendingRequestsMap pending_requests_;
  std::unique_ptr<LastRequestResultCache> result_cache_;
  // Maps origins to whether they can view device labels.
  // The pair is ordered as (Audio, Video).
  std::map<url::Origin, std::pair<bool, bool>> enumerate_devices_labels_cache_;

  // Given that the status of the grant is unlikely to change in an app's
  // lifecycle, we cache this result after retrieving it from the
  // delegate.
  base::NoDestructor<base::LRUCache<std::string, bool>> saa_cache_;
  SEQUENCE_CHECKER(sequence_checker_);

  base::WeakPtrFactory<AwPermissionManager> weak_ptr_factory_{this};
};

} // namespace android_webview

#endif  // ANDROID_WEBVIEW_BROWSER_AW_PERMISSION_MANAGER_H_