File: permissions_utils.mm

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; 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-- 4,971 bytes parent folder | download | duplicates (7)
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 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 "ui/base/cocoa/permissions_utils.h"

#include <CoreGraphics/CoreGraphics.h>
#include <Foundation/Foundation.h>
#import <ScreenCaptureKit/ScreenCaptureKit.h>

#include "base/apple/bridging.h"
#include "base/apple/foundation_util.h"
#include "base/apple/scoped_cftyperef.h"
#include "base/feature_list.h"
#include "base/logging.h"
#include "base/mac/mac_util.h"
#include "base/task/thread_pool.h"

namespace ui {
namespace {

BASE_FEATURE(kWarmScreenCaptureSonoma,
             "WarmScreenCaptureSonoma",
             base::FEATURE_ENABLED_BY_DEFAULT);

BASE_FEATURE(kWarmScreenCaptureSequoia,
             "WarmScreenCaptureSequoia",
             base::FEATURE_DISABLED_BY_DEFAULT);

bool ShouldWarmScreenCapture() {
  const int macos_version = base::mac::MacOSVersion();
  // On macOS < 14, we're using CGWindowListCreateImage to capture a screenshot.
  // Starting in macOS 14, CGWindowListCreateImage causes a "your screen is
  // being captured" chip to show in the menu bar while an app is capturing the
  // screen, and if it's a one-time image capture, it shows for ten seconds.
  if (macos_version < 14'00'00) {
    return true;
  }

  // Kill switch, Sonoma.
  if (macos_version < 15'00'00 &&
      !base::FeatureList::IsEnabled(kWarmScreenCaptureSonoma)) {
    return false;
  }

  // Feature disabled by default for Sequoia unless explicitly enabled.
  if (macos_version >= 15'00'00 &&
      !base::FeatureList::IsEnabled(kWarmScreenCaptureSequoia)) {
    return false;
  }

  // On macOS >= 14, Apple introduced SCScreenshotManager that can be used to
  // capture a screenshot without any notification shown to the user. There's a
  // bug in this API that was fixed in 14.4.
  if (macos_version >= 14'04'00) {
    return true;
  }

  // macOS 14-14.3.
  return false;
}

// Capture a screenshot and throw away the result.
void CaptureScreenshot() {
  if (@available(macOS 14.0, *)) {
    CHECK(base::FeatureList::IsEnabled(kWarmScreenCaptureSonoma));
    // Capturing a screenshot using SCK involves three asynchronous steps:
    //   1. Request shareable contents (getShareableContent...),
    //   2. Instruct SCScreenshotManager to take a screenshot (captureImage...),
    //   3. Receive a callback with the actual image.
    auto shareable_content_handler = ^(SCShareableContent* content,
                                       NSError* error) {
      if (!content.displays.count || error) {
        LOG(WARNING)
            << "Failed to get shareable content during WarmScreenCapture.";
        return;
      }

      SCDisplay* first_display = content.displays.firstObject;
      SCStreamConfiguration* config = [[SCStreamConfiguration alloc] init];
      // Set the size to something small to make it clear to anyone reading the
      // code that the screenshot contains no real information.
      config.width = 16;
      config.height = 10;
      auto screenshot_handler = ^(CGImageRef sampleBuffer, NSError* sc_error) {
        // Do nothing.
      };

      SCContentFilter* filter =
          [[SCContentFilter alloc] initWithDisplay:first_display
                                  excludingWindows:@[]];
      [SCScreenshotManager captureImageWithFilter:filter
                                    configuration:config
                                completionHandler:screenshot_handler];
    };
    [SCShareableContent
        getShareableContentExcludingDesktopWindows:true
                               onScreenWindowsOnly:true
                                 completionHandler:shareable_content_handler];
  } else {
    base::apple::ScopedCFTypeRef<CGImageRef>(
        CGWindowListCreateImage(CGRectInfinite, kCGWindowListOptionOnScreenOnly,
                                kCGNullWindowID, kCGWindowImageDefault));
  }
}

}  // namespace

bool IsScreenCaptureAllowed() {
    return CGPreflightScreenCaptureAccess();
}

bool TryPromptUserForScreenCapture() {
    return CGRequestScreenCaptureAccess();
}

void WarmScreenCapture() {
  if (!ShouldWarmScreenCapture()) {
    return;
  }

  // WarmScreenCapture() is meant to be called during early startup. Since the
  // calls to warm the cache may block, execute them off the main thread so we
  // don't hold up startup. To be effective these calls need to run before
  // Chrome is updated. Running them off the main thread technically opens us
  // to a race condition, however updating happens way later so this is not a
  // concern.
  base::ThreadPool::PostTask(
      FROM_HERE,
      // Checking screen capture access hits the TCC.db and reads Chrome's
      // code signature from disk, marking as MayBlock.
      {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
      base::BindOnce([] {
        if (IsScreenCaptureAllowed()) {
          CaptureScreenshot();
        }
      }));
}

}  // namespace ui