File: notification_platform_bridge_delegator.cc

package info (click to toggle)
chromium 138.0.7204.157-1
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 6,071,864 kB
  • sloc: cpp: 34,936,859; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,967; 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 (186 lines) | stat: -rw-r--r-- 6,893 bytes parent folder | download | duplicates (3)
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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
// 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 "chrome/browser/notifications/notification_platform_bridge_delegator.h"

#include <algorithm>
#include <utility>
#include <vector>

#include "base/barrier_closure.h"
#include "base/check.h"
#include "base/functional/bind.h"
#include "base/metrics/histogram_functions.h"
#include "build/build_config.h"
#include "build/buildflag.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/notifications/notification_display_service_impl.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/buildflags.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/pref_names.h"
#include "components/prefs/pref_service.h"

#if BUILDFLAG(ENABLE_CHROME_NOTIFICATIONS)
#include "chrome/browser/notifications/notification_platform_bridge_message_center.h"
#endif

#if BUILDFLAG(IS_WIN)
#include "chrome/browser/notifications/notification_platform_bridge_win.h"
#endif

namespace {

// Returns if the current platform has system notifications enabled.
// Platforms behave as follows:
//
//   * Android, Chrome OS
//     Always uses system notifications.
//
//   * Windows before 10 RS4 (incl. Win8 & Win7)
//     Always uses message center.
//
//   * Mac OS X, Linux, Windows 10 RS4+
//     Uses system notifications by default, but can fall back to the message
//     center if features::kSystemNotifications is disabled or initialization
//     fails. Linux additionally checks if prefs::kAllowSystemNotifications is
//     disabled and falls back to the message center if so.
//
// Please try to keep this comment up to date when changing behaviour on one of
// the platforms supported by the browser.
bool SystemNotificationsEnabled(Profile* profile) {
#if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
  return true;
#elif BUILDFLAG(IS_WIN)
  return NotificationPlatformBridgeWin::SystemNotificationEnabled();
#else
#if BUILDFLAG(IS_LINUX)
  if (profile) {
    // Prefs take precedence over flags.
    PrefService* prefs = profile->GetPrefs();
    if (!prefs->GetBoolean(prefs::kAllowSystemNotifications)) {
      return false;
    }
  }
#endif  // BUILDFLAG(IS_LINUX)
  return base::FeatureList::IsEnabled(features::kNativeNotifications) &&
         base::FeatureList::IsEnabled(features::kSystemNotifications);
#endif  // BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
}

NotificationPlatformBridge* GetSystemNotificationPlatformBridge(
    Profile* profile) {
  if (SystemNotificationsEnabled(profile))
    return g_browser_process->notification_platform_bridge();

  // The platform does not support, or has not enabled, system notifications.
  return nullptr;
}

// Returns the NotificationPlatformBridge to use for the message center. May be
// a nullptr for platforms where the message center is not available.
NotificationPlatformBridge* GetMessageCenterBridge() {
#if BUILDFLAG(ENABLE_CHROME_NOTIFICATIONS)
  return NotificationPlatformBridgeMessageCenter::Get();
#else
  return nullptr;
#endif
}

}  // namespace

NotificationPlatformBridgeDelegator::NotificationPlatformBridgeDelegator(
    Profile* profile,
    base::OnceClosure ready_callback)
    : profile_(profile),
      message_center_bridge_(GetMessageCenterBridge()),
      system_bridge_(GetSystemNotificationPlatformBridge(profile_)),
      ready_callback_(std::move(ready_callback)) {
  // Initialize the |system_bridge_| if system notifications are available,
  // otherwise signal that the bridge could not be initialized.
  if (system_bridge_) {
    system_bridge_->SetReadyCallback(
        base::BindOnce(&NotificationPlatformBridgeDelegator::
                           OnSystemNotificationPlatformBridgeReady,
                       weak_factory_.GetWeakPtr()));
  } else {
    OnSystemNotificationPlatformBridgeReady(/*success=*/false);
  }
}

NotificationPlatformBridgeDelegator::~NotificationPlatformBridgeDelegator() =
    default;

void NotificationPlatformBridgeDelegator::Display(
    NotificationHandler::Type notification_type,
    const message_center::Notification& notification,
    std::unique_ptr<NotificationCommon::Metadata> metadata) {
  NotificationPlatformBridge* bridge = GetBridgeForType(notification_type);
  DCHECK(bridge);
  bridge->Display(notification_type, profile_, notification,
                  std::move(metadata));
}

void NotificationPlatformBridgeDelegator::Close(
    NotificationHandler::Type notification_type,
    const std::string& notification_id) {
  NotificationPlatformBridge* bridge = GetBridgeForType(notification_type);
  DCHECK(bridge);
  bridge->Close(profile_, notification_id);
}

void NotificationPlatformBridgeDelegator::GetDisplayed(
    GetDisplayedNotificationsCallback callback) const {
  // TODO(crbug.com/40788519): We currently only query one of the bridges for
  // displayed notifications which may not return TRANSIENT style ones. Ideally
  // there would be only one bridge to query from.
  NotificationPlatformBridge* bridge =
      system_bridge_ ? system_bridge_.get() : message_center_bridge_.get();
  DCHECK(bridge);
  bridge->GetDisplayed(profile_, std::move(callback));
}

void NotificationPlatformBridgeDelegator::GetDisplayedForOrigin(
    const GURL& origin,
    GetDisplayedNotificationsCallback callback) const {
  // TODO(crbug.com/40788519): We currently only query one of the bridges for
  // displayed notifications which may not return TRANSIENT style ones. Ideally
  // there would be only one bridge to query from.
  NotificationPlatformBridge* bridge =
      system_bridge_ ? system_bridge_.get() : message_center_bridge_.get();
  DCHECK(bridge);
  bridge->GetDisplayedForOrigin(profile_, origin, std::move(callback));
}

void NotificationPlatformBridgeDelegator::DisplayServiceShutDown() {
  if (message_center_bridge_)
    message_center_bridge_->DisplayServiceShutDown(profile_);
  if (system_bridge_)
    system_bridge_->DisplayServiceShutDown(profile_);
}

NotificationPlatformBridge*
NotificationPlatformBridgeDelegator::GetBridgeForType(
    NotificationHandler::Type type) {
  // Prefer the system bridge if available and it can handle |type|.
  if (system_bridge_ && NotificationPlatformBridge::CanHandleType(type))
    return system_bridge_;
  return message_center_bridge_;
}

void NotificationPlatformBridgeDelegator::
    OnSystemNotificationPlatformBridgeReady(bool success) {
  if (!success) {
    // Fall back to the message center if initialization failed. Initialization
    // must always succeed on platforms where the message center is unavailable.
    DCHECK(message_center_bridge_);
    system_bridge_ = nullptr;
  }

  base::UmaHistogramBoolean("Notifications.UsingSystemNotificationCenter",
                            system_bridge_ != nullptr);

  if (ready_callback_)
    std::move(ready_callback_).Run();
}