chromium/chrome/browser/media/webrtc/capture_policy_utils.cc

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

#include "chrome/browser/media/webrtc/capture_policy_utils.h"

#include <vector>

#include "base/feature_list.h"
#include "base/functional/callback.h"
#include "base/ranges/algorithm.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/ash/crosapi/crosapi_manager.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/picture_in_picture/picture_in_picture_window_manager.h"
#include "chrome/browser/policy/policy_util.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/pref_names.h"
#include "chrome/grit/generated_resources.h"
#include "components/content_settings/browser/page_specific_content_settings.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/content_settings/core/common/content_settings_pattern.h"
#include "components/content_settings/core/common/pref_names.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/web_contents.h"
#include "media/base/media_switches.h"
#include "third_party/blink/public/common/features_generated.h"
#include "ui/base/mojom/dialog_button.mojom.h"
#include "url/gurl.h"
#include "url/origin.h"

#if !BUILDFLAG(IS_ANDROID)
#include "chrome/browser/ui/tab_modal_confirm_dialog.h"
#include "chrome/browser/ui/tab_modal_confirm_dialog_delegate.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/ui_base_types.h"
#endif

#if BUILDFLAG(IS_CHROMEOS)
#include "chromeos/crosapi/mojom/multi_capture_service.mojom.h"
#endif  // BUILDFLAG(IS_CHROMEOS)

#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "chrome/browser/ash/crosapi/crosapi_ash.h"
#include "chrome/browser/ash/crosapi/multi_capture_service_ash.h"
#include "chrome/browser/ash/policy/multi_screen_capture/multi_screen_capture_policy_service.h"
#include "chrome/browser/ash/policy/multi_screen_capture/multi_screen_capture_policy_service_factory.h"
#endif  // BUILDFLAG(IS_CHROMEOS_ASH)

#if BUILDFLAG(IS_CHROMEOS_LACROS)
#include "chromeos/lacros/lacros_service.h"
#endif  // BUILDFLAG(IS_CHROMEOS_LACROS)

namespace {

#if BUILDFLAG(IS_CHROMEOS)
crosapi::mojom::MultiCaptureService* g_multi_capture_service_for_testing =
    nullptr;

void IsMultiCaptureAllowedForAnyOriginOnMainProfileResultReceived(
    base::OnceCallback<void(bool)> callback,
    content::BrowserContext* context,
    bool is_multi_capture_allowed_for_any_origin_on_main_profile) {
  // If the new MultiScreenCaptureAllowedForUrls policy permits access, exit
  // early. If not, check the legacy
  // GetDisplayMediaSetSelectAllScreensAllowedForUrls policy.
  if (is_multi_capture_allowed_for_any_origin_on_main_profile) {
    std::move(callback).Run(true);
    return;
  }

  // TODO(b/329064666): Remove the checks below once the pivot to IWAs is
  // complete.
  Profile* profile = Profile::FromBrowserContext(context);
  if (!profile) {
    std::move(callback).Run(false);
    return;
  }

#if BUILDFLAG(IS_CHROMEOS_LACROS)
  // To ensure that a user is informed at login time that capturing of all
  // screens can happen (for privacy reasons), this API is only available on
  // primary profiles.
  if (!profile->IsMainProfile()) {
    std::move(callback).Run(false);
    return;
  }
#endif  // BUILDFLAG(IS_CHROMEOS_LACROS)

  HostContentSettingsMap* host_content_settings_map =
      HostContentSettingsMapFactory::GetForProfile(profile);
  if (!host_content_settings_map) {
    std::move(callback).Run(false);
    return;
  }
  ContentSettingsForOneType content_settings =
      host_content_settings_map->GetSettingsForOneType(
          ContentSettingsType::ALL_SCREEN_CAPTURE);
  std::move(callback).Run(base::ranges::any_of(
      content_settings, [](const ContentSettingPatternSource& source) {
        return source.GetContentSetting() ==
               ContentSetting::CONTENT_SETTING_ALLOW;
      }));
}

void CheckAllScreensMediaAllowedForIwaResultReceived(
    base::OnceCallback<void(bool)> callback,
    const GURL& url,
    content::BrowserContext* context,
    bool result) {
  if (result) {
    std::move(callback).Run(true);
    return;
  }

  Profile* profile = Profile::FromBrowserContext(context);
  if (!profile) {
    std::move(callback).Run(false);
    return;
  }
  HostContentSettingsMap* host_content_settings_map =
      HostContentSettingsMapFactory::GetForProfile(profile);
  if (!host_content_settings_map) {
    std::move(callback).Run(false);
    return;
  }
  ContentSetting auto_accept_enabled =
      host_content_settings_map->GetContentSetting(
          url, url, ContentSettingsType::ALL_SCREEN_CAPTURE);
  std::move(callback).Run(auto_accept_enabled ==
                          ContentSetting::CONTENT_SETTING_ALLOW);
}
#endif  // BUILDFLAG(IS_CHROMEOS)

}  // namespace

namespace capture_policy {

// This pref connects to the GetDisplayMediaSetSelectAllScreensAllowedForUrls
// policy. To avoid dynamic refresh, this pref will not be read directly, but
// the value will be copied manually to the
// kManagedAccessToGetAllScreensMediaInSessionAllowedForUrls pref, which is then
// consumed by content settings to check if access to `getAllScreensMedia` shall
// be permitted for a given origin.
// TODO(b/329064666): Remove this pref once the pivot to IWAs is complete.
const char kManagedAccessToGetAllScreensMediaAllowedForUrls[] =;

#if BUILDFLAG(IS_CHROMEOS_ASH)

// This pref connects to the MultiScreenCaptureAllowedForUrls policy and will
// replace the deprecated GetDisplayMediaSetSelectAllScreensAllowedForUrls
// policy once the pivot to IWAs is complete.
const char kManagedMultiScreenCaptureAllowedForUrls[] =
    "profile.managed_multi_screen_capture_allowed_for_urls";

#endif  // BUILDFLAG(IS_CHROMEOS_ASH)

namespace {

struct RestrictedCapturePolicy {};

}  // namespace

#if BUILDFLAG(IS_CHROMEOS)
void SetMultiCaptureServiceForTesting(
    crosapi::mojom::MultiCaptureService* service) {
  CHECK_IS_TEST();
  CHECK(!service || !g_multi_capture_service_for_testing);
  g_multi_capture_service_for_testing = service;
}

crosapi::mojom::MultiCaptureService* GetMultiCaptureService() {
  if (g_multi_capture_service_for_testing) {
    return g_multi_capture_service_for_testing;
  }

#if BUILDFLAG(IS_CHROMEOS_LACROS)
  chromeos::LacrosService* lacros_service = chromeos::LacrosService::Get();
  const int multi_capture_service_version =
      lacros_service
          ->GetInterfaceVersion<crosapi::mojom::MultiCaptureService>();
  if (multi_capture_service_version >=
      static_cast<int>(crosapi::mojom::MultiCaptureService::MethodMinVersions::
                           kIsMultiCaptureAllowedMinVersion)) {
    return lacros_service->GetRemote<crosapi::mojom::MultiCaptureService>()
        .get();
  }
  return nullptr;
#elif BUILDFLAG(IS_CHROMEOS_ASH)
  return crosapi::CrosapiManager::Get()
      ->crosapi_ash()
      ->multi_capture_service_ash();
#endif
}
#endif  // BUILDFLAG(IS_CHROMEOS)

bool IsOriginInList(const GURL& request_origin,
                    const base::Value::List& allowed_origins) {}

AllowedScreenCaptureLevel GetAllowedCaptureLevel(
    const GURL& request_origin,
    content::WebContents* capturer_web_contents) {}

AllowedScreenCaptureLevel GetAllowedCaptureLevel(const GURL& request_origin,
                                                 const PrefService& prefs) {}

void RegisterProfilePrefs(PrefRegistrySimple* registry) {}

void CheckGetAllScreensMediaAllowedForAnyOrigin(
    content::BrowserContext* context,
    base::OnceCallback<void(bool)> callback) {}

void CheckGetAllScreensMediaAllowed(content::BrowserContext* context,
                                    const GURL& url,
                                    base::OnceCallback<void(bool)> callback) {}

#if !BUILDFLAG(IS_ANDROID)
bool IsTransientActivationRequiredForGetDisplayMedia(
    content::WebContents* contents) {}
#endif  // !BUILDFLAG(IS_ANDROID)

DesktopMediaList::WebContentsFilter GetIncludableWebContentsFilter(
    const GURL& request_origin,
    AllowedScreenCaptureLevel capture_level) {}

void FilterMediaList(std::vector<DesktopMediaList::Type>& media_types,
                     AllowedScreenCaptureLevel capture_level) {}

#if !BUILDFLAG(IS_ANDROID)
class CaptureTerminatedDialogDelegate : public TabModalConfirmDialogDelegate {};
#endif

void ShowCaptureTerminatedDialog(content::WebContents* contents) {}

}  // namespace capture_policy