File: metrics.mm

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 (133 lines) | stat: -rw-r--r-- 4,747 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
// 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/mac/metrics.h"

#import <Foundation/Foundation.h>
#include <Security/Security.h>
#include <sys/attr.h>
#include <sys/vnode.h>
#include <unistd.h>

#include "base/containers/fixed_flat_map.h"
#include "base/functional/bind.h"
#include "base/functional/callback_forward.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/scoped_refptr.h"
#include "base/metrics/histogram_functions.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/thread_pool.h"
#include "chrome/browser/upgrade_detector/upgrade_detector.h"

namespace {

mac_metrics::FileSystemType VolumeTagToFileSystemType(enum vtagtype tag) {
  static constexpr auto map =
      base::MakeFixedFlatMap<enum vtagtype, mac_metrics::FileSystemType>({
          {VT_HFS, mac_metrics::FileSystemType::kHFS},
          {VT_APFS, mac_metrics::FileSystemType::kAPFS},
      });
  const auto it = map.find(tag);
  return it != map.end() ? it->second : mac_metrics::FileSystemType::kUnknown;
}

void RecordAppFileSystemTypeUsingVolumeTag(enum vtagtype tag) {
  base::UmaHistogramEnumeration("Mac.AppFileSystemType",
                                VolumeTagToFileSystemType(tag));
}

void RecordAppUpgradeCodeSignatureValidationStatus(OSStatus status) {
  // There are currently 83 possible code signing errSec values.
  // https://github.com/apple-oss-distributions/Security/blob/Security-61040.80.10.0.1/OSX/libsecurity_codesigning/lib/CSCommon.h#L64
  base::UmaHistogramSparse("Mac.AppUpgradeCodeSignatureValidationStatus",
                           status);
}

void RecordAppUpgradeCodeSignatureValidationImpl(base::OnceClosure closure) {
  // SecCodeCheckValidity blocks on I/O, do the validation and metric recording
  // on from background thread.
  scoped_refptr<base::SequencedTaskRunner> task_runner =
      base::ThreadPool::CreateSequencedTaskRunner(
          {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
  task_runner->PostTask(
      FROM_HERE,
      base::BindOnce(
          [](base::OnceClosure closure) {
            SecCodeRef self_code = nullptr;
            if (SecCodeCopySelf(kSecCSDefaultFlags, &self_code) !=
                errSecSuccess) {
              std::move(closure).Run();
              return;
            }
            // Ignoring revocation status with the kSecCSNoNetworkAccess.
            RecordAppUpgradeCodeSignatureValidationStatus(SecCodeCheckValidity(
                self_code, kSecCSNoNetworkAccess, nullptr));
            if (self_code) {
              CFRelease(self_code);
            }

            std::move(closure).Run();
          },
          std::move(closure)));
}

struct alignas(4) AttributeBuffer {
  uint32_t length;
  enum vtagtype tag;
} __attribute__((packed));

}  // namespace

namespace mac_metrics {

Metrics::Metrics() {
  UpgradeDetector::GetInstance()->AddObserver(this);
}

Metrics::~Metrics() {
  UpgradeDetector::GetInstance()->RemoveObserver(this);
}

void Metrics::RecordAppFileSystemType() {
  const char* path =
      NSProcessInfo.processInfo.arguments.firstObject.fileSystemRepresentation;

  struct attrlist attr_list = {
      .bitmapcount = ATTR_BIT_MAP_COUNT,  // default
      .commonattr = ATTR_CMN_OBJTAG       // get the file system type
  };
  struct AttributeBuffer buff;

  // Using getattrlist instead of statfs. ATTR_CMN_OBJTAG from getattrlist is
  // the only value needed, which should be faster to get than the whole statfs
  // struct. Additionally the statfs field f_type does not seem to map to any
  // public enum of file system types. According to man 2 getattrlist it is not
  // a useful value. The f_fstypename field could be used but adds the
  // additional burden of handling strings.
  if (getattrlist(path, &attr_list, &buff, sizeof(buff), 0) != 0) {
    // Record FileSystemType::kUnknown if there is a failure with getattrlist.
    RecordAppFileSystemTypeUsingVolumeTag(VT_NON);
    return;
  }
  DCHECK_GE(sizeof(buff), buff.length);
  RecordAppFileSystemTypeUsingVolumeTag(buff.tag);
}

void Metrics::OnUpgradeRecommended() {
  // By default OnUpgradeRecommended is called multiple times over the course
  // of 7 days, the first being 1 hour after the update has been staged. Record
  // the metric once and ignore all other calls.
  static bool once = []() {
    RecordAppUpgradeCodeSignatureValidationImpl(base::DoNothing());
    return true;
  }();
  DCHECK(once);
}

void Metrics::RecordAppUpgradeCodeSignatureValidation(
    base::OnceClosure closure) {
  RecordAppUpgradeCodeSignatureValidationImpl(std::move(closure));
}

}  // namespace mac_metrics