File: clipboard_restriction_service.cc

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (140 lines) | stat: -rw-r--r-- 5,538 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
// 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 "components/enterprise/content/clipboard_restriction_service.h"

#include "components/enterprise/content/pref_names.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
#include "components/policy/core/common/policy_pref_names.h"
#include "components/prefs/pref_service.h"
#include "components/strings/grit/components_strings.h"
#include "components/url_matcher/url_util.h"
#include "components/user_prefs/user_prefs.h"
#include "content/public/browser/browser_context.h"
#include "ui/base/l10n/l10n_util.h"

ClipboardRestrictionService::ClipboardRestrictionService(
    PrefService* pref_service)
    : pref_service_(pref_service),
      next_id_(0),
      enable_url_matcher_(nullptr),
      disable_url_matcher_(nullptr) {
  pref_change_registrar_.Init(pref_service_);
  pref_change_registrar_.Add(
      enterprise::content::kCopyPreventionSettings,
      base::BindRepeating(&ClipboardRestrictionService::UpdateSettings,
                          base::Unretained(this)));
  UpdateSettings();
}

ClipboardRestrictionService::~ClipboardRestrictionService() = default;

bool ClipboardRestrictionService::IsUrlAllowedToCopy(
    const GURL& url,
    size_t data_size_in_bytes,
    std::u16string* replacement_data) const {
  if (!enable_url_matcher_ || !disable_url_matcher_)
    return true;

  if (data_size_in_bytes < min_data_size_)
    return true;

  // The copy is allowed in the following scenarios:
  // 1. The URL doesn't match a pattern in the enable list
  // or
  // 2. The URL matches a pattern in the enable list but also matches a pattern
  //    in the disable list
  // Conversely, it is blocked iff it matches a pattern in the enable list and
  // doesn't match a pattern in the disable list.
  bool is_allowed = enable_url_matcher_->MatchURL(url).empty() ||
                    disable_url_matcher_->MatchURL(url).size() > 0;

  if (!is_allowed && replacement_data) {
    *replacement_data = l10n_util::GetStringUTF16(
        IDS_ENTERPRISE_COPY_PREVENTION_WARNING_MESSAGE);
  }

  return is_allowed;
}

void ClipboardRestrictionService::UpdateSettings() {
  // This is infrequent enough that this code can teardown the url matcher
  // entirely and rebuild it. There's also no state that should be carried over
  // from the previous values, so doing it this way makes that semantic clearer.
  enable_url_matcher_ = nullptr;
  disable_url_matcher_ = nullptr;

  if (!pref_service_->IsManagedPreference(
          enterprise::content::kCopyPreventionSettings)) {
    return;
  }

  const base::Value::Dict& settings =
      pref_service_->GetDict(enterprise::content::kCopyPreventionSettings);
  const base::Value::List* enable = settings.FindList(
      enterprise::content::kCopyPreventionSettingsEnableFieldName);
  const base::Value::List* disable = settings.FindList(
      enterprise::content::kCopyPreventionSettingsDisableFieldName);

  DCHECK(enable);
  DCHECK(disable);

  enable_url_matcher_ = std::make_unique<url_matcher::URLMatcher>();
  disable_url_matcher_ = std::make_unique<url_matcher::URLMatcher>();

  // For the following 2 calls, the second param is a bool called `allow`. In
  // this context, we're not concerned about a URL being "allowed" or not, but
  // rather with this prevention feature being enabled on a given URL. Because
  // of this, pass `true` for patterns in the `enable` list and false for
  // patterns in the `disable` list. If the URL Matcher subsequently matches a
  // URL as "allowed", it means the prevention feature is active for that URL
  // and the copy will be blocked. While confusing, this is mostly to map to the
  // same policy format as the content analysis connector, which also has
  // "enable" and "disable" lists used in this way.
  url_matcher::util::AddFiltersWithLimit(enable_url_matcher_.get(), true,
                                         &next_id_, *enable);
  url_matcher::util::AddFiltersWithLimit(disable_url_matcher_.get(), false,
                                         &next_id_, *disable);

  std::optional<int> min_data_size = settings.FindInt(
      enterprise::content::kCopyPreventionSettingsMinDataSizeFieldName);
  DCHECK(min_data_size);
  DCHECK(min_data_size >= 0);
  min_data_size_ = *min_data_size;
}

// static
ClipboardRestrictionServiceFactory*
ClipboardRestrictionServiceFactory::GetInstance() {
  return base::Singleton<ClipboardRestrictionServiceFactory>::get();
}

// static
ClipboardRestrictionService*
ClipboardRestrictionServiceFactory::GetForBrowserContext(
    content::BrowserContext* context) {
  return static_cast<ClipboardRestrictionService*>(
      GetInstance()->GetServiceForBrowserContext(context, true));
}

ClipboardRestrictionServiceFactory::ClipboardRestrictionServiceFactory()
    : BrowserContextKeyedServiceFactory(
          "PolicyClipboardRestriction",
          BrowserContextDependencyManager::GetInstance()) {}

ClipboardRestrictionServiceFactory::~ClipboardRestrictionServiceFactory() =
    default;

content::BrowserContext*
ClipboardRestrictionServiceFactory::GetBrowserContextToUse(
    content::BrowserContext* context) const {
  return context;
}

std::unique_ptr<KeyedService>
ClipboardRestrictionServiceFactory::BuildServiceInstanceForBrowserContext(
    content::BrowserContext* context) const {
  return std::make_unique<ClipboardRestrictionService>(
      user_prefs::UserPrefs::Get(context));
}