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 187 188 189 190 191 192 193 194
|
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_BADGING_BADGE_MANAGER_H_
#define CHROME_BROWSER_BADGING_BADGE_MANAGER_H_
#include <map>
#include <memory>
#include <optional>
#include <string>
#include <vector>
#include "base/memory/raw_ptr.h"
#include "base/time/time.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/webapps/common/web_app_id.h"
#include "content/public/browser/service_worker_version_base_info.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "third_party/blink/public/mojom/badging/badging.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_ancestor_frame_type.mojom.h"
#include "url/gurl.h"
class Profile;
namespace base {
class Clock;
} // namespace base
namespace content {
class RenderFrameHost;
class RenderProcessHost;
} // namespace content
namespace ukm {
class UkmRecorder;
} // namespace ukm
namespace badging {
class BadgeManagerDelegate;
// Records different types of update badge event.
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum UpdateBadgeType {
// Set badge to a positive integer value.
kSetNumericBadge = 0,
// Set badge without value, display a plain dot.
kSetFlagBadge = 1,
// Clear badge with either navigator.setAppBadge(0)
// or navigator.clearAppBadge().
kClearBadge = 2,
};
// The maximum value of badge contents before saturation occurs.
inline constexpr uint64_t kMaxBadgeContent = 99u;
// We don't show a badge in response to notifications if the
// Badging API has been used recently.
inline constexpr base::TimeDelta kBadgingOverrideLifetime = base::Days(14);
// We record when the Badging API was last used, but rate limit
// our updates to minimize load on the Web App database,
inline constexpr base::TimeDelta kBadgingMinimumUpdateInterval = base::Hours(2);
// Maintains a record of badge contents and dispatches badge changes to a
// delegate.
class BadgeManager : public KeyedService, public blink::mojom::BadgeService {
public:
// The badge being applied to a document URL or service worker scope. If the
// optional is |std::nullopt| then the badge is "flag". Otherwise the badge
// is a non-zero integer.
using BadgeValue = std::optional<uint64_t>;
explicit BadgeManager(Profile* profile);
BadgeManager(const BadgeManager&) = delete;
BadgeManager& operator=(const BadgeManager&) = delete;
~BadgeManager() override;
// Sets the delegate used for setting/clearing badges.
void SetDelegate(std::unique_ptr<BadgeManagerDelegate> delegate);
static void BindFrameReceiverIfAllowed(
content::RenderFrameHost* frame,
mojo::PendingReceiver<blink::mojom::BadgeService> receiver);
// Binds a remote ServiceWorkerGlobalScope to a badge service. After
// receiving a badge update from a ServiceWorkerGlobalScope, the badge
// service must update the badge for each app under `service_worker_scope`.
static void BindServiceWorkerReceiverIfAllowed(
content::RenderProcessHost* service_worker_process_host,
const content::ServiceWorkerVersionBaseInfo& info,
mojo::PendingReceiver<blink::mojom::BadgeService> receiver);
// Gets the badge for |app_id|. This will be std::nullopt if the app is not
// badged.
std::optional<BadgeValue> GetBadgeValue(const webapps::AppId& app_id);
bool HasRecentApiUsage(const webapps::AppId& app_id) const;
void SetBadgeForTesting(const webapps::AppId& app_id,
BadgeValue value,
ukm::UkmRecorder* test_recorder);
void ClearBadgeForTesting(const webapps::AppId& app_id,
ukm::UkmRecorder* test_recorder);
const base::Clock* SetClockForTesting(const base::Clock* clock);
private:
// The BindingContext of a mojo request. Allows mojo calls to be tied back
// to the execution context they belong to without trusting the renderer for
// that information. This is an abstract base class that different types of
// execution contexts derive.
class BindingContext {
public:
virtual ~BindingContext() = default;
// Gets the list of app IDs to badge, based on the state of this
// BindingContext. Returns an empty list when no apps exist for this
// BindingContext.
virtual std::vector<std::tuple<webapps::AppId, GURL>>
GetAppIdsAndUrlsForBadging() const = 0;
};
// The BindingContext for Window execution contexts.
class FrameBindingContext final : public BindingContext {
public:
FrameBindingContext(int process_id, int frame_id)
: process_id_(process_id), frame_id_(frame_id) {}
~FrameBindingContext() override = default;
// Returns the AppId that matches the frame's URL. Returns either 0 or 1
// AppIds.
std::vector<std::tuple<webapps::AppId, GURL>> GetAppIdsAndUrlsForBadging()
const override;
private:
int process_id_;
int frame_id_;
};
// The BindingContext for ServiceWorkerGlobalScope execution contexts.
class ServiceWorkerBindingContext final : public BindingContext {
public:
ServiceWorkerBindingContext(int process_id, const GURL& scope)
: process_id_(process_id), scope_(scope) {}
~ServiceWorkerBindingContext() override = default;
// Returns the list of AppIds within the service worker's scope. Returns
// either 0, 1 or more AppIds.
std::vector<std::tuple<webapps::AppId, GURL>> GetAppIdsAndUrlsForBadging()
const override;
private:
int process_id_;
GURL scope_;
};
// Updates the badge for |app_id| to be |value|, if it is not std::nullopt.
// If value is |std::nullopt| then this clears the badge.
void UpdateBadge(const webapps::AppId& app_id,
std::optional<BadgeValue> value);
// blink::mojom::BadgeService:
// Note: These are private to stop them being called outside of mojo as they
// require a mojo binding context.
void SetBadge(blink::mojom::BadgeValuePtr value) override;
void ClearBadge() override;
const raw_ptr<Profile, DanglingUntriaged> profile_;
raw_ptr<const base::Clock> clock_;
// All the mojo receivers for the BadgeManager. Keeps track of the
// render_frame the binding is associated with, so as to not have to rely
// on the renderer passing it in.
mojo::ReceiverSet<blink::mojom::BadgeService, std::unique_ptr<BindingContext>>
receivers_;
// Delegate which handles actual setting and clearing of the badge.
// Note: This is currently set on Windows, MacOS and Chrome OS.
std::unique_ptr<BadgeManagerDelegate> delegate_;
// Maps app_id to badge contents.
std::map<webapps::AppId, BadgeValue> badged_apps_;
};
// Determines the text to put on the badge based on some badge_content.
std::string GetBadgeString(BadgeManager::BadgeValue badge_content);
} // namespace badging
#endif // CHROME_BROWSER_BADGING_BADGE_MANAGER_H_
|