File: screen_capture_permission_checker_mac.mm

package info (click to toggle)
chromium 139.0.7258.138-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 6,120,676 kB
  • sloc: cpp: 35,100,869; 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 (135 lines) | stat: -rw-r--r-- 5,067 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
// Copyright 2024 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/ui/views/desktop_capture/screen_capture_permission_checker_mac.h"

#include "base/mac/mac_util.h"
#include "base/metrics/histogram_functions.h"
#include "chrome/browser/media/webrtc/system_media_capture_permissions_mac.h"
#include "content/public/browser/browser_thread.h"
#include "ui/base/cocoa/permissions_utils.h"
#include "ui/base/ui_base_features.h"

// If enabled, a `ScreenCapturePermissionChecker` will be instantiated.
// * The `ScreenCapturePermissionChecker` object *will* record the initial
//   screen-sharing permission status.
// * Depending on the state of the `kDesktopCapturePermissionChecker*` features
//   defined below, the `ScreenCapturePermissionChecker` object may additionally
//   send updates on the system's screen-recording permission-state, which may
//   be used to display a permission notification and a button to open the
//   screen-recording settings when the permission is missing.
BASE_FEATURE(kDesktopCapturePermissionCheckerKillSwitch,
             "DesktopCapturePermissionCheckerKillSwitch",
             base::FEATURE_ENABLED_BY_DEFAULT);

// Only has an effect if `kDesktopCapturePermissionCheckerKillSwitch` is enabled
// and macOS 14.4+ is used, in which case:
// * If the user is missing screen-sharing permissions, then when
//   `kDesktopCapturePermissionCheckerMacos14_4Plus` is enabled, users will be
//   presented with a button letting them quickly jump into the OS settings
//   where they can grant the missing permission.
// * If the user has screen-sharing permission,
// `kDesktopCapturePermissionCheckerMacos14_4Plus` will not have any
// user-visible effect.
BASE_FEATURE(kDesktopCapturePermissionCheckerMacos14_4Plus,
             "DesktopCapturePermissionCheckerMacos14_4Plus",
             base::FEATURE_ENABLED_BY_DEFAULT);

// This feature is the same as `kDesktopCapturePermissionCheckerMacos14_4Plus`
// but only affects macOS <14.4.
BASE_FEATURE(kDesktopCapturePermissionCheckerPreMacos14_4,
             "DesktopCapturePermissionCheckerPreMacos14_4",
             base::FEATURE_DISABLED_BY_DEFAULT);

const base::FeatureParam<int> kDesktopCapturePermissionCheckerUpdateIntervalMs{
    &kDesktopCapturePermissionCheckerMacos14_4Plus, "update_interval_ms", 1000};

namespace {
bool IsDesktopCapturePermissionCheckerEnabled() {
  const int macos_version = base::mac::MacOSVersion();
  if (macos_version >= 14'04'00 &&
      !base::FeatureList::IsEnabled(
          kDesktopCapturePermissionCheckerMacos14_4Plus)) {
    return false;
  }
  if (macos_version < 14'04'00 &&
      !base::FeatureList::IsEnabled(
          kDesktopCapturePermissionCheckerPreMacos14_4)) {
    return false;
  }
  return true;
}
}  // namespace

std::unique_ptr<ScreenCapturePermissionCheckerMac>
ScreenCapturePermissionCheckerMac::MaybeCreate(
    base::RepeatingCallback<void(bool)> callback) {
  if (!system_media_permissions::ScreenCaptureNeedsSystemLevelPermissions()) {
    return nullptr;
  }

  if (base::FeatureList::IsEnabled(
          kDesktopCapturePermissionCheckerKillSwitch) &&
      base::mac::MacOSMajorVersion() >= 13) {
    return std::make_unique<ScreenCapturePermissionCheckerMac>(
        callback, base::BindRepeating(&ui::IsScreenCaptureAllowed));
  }
  return nullptr;
}

ScreenCapturePermissionCheckerMac::ScreenCapturePermissionCheckerMac(
    base::RepeatingCallback<void(bool)> callback,
    base::RepeatingCallback<bool()> is_screen_capture_allowed)
    : callback_(std::move(callback)),
      is_screen_capture_allowed_(std::move(is_screen_capture_allowed)) {
  OnRecurrentPermissionCheck();

  if (!IsDesktopCapturePermissionCheckerEnabled()) {
    return;
  }

  // Passing `this` to `timer_.Start` is safe since `timer_` is owned by `this`.
  timer_.Start(FROM_HERE,
               base::Milliseconds(
                   kDesktopCapturePermissionCheckerUpdateIntervalMs.Get()),
               this,
               &ScreenCapturePermissionCheckerMac::OnRecurrentPermissionCheck);
}

ScreenCapturePermissionCheckerMac::~ScreenCapturePermissionCheckerMac() =
    default;

void ScreenCapturePermissionCheckerMac::Stop() {
  timer_.Stop();
}

void ScreenCapturePermissionCheckerMac::OnRecurrentPermissionCheck() {
  if (has_pending_task_) {
    return;
  }
  has_pending_task_ = true;

  sequenced_task_runner_->PostTaskAndReplyWithResult(
      FROM_HERE, is_screen_capture_allowed_,
      base::BindOnce(&ScreenCapturePermissionCheckerMac::OnPermissionUpdate,
                     weak_factory_.GetWeakPtr()));
}

void ScreenCapturePermissionCheckerMac::OnPermissionUpdate(
    bool has_permission) {
  has_pending_task_ = false;

  if (!has_recorded_uma_) {
    base::UmaHistogramBoolean(
        "Media.Ui.GetDisplayMedia.HasScreenRecordingPermission",
        has_permission);
    has_recorded_uma_ = true;
  }

  if (!IsDesktopCapturePermissionCheckerEnabled()) {
    return;
  }

  callback_.Run(has_permission);
}