X Tutup
Skip to content

Commit c5a41de

Browse files
authored
fix: enable navigator.setAppBadge/clearAppBadge (electron#27067)
1 parent 8b74361 commit c5a41de

19 files changed

+481
-41
lines changed

docs/api/app.md

100644100755
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1174,9 +1174,9 @@ For `infoType` equal to `basic`:
11741174

11751175
Using `basic` should be preferred if only basic information like `vendorId` or `driverId` is needed.
11761176

1177-
### `app.setBadgeCount(count)` _Linux_ _macOS_
1177+
### `app.setBadgeCount([count])` _Linux_ _macOS_
11781178

1179-
* `count` Integer
1179+
* `count` Integer (optional) - If a value is provided, set the badge to the provided value otherwise, on macOS, display a plain white dot (e.g. unknown number of notifications). On Linux, if a value is not provided the badge will not display.
11801180

11811181
Returns `Boolean` - Whether the call succeeded.
11821182

electron_strings.grdp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,5 +83,18 @@
8383
<message name="IDS_DOWNLOAD_MORE_ACTIONS"
8484
desc="Tooltip of a button on the downloads page that shows a menu with actions like 'Open downloads folder' or 'Clear all'">
8585
More actions
86-
</message>
86+
</message>
87+
<!-- Badging -->
88+
<message name="IDS_SATURATED_BADGE_CONTENT" desc="The content to display when the application's badge is too large to display to indicate that the badge is more than a given maximum. This string should be as short as possible, preferably only one character beyond the content">
89+
<ph name="MAXIMUM_VALUE">$1<ex>99</ex></ph>+
90+
</message>
91+
<message name="IDS_BADGE_UNREAD_NOTIFICATIONS_SATURATED" desc="The accessibility text which will be read by a screen reader when the notification count is too large to display (e.g. greater than 99).">
92+
{MAX_UNREAD_NOTIFICATIONS, plural, =1 {More than 1 unread notification} other {More than # unread notifications}}
93+
</message>
94+
<message name="IDS_BADGE_UNREAD_NOTIFICATIONS_UNSPECIFIED" desc="The accessibility text which will be read by a screen reader when there are some unspecified number of notifications, or user attention is required">
95+
Unread Notifications
96+
</message>
97+
<message name="IDS_BADGE_UNREAD_NOTIFICATIONS" desc="The accessibility text which will be read by a screen reader when there are notifcatications">
98+
{UNREAD_NOTIFICATIONS, plural, =1 {1 Unread Notification} other {# Unread Notifications}}
99+
</message>
87100
</grit-part>

filenames.gni

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,10 @@ filenames = {
328328
"shell/browser/api/ui_event.h",
329329
"shell/browser/auto_updater.cc",
330330
"shell/browser/auto_updater.h",
331+
"shell/browser/badging/badge_manager.cc",
332+
"shell/browser/badging/badge_manager.h",
333+
"shell/browser/badging/badge_manager_factory.cc",
334+
"shell/browser/badging/badge_manager_factory.h",
331335
"shell/browser/browser.cc",
332336
"shell/browser/browser.h",
333337
"shell/browser/browser_observer.h",
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
// Copyright 2018 The Chromium Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#include "shell/browser/badging/badge_manager.h"
6+
7+
#include <tuple>
8+
#include <utility>
9+
10+
#include "base/i18n/number_formatting.h"
11+
#include "base/strings/utf_string_conversions.h"
12+
#include "build/build_config.h"
13+
#include "content/public/browser/browser_task_traits.h"
14+
#include "content/public/browser/browser_thread.h"
15+
#include "content/public/browser/render_frame_host.h"
16+
#include "content/public/browser/render_process_host.h"
17+
#include "content/public/browser/web_contents.h"
18+
#include "shell/browser/badging/badge_manager_factory.h"
19+
#include "shell/browser/browser.h"
20+
#include "ui/base/l10n/l10n_util.h"
21+
#include "ui/strings/grit/ui_strings.h"
22+
23+
namespace badging {
24+
25+
BadgeManager::BadgeManager() = default;
26+
BadgeManager::~BadgeManager() = default;
27+
28+
// static
29+
void BadgeManager::BindFrameReceiver(
30+
content::RenderFrameHost* frame,
31+
mojo::PendingReceiver<blink::mojom::BadgeService> receiver) {
32+
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
33+
34+
auto* browser_context =
35+
content::WebContents::FromRenderFrameHost(frame)->GetBrowserContext();
36+
37+
auto* badge_manager =
38+
badging::BadgeManagerFactory::GetInstance()->GetForBrowserContext(
39+
browser_context);
40+
if (!badge_manager)
41+
return;
42+
43+
auto context = std::make_unique<FrameBindingContext>(
44+
frame->GetProcess()->GetID(), frame->GetRoutingID());
45+
46+
badge_manager->receivers_.Add(badge_manager, std::move(receiver),
47+
std::move(context));
48+
}
49+
50+
std::string BadgeManager::GetBadgeString(base::Optional<int> badge_content) {
51+
if (!badge_content)
52+
return "";
53+
54+
if (badge_content > kMaxBadgeContent) {
55+
return base::UTF16ToUTF8(l10n_util::GetStringFUTF16(
56+
IDS_SATURATED_BADGE_CONTENT, base::FormatNumber(kMaxBadgeContent)));
57+
}
58+
59+
return base::UTF16ToUTF8(base::FormatNumber(badge_content.value()));
60+
}
61+
62+
void BadgeManager::SetBadge(blink::mojom::BadgeValuePtr mojo_value) {
63+
if (mojo_value->is_number() && mojo_value->get_number() == 0) {
64+
mojo::ReportBadMessage(
65+
"|value| should not be zero when it is |number| (ClearBadge should be "
66+
"called instead)!");
67+
return;
68+
}
69+
70+
base::Optional<int> value =
71+
mojo_value->is_flag() ? base::nullopt
72+
: base::make_optional(mojo_value->get_number());
73+
74+
electron::Browser::Get()->SetBadgeCount(value);
75+
}
76+
77+
void BadgeManager::ClearBadge() {
78+
electron::Browser::Get()->SetBadgeCount(0);
79+
}
80+
81+
} // namespace badging
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
// Copyright 2018 The Chromium Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#ifndef SHELL_BROWSER_BADGING_BADGE_MANAGER_H_
6+
#define SHELL_BROWSER_BADGING_BADGE_MANAGER_H_
7+
8+
#include <map>
9+
#include <memory>
10+
#include <string>
11+
#include <vector>
12+
13+
#include "base/macros.h"
14+
#include "base/optional.h"
15+
#include "components/keyed_service/core/keyed_service.h"
16+
#include "mojo/public/cpp/bindings/receiver_set.h"
17+
#include "third_party/blink/public/mojom/badging/badging.mojom.h"
18+
#include "url/gurl.h"
19+
20+
namespace content {
21+
class RenderFrameHost;
22+
class RenderProcessHost;
23+
} // namespace content
24+
25+
namespace badging {
26+
27+
// The maximum value of badge contents before saturation occurs.
28+
constexpr int kMaxBadgeContent = 99;
29+
30+
// Maintains a record of badge contents and dispatches badge changes to a
31+
// delegate.
32+
class BadgeManager : public KeyedService, public blink::mojom::BadgeService {
33+
public:
34+
BadgeManager();
35+
~BadgeManager() override;
36+
37+
static void BindFrameReceiver(
38+
content::RenderFrameHost* frame,
39+
mojo::PendingReceiver<blink::mojom::BadgeService> receiver);
40+
41+
// Determines the text to put on the badge based on some badge_content.
42+
static std::string GetBadgeString(base::Optional<int> badge_content);
43+
44+
private:
45+
// The BindingContext of a mojo request. Allows mojo calls to be tied back
46+
// to the execution context they belong to without trusting the renderer for
47+
// that information. This is an abstract base class that different types of
48+
// execution contexts derive.
49+
class BindingContext {
50+
public:
51+
virtual ~BindingContext() = default;
52+
};
53+
54+
// The BindingContext for Window execution contexts.
55+
class FrameBindingContext final : public BindingContext {
56+
public:
57+
FrameBindingContext(int process_id, int frame_id)
58+
: process_id_(process_id), frame_id_(frame_id) {}
59+
~FrameBindingContext() override = default;
60+
61+
int GetProcessId() { return process_id_; }
62+
int GetFrameId() { return frame_id_; }
63+
64+
private:
65+
int process_id_;
66+
int frame_id_;
67+
};
68+
69+
// blink::mojom::BadgeService:
70+
// Note: These are private to stop them being called outside of mojo as they
71+
// require a mojo binding context.
72+
void SetBadge(blink::mojom::BadgeValuePtr value) override;
73+
void ClearBadge() override;
74+
75+
// All the mojo receivers for the BadgeManager. Keeps track of the
76+
// render_frame the binding is associated with, so as to not have to rely
77+
// on the renderer passing it in.
78+
mojo::ReceiverSet<blink::mojom::BadgeService, std::unique_ptr<BindingContext>>
79+
receivers_;
80+
81+
// Delegate which handles actual setting and clearing of the badge.
82+
// Note: This is currently only set on Windows and MacOS.
83+
// std::unique_ptr<BadgeManagerDelegate> delegate_;
84+
85+
DISALLOW_COPY_AND_ASSIGN(BadgeManager);
86+
};
87+
88+
} // namespace badging
89+
90+
#endif // SHELL_BROWSER_BADGING_BADGE_MANAGER_H_
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Copyright 2018 The Chromium Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#include "shell/browser/badging/badge_manager_factory.h"
6+
7+
#include <memory>
8+
9+
#include "base/bind.h"
10+
#include "base/memory/ptr_util.h"
11+
#include "base/memory/singleton.h"
12+
#include "components/keyed_service/content/browser_context_dependency_manager.h"
13+
#include "shell/browser/badging/badge_manager.h"
14+
15+
namespace badging {
16+
17+
// static
18+
BadgeManager* BadgeManagerFactory::GetForBrowserContext(
19+
content::BrowserContext* context) {
20+
return static_cast<badging::BadgeManager*>(
21+
GetInstance()->GetServiceForBrowserContext(context, true));
22+
}
23+
24+
// static
25+
BadgeManagerFactory* BadgeManagerFactory::GetInstance() {
26+
return base::Singleton<BadgeManagerFactory>::get();
27+
}
28+
29+
BadgeManagerFactory::BadgeManagerFactory()
30+
: BrowserContextKeyedServiceFactory(
31+
"BadgeManager",
32+
BrowserContextDependencyManager::GetInstance()) {}
33+
34+
BadgeManagerFactory::~BadgeManagerFactory() {}
35+
36+
KeyedService* BadgeManagerFactory::BuildServiceInstanceFor(
37+
content::BrowserContext* context) const {
38+
return new BadgeManager();
39+
}
40+
41+
} // namespace badging
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Copyright 2018 The Chromium Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#ifndef SHELL_BROWSER_BADGING_BADGE_MANAGER_FACTORY_H_
6+
#define SHELL_BROWSER_BADGING_BADGE_MANAGER_FACTORY_H_
7+
8+
#include "base/macros.h"
9+
#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
10+
11+
namespace base {
12+
template <typename T>
13+
struct DefaultSingletonTraits;
14+
}
15+
16+
namespace badging {
17+
18+
class BadgeManager;
19+
20+
// Singleton that provides access to context specific BadgeManagers.
21+
class BadgeManagerFactory : public BrowserContextKeyedServiceFactory {
22+
public:
23+
// Gets the BadgeManager for the specified context
24+
static BadgeManager* GetForBrowserContext(content::BrowserContext* context);
25+
26+
// Returns the BadgeManagerFactory singleton.
27+
static BadgeManagerFactory* GetInstance();
28+
29+
private:
30+
friend struct base::DefaultSingletonTraits<BadgeManagerFactory>;
31+
32+
BadgeManagerFactory();
33+
~BadgeManagerFactory() override;
34+
35+
// BrowserContextKeyedServiceFactory
36+
KeyedService* BuildServiceInstanceFor(
37+
content::BrowserContext* context) const override;
38+
39+
DISALLOW_COPY_AND_ASSIGN(BadgeManagerFactory);
40+
};
41+
42+
} // namespace badging
43+
44+
#endif // SHELL_BROWSER_BADGING_BADGE_MANAGER_FACTORY_H_

shell/browser/browser.cc

100644100755
File mode changed.

shell/browser/browser.h

100644100755
Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#if defined(OS_WIN)
2424
#include <windows.h>
2525
#include "base/files/file_path.h"
26+
#include "shell/browser/ui/win/taskbar_host.h"
2627
#endif
2728

2829
#if defined(OS_MAC)
@@ -107,7 +108,7 @@ class Browser : public WindowListObserver {
107108
#endif
108109

109110
// Set/Get the badge count.
110-
bool SetBadgeCount(int count);
111+
bool SetBadgeCount(base::Optional<int> count);
111112
int GetBadgeCount();
112113

113114
#if defined(OS_WIN)
@@ -364,6 +365,15 @@ class Browser : public WindowListObserver {
364365
base::DictionaryValue about_panel_options_;
365366
#endif
366367

368+
#if defined(OS_WIN)
369+
void UpdateBadgeContents(HWND hwnd,
370+
const base::Optional<std::string>& badge_content,
371+
const std::string& badge_alt_string);
372+
373+
// In charge of running taskbar related APIs.
374+
TaskbarHost taskbar_host_;
375+
#endif
376+
367377
DISALLOW_COPY_AND_ASSIGN(Browser);
368378
};
369379

shell/browser/browser_linux.cc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -130,10 +130,10 @@ base::string16 Browser::GetApplicationNameForProtocol(const GURL& url) {
130130
return base::ASCIIToUTF16(GetXdgAppOutput(argv).value_or(std::string()));
131131
}
132132

133-
bool Browser::SetBadgeCount(int count) {
134-
if (IsUnityRunning()) {
135-
unity::SetDownloadCount(count);
136-
badge_count_ = count;
133+
bool Browser::SetBadgeCount(base::Optional<int> count) {
134+
if (IsUnityRunning() && count.has_value()) {
135+
unity::SetDownloadCount(count.value());
136+
badge_count_ = count.value();
137137
return true;
138138
} else {
139139
return false;

0 commit comments

Comments
 (0)
X Tutup