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
content / browser / accessibility / browser_accessibility_state_impl_mac.mm [blame]
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/accessibility/browser_accessibility_state_impl.h"
#import <Cocoa/Cocoa.h>
#include <memory>
#import "base/mac/mac_util.h"
#include "base/metrics/histogram_macros.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_features.h"
#include "ui/gfx/animation/animation.h"
namespace content {
namespace {
void SetUpAccessibilityNotifications() {
// We need to call into gfx::Animation and WebContentsImpl on the UI thread,
// so ensure that we setup the notification on the correct thread.
DCHECK_CURRENTLY_ON(BrowserThread::UI);
// Listen to accessibility display options changing, so that we can update
// the renderer for the prefers reduced motion settings.
//
// BrowserAccessibilityStateImpl is a deliberately leaked singleton, so we
// don't need to record the notification token for later cleanup.
[NSWorkspace.sharedWorkspace.notificationCenter
addObserverForName:
NSWorkspaceAccessibilityDisplayOptionsDidChangeNotification
object:nil
queue:nil
usingBlock:^(NSNotification* notification) {
gfx::Animation::UpdatePrefersReducedMotion();
BrowserAccessibilityStateImpl::GetInstance()
->NotifyWebContentsPreferencesChanged();
}];
if (base::mac::MacOSVersion() >= 14'00'00 &&
base::FeatureList::IsEnabled(
features::kSonomaAccessibilityActivationRefinements)) {
// Set up KVO monitoring of VoiceOver state changes. KVO best practices
// recommend setting the context to the "address of a uniquely named
// static variable within the class". This allows observers to disambiguate
// notifications (where a class and its superclass, say, are observing the
// same property). We'll use the global accessibility object.
[[NSWorkspace sharedWorkspace]
addObserver:NSApp
forKeyPath:@"voiceOverEnabled"
options:(NSKeyValueObservingOptionInitial |
NSKeyValueObservingOptionNew)
context:BrowserAccessibilityStateImpl::GetInstance()];
}
}
} // namespace
class BrowserAccessibilityStateImplMac : public BrowserAccessibilityStateImpl {
public:
BrowserAccessibilityStateImplMac() = default;
~BrowserAccessibilityStateImplMac() override {}
protected:
void InitBackgroundTasks() override;
void UpdateHistogramsOnOtherThread() override;
void UpdateUniqueUserHistograms() override;
};
void BrowserAccessibilityStateImplMac::InitBackgroundTasks() {
BrowserAccessibilityStateImpl::InitBackgroundTasks();
GetUIThreadTaskRunner({})->PostTask(
FROM_HERE, base::BindOnce(&SetUpAccessibilityNotifications));
}
void BrowserAccessibilityStateImplMac::UpdateHistogramsOnOtherThread() {
BrowserAccessibilityStateImpl::UpdateHistogramsOnOtherThread();
// Screen reader metric.
ui::AXMode mode =
BrowserAccessibilityStateImpl::GetInstance()->GetAccessibilityMode();
UMA_HISTOGRAM_BOOLEAN("Accessibility.Mac.ScreenReader",
mode.has_mode(ui::AXMode::kScreenReader));
}
void BrowserAccessibilityStateImplMac::UpdateUniqueUserHistograms() {
BrowserAccessibilityStateImpl::UpdateUniqueUserHistograms();
ui::AXMode mode = GetAccessibilityMode();
UMA_HISTOGRAM_BOOLEAN("Accessibility.Mac.ScreenReader.EveryReport",
mode.has_mode(ui::AXMode::kScreenReader));
}
// static
std::unique_ptr<BrowserAccessibilityStateImpl>
BrowserAccessibilityStateImpl::Create() {
return std::make_unique<BrowserAccessibilityStateImplMac>();
}
} // namespace content