chromium/chrome/browser/chromeos/policy/dlp/dlp_content_restriction_set.cc

// Copyright 2020 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/chromeos/policy/dlp/dlp_content_restriction_set.h"

#include <algorithm>

#include "base/containers/flat_map.h"
#include "base/no_destructor.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/chromeos/policy/dlp/dlp_rules_manager.h"
#include "chrome/browser/chromeos/policy/dlp/dlp_rules_manager_factory.h"
#include "url/gurl.h"

namespace policy {

namespace {
static base::NoDestructor<base::flat_map<GURL, DlpContentRestrictionSet>>
    g_restrictions_for_url_for_testing;
}

DlpContentRestrictionSet::DlpContentRestrictionSet() {
  restrictions_.fill(RestrictionLevelAndUrl());
}

DlpContentRestrictionSet::DlpContentRestrictionSet(
    DlpContentRestriction restriction,
    DlpRulesManager::Level level) {
  restrictions_.fill(RestrictionLevelAndUrl());
  restrictions_[static_cast<int>(restriction)].level = level;
}

DlpContentRestrictionSet::DlpContentRestrictionSet(
    const DlpContentRestrictionSet& restriction_set) = default;

DlpContentRestrictionSet& DlpContentRestrictionSet::operator=(
    const DlpContentRestrictionSet& other) = default;

DlpContentRestrictionSet::~DlpContentRestrictionSet() = default;

bool DlpContentRestrictionSet::operator==(
    const DlpContentRestrictionSet& other) const {
  return restrictions_ == other.restrictions_;
}

bool DlpContentRestrictionSet::operator!=(
    const DlpContentRestrictionSet& other) const {
  return !(*this == other);
}

void DlpContentRestrictionSet::SetRestriction(DlpContentRestriction restriction,
                                              DlpRulesManager::Level level,
                                              const GURL& url) {
  if (level > restrictions_[static_cast<int>(restriction)].level) {
    restrictions_[static_cast<int>(restriction)] =
        RestrictionLevelAndUrl(level, url);
  }
}

DlpRulesManager::Level DlpContentRestrictionSet::GetRestrictionLevel(
    DlpContentRestriction restriction) const {
  return restrictions_[static_cast<int>(restriction)].level;
}

const GURL& DlpContentRestrictionSet::GetRestrictionUrl(
    DlpContentRestriction restriction) const {
  return restrictions_[static_cast<int>(restriction)].url;
}

RestrictionLevelAndUrl DlpContentRestrictionSet::GetRestrictionLevelAndUrl(
    DlpContentRestriction restriction) const {
  return restrictions_[static_cast<int>(restriction)];
}

bool DlpContentRestrictionSet::IsEmpty() const {
  for (size_t i = 0; i < restrictions_.size(); ++i) {
    if (restrictions_[i].level != DlpRulesManager::Level::kNotSet)
      return false;
  }
  return true;
}

void DlpContentRestrictionSet::UnionWith(
    const DlpContentRestrictionSet& other) {
  for (size_t i = 0; i < restrictions_.size(); ++i) {
    if (other.restrictions_[i].level > restrictions_[i].level) {
      restrictions_[i] = other.restrictions_[i];
    }
  }
}

DlpContentRestrictionSet DlpContentRestrictionSet::DifferenceWith(
    const DlpContentRestrictionSet& other) const {
  // Leave only the restrictions that are present in |this|, but not in |other|.
  DlpContentRestrictionSet result;
  for (size_t i = 0; i < restrictions_.size(); ++i) {
    if (restrictions_[i].level > other.restrictions_[i].level) {
      result.restrictions_[i] = restrictions_[i];
    }
  }
  return result;
}

// static
DlpContentRestrictionSet DlpContentRestrictionSet::GetForURL(const GURL& url) {
  if (g_restrictions_for_url_for_testing->find(url) !=
      g_restrictions_for_url_for_testing->end()) {
    return g_restrictions_for_url_for_testing->at(url);
  }

  DlpContentRestrictionSet set;

  DlpRulesManager* dlp_rules_manager =
      DlpRulesManagerFactory::GetForPrimaryProfile();
  if (!dlp_rules_manager)
    return set;

  const size_t kRestrictionsCount = 4;
  static constexpr std::array<
      std::pair<DlpRulesManager::Restriction, DlpContentRestriction>,
      kRestrictionsCount>
      kRestrictionsArray = {{{DlpRulesManager::Restriction::kScreenshot,
                              DlpContentRestriction::kScreenshot},
                             {DlpRulesManager::Restriction::kPrivacyScreen,
                              DlpContentRestriction::kPrivacyScreen},
                             {DlpRulesManager::Restriction::kPrinting,
                              DlpContentRestriction::kPrint},
                             {DlpRulesManager::Restriction::kScreenShare,
                              DlpContentRestriction::kScreenShare}}};

  for (const auto& restriction : kRestrictionsArray) {
    DlpRulesManager::Level level =
        dlp_rules_manager->IsRestricted(url, restriction.first);
    if (level == DlpRulesManager::Level::kNotSet ||
        level == DlpRulesManager::Level::kAllow)
      continue;
    set.SetRestriction(restriction.second, level, url);
  }

  return set;
}

// static
void DlpContentRestrictionSet::SetRestrictionsForURLForTesting(
    const GURL& url,
    const DlpContentRestrictionSet& restrictions) {
  g_restrictions_for_url_for_testing->insert_or_assign(url, restrictions);
}

}  // namespace policy