Commit bb362ce7 authored by Louise Brett's avatar Louise Brett Committed by Chromium LUCI CQ

Add attention badging for PWAs on Chrome OS

This hooks up the existing web badging API to the UI so that a PWA
will show an attention badge if the PWA has called the web badging
API.

- When the flag "enable-desktop-pwas-attention-badging-cros" is set to
  "notifications-only", a badge will only show when a notification is
  showing.
- When the flag is set to "api-only" a badge will only show if the web
  badging api has a badge set.
- When the flag is set to "api-and-notifications" a badge will show
  either if a notification is showing or if the web badging api has a
  badge set. This is the default behaviour.

Bug: 1157273
Change-Id: Ic0275e5e2d023f13554ed6ca001665b69f49f58e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2589055
Commit-Queue: Louise Brett <loubrett@google.com>
Reviewed-by: default avatarNancy Wang <nancylingwang@chromium.org>
Reviewed-by: default avatarGlen Robertson <glenrob@chromium.org>
Reviewed-by: default avatarMatt Giuca <mgiuca@chromium.org>
Cr-Commit-Position: refs/heads/master@{#837903}
parent a6d5c25d
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "base/bind.h" #include "base/bind.h"
#include "base/callback.h" #include "base/callback.h"
#include "base/callback_helpers.h" #include "base/callback_helpers.h"
#include "base/memory/weak_ptr.h"
#include "base/metrics/histogram_macros.h" #include "base/metrics/histogram_macros.h"
#include "base/optional.h" #include "base/optional.h"
#include "base/stl_util.h" #include "base/stl_util.h"
...@@ -21,6 +22,7 @@ ...@@ -21,6 +22,7 @@
#include "chrome/browser/apps/app_service/app_service_metrics.h" #include "chrome/browser/apps/app_service/app_service_metrics.h"
#include "chrome/browser/apps/app_service/launch_utils.h" #include "chrome/browser/apps/app_service/launch_utils.h"
#include "chrome/browser/apps/app_service/menu_util.h" #include "chrome/browser/apps/app_service/menu_util.h"
#include "chrome/browser/badging/badge_manager_factory.h"
#include "chrome/browser/chromeos/arc/arc_util.h" #include "chrome/browser/chromeos/arc/arc_util.h"
#include "chrome/browser/chromeos/arc/arc_web_contents_data.h" #include "chrome/browser/chromeos/arc/arc_web_contents_data.h"
#include "chrome/browser/chromeos/crostini/crostini_util.h" #include "chrome/browser/chromeos/crostini/crostini_util.h"
...@@ -44,6 +46,7 @@ ...@@ -44,6 +46,7 @@
#include "chrome/browser/web_applications/web_app_registrar.h" #include "chrome/browser/web_applications/web_app_registrar.h"
#include "chrome/browser/web_applications/web_app_sync_bridge.h" #include "chrome/browser/web_applications/web_app_sync_bridge.h"
#include "chrome/common/chrome_features.h" #include "chrome/common/chrome_features.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/grit/generated_resources.h" #include "chrome/grit/generated_resources.h"
#include "components/arc/arc_service_manager.h" #include "components/arc/arc_service_manager.h"
#include "components/content_settings/core/common/content_settings.h" #include "components/content_settings/core/common/content_settings.h"
...@@ -58,8 +61,42 @@ ...@@ -58,8 +61,42 @@
#include "ui/message_center/public/cpp/notification.h" #include "ui/message_center/public/cpp/notification.h"
#include "url/origin.h" #include "url/origin.h"
namespace {
std::string GetDesktopPWAsAttentionBadgingFlag() {
const base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
if (cmdline->HasSwitch(switches::kDesktopPWAsAttentionBadgingCrOS)) {
return cmdline->GetSwitchValueASCII(
switches::kDesktopPWAsAttentionBadgingCrOS);
}
return "";
}
} // namespace
namespace apps { namespace apps {
WebAppsChromeOs::BadgeManagerDelegate::BadgeManagerDelegate(
const base::WeakPtr<WebAppsChromeOs>& web_apps_chrome_os)
: badging::BadgeManagerDelegate(web_apps_chrome_os->profile(),
web_apps_chrome_os->badge_manager_),
web_apps_chrome_os_(web_apps_chrome_os) {}
WebAppsChromeOs::BadgeManagerDelegate::~BadgeManagerDelegate() = default;
void WebAppsChromeOs::BadgeManagerDelegate::OnAppBadgeUpdated(
const web_app::AppId& app_id) {
if (!web_apps_chrome_os_) {
return;
}
apps::mojom::AppPtr app =
web_apps_chrome_os_->app_notifications_.GetAppWithHasBadgeStatus(
apps::mojom::AppType::kWeb, app_id);
app->has_badge = web_apps_chrome_os_->ShouldShowBadge(app_id, app->has_badge);
web_apps_chrome_os_->Publish(std::move(app),
web_apps_chrome_os_->subscribers());
}
WebAppsChromeOs::WebAppsChromeOs( WebAppsChromeOs::WebAppsChromeOs(
const mojo::Remote<apps::mojom::AppService>& app_service, const mojo::Remote<apps::mojom::AppService>& app_service,
Profile* profile, Profile* profile,
...@@ -67,6 +104,13 @@ WebAppsChromeOs::WebAppsChromeOs( ...@@ -67,6 +104,13 @@ WebAppsChromeOs::WebAppsChromeOs(
: WebAppsBase(app_service, profile), instance_registry_(instance_registry) { : WebAppsBase(app_service, profile), instance_registry_(instance_registry) {
DCHECK(instance_registry_); DCHECK(instance_registry_);
Initialize(); Initialize();
badge_manager_ = badging::BadgeManagerFactory::GetForProfile(profile);
// badge_manager_ is nullptr in guest and incognito profiles.
if (badge_manager_) {
badge_manager_->SetDelegate(
std::make_unique<apps::WebAppsChromeOs::BadgeManagerDelegate>(
weak_ptr_factory_.GetWeakPtr()));
}
} }
WebAppsChromeOs::~WebAppsChromeOs() { WebAppsChromeOs::~WebAppsChromeOs() {
...@@ -318,9 +362,10 @@ void WebAppsChromeOs::OnNotificationClosed(const std::string& notification_id) { ...@@ -318,9 +362,10 @@ void WebAppsChromeOs::OnNotificationClosed(const std::string& notification_id) {
app_notifications_.RemoveNotification(notification_id); app_notifications_.RemoveNotification(notification_id);
for (const auto& app_id : app_ids) { for (const auto& app_id : app_ids) {
Publish(app_notifications_.GetAppWithHasBadgeStatus( apps::mojom::AppPtr app = app_notifications_.GetAppWithHasBadgeStatus(
apps::mojom::AppType::kWeb, app_id), apps::mojom::AppType::kWeb, app_id);
subscribers()); app->has_badge = ShouldShowBadge(app_id, app->has_badge);
Publish(std::move(app), subscribers());
} }
} }
...@@ -337,9 +382,10 @@ bool WebAppsChromeOs::MaybeAddNotification(const std::string& app_id, ...@@ -337,9 +382,10 @@ bool WebAppsChromeOs::MaybeAddNotification(const std::string& app_id,
} }
app_notifications_.AddNotification(app_id, notification_id); app_notifications_.AddNotification(app_id, notification_id);
Publish(app_notifications_.GetAppWithHasBadgeStatus( apps::mojom::AppPtr app = app_notifications_.GetAppWithHasBadgeStatus(
apps::mojom::AppType::kWeb, app_id), apps::mojom::AppType::kWeb, app_id);
subscribers()); app->has_badge = ShouldShowBadge(app_id, app->has_badge);
Publish(std::move(app), subscribers());
return true; return true;
} }
...@@ -386,9 +432,11 @@ apps::mojom::AppPtr WebAppsChromeOs::Convert(const web_app::WebApp* web_app, ...@@ -386,9 +432,11 @@ apps::mojom::AppPtr WebAppsChromeOs::Convert(const web_app::WebApp* web_app,
app->icon_key = icon_key_factory().MakeIconKey( app->icon_key = icon_key_factory().MakeIconKey(
GetIconEffects(web_app, paused, is_disabled)); GetIconEffects(web_app, paused, is_disabled));
app->has_badge = app_notifications_.HasNotification(web_app->app_id()) apps::mojom::OptionalBool has_notification =
? apps::mojom::OptionalBool::kTrue app_notifications_.HasNotification(web_app->app_id())
: apps::mojom::OptionalBool::kFalse; ? apps::mojom::OptionalBool::kTrue
: apps::mojom::OptionalBool::kFalse;
app->has_badge = ShouldShowBadge(web_app->app_id(), has_notification);
app->paused = paused ? apps::mojom::OptionalBool::kTrue app->paused = paused ? apps::mojom::OptionalBool::kTrue
: apps::mojom::OptionalBool::kFalse; : apps::mojom::OptionalBool::kFalse;
return app; return app;
...@@ -477,4 +525,26 @@ bool WebAppsChromeOs::Accepts(const std::string& app_id) { ...@@ -477,4 +525,26 @@ bool WebAppsChromeOs::Accepts(const std::string& app_id) {
return app_id != crostini::kCrostiniTerminalSystemAppId; return app_id != crostini::kCrostiniTerminalSystemAppId;
} }
apps::mojom::OptionalBool WebAppsChromeOs::ShouldShowBadge(
const std::string& app_id,
apps::mojom::OptionalBool has_notification) {
std::string flag = GetDesktopPWAsAttentionBadgingFlag();
if (flag == switches::kDesktopPWAsAttentionBadgingCrOSApiOnly) {
// Show a badge based only on the Web Badging API.
return badge_manager_ && badge_manager_->GetBadgeValue(app_id).has_value()
? apps::mojom::OptionalBool::kTrue
: apps::mojom::OptionalBool::kFalse;
} else if (flag ==
switches::kDesktopPWAsAttentionBadgingCrOSNotificationsOnly) {
// Show a badge only if a notification is showing.
return has_notification;
} else {
// When the flag is not set or set to "api-and-notifications" we show a
// badge if either a notification is showing or the Web Badging API has a
// badge set.
return badge_manager_ && badge_manager_->GetBadgeValue(app_id).has_value()
? apps::mojom::OptionalBool::kTrue
: has_notification;
}
}
} // namespace apps } // namespace apps
...@@ -7,11 +7,14 @@ ...@@ -7,11 +7,14 @@
#include <string> #include <string>
#include "base/memory/weak_ptr.h"
#include "base/scoped_observer.h" #include "base/scoped_observer.h"
#include "chrome/browser/apps/app_service/app_notifications.h" #include "chrome/browser/apps/app_service/app_notifications.h"
#include "chrome/browser/apps/app_service/icon_key_util.h" #include "chrome/browser/apps/app_service/icon_key_util.h"
#include "chrome/browser/apps/app_service/paused_apps.h" #include "chrome/browser/apps/app_service/paused_apps.h"
#include "chrome/browser/apps/app_service/web_apps_base.h" #include "chrome/browser/apps/app_service/web_apps_base.h"
#include "chrome/browser/badging/badge_manager.h"
#include "chrome/browser/badging/badge_manager_delegate.h"
#include "chrome/browser/notifications/notification_common.h" #include "chrome/browser/notifications/notification_common.h"
#include "chrome/browser/notifications/notification_display_service.h" #include "chrome/browser/notifications/notification_display_service.h"
#include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h" #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
...@@ -45,7 +48,24 @@ class WebAppsChromeOs : public WebAppsBase, ...@@ -45,7 +48,24 @@ class WebAppsChromeOs : public WebAppsBase,
void ObserveArc(); void ObserveArc();
base::WeakPtr<WebAppsChromeOs> GetWeakPtr() {
return weak_ptr_factory_.GetWeakPtr();
}
private: private:
class BadgeManagerDelegate : public badging::BadgeManagerDelegate {
public:
explicit BadgeManagerDelegate(
const base::WeakPtr<WebAppsChromeOs>& web_apps_chrome_os_);
~BadgeManagerDelegate() override;
void OnAppBadgeUpdated(const web_app::AppId& app_id) override;
private:
base::WeakPtr<WebAppsChromeOs> web_apps_chrome_os_;
};
void Initialize(); void Initialize();
// apps::mojom::Publisher overrides. // apps::mojom::Publisher overrides.
...@@ -122,6 +142,11 @@ class WebAppsChromeOs : public WebAppsBase, ...@@ -122,6 +142,11 @@ class WebAppsChromeOs : public WebAppsBase,
bool Accepts(const std::string& app_id) override; bool Accepts(const std::string& app_id) override;
// Returns whether the app should show a badge.
apps::mojom::OptionalBool ShouldShowBadge(
const std::string& app_id,
apps::mojom::OptionalBool has_notification_indicator);
apps::InstanceRegistry* instance_registry_; apps::InstanceRegistry* instance_registry_;
PausedApps paused_apps_; PausedApps paused_apps_;
...@@ -133,6 +158,10 @@ class WebAppsChromeOs : public WebAppsBase, ...@@ -133,6 +158,10 @@ class WebAppsChromeOs : public WebAppsBase,
notification_display_service_{this}; notification_display_service_{this};
AppNotifications app_notifications_; AppNotifications app_notifications_;
badging::BadgeManager* badge_manager_ = nullptr;
base::WeakPtrFactory<WebAppsChromeOs> weak_ptr_factory_{this};
}; };
} // namespace apps } // namespace apps
......
...@@ -37,6 +37,8 @@ ...@@ -37,6 +37,8 @@
namespace badging { namespace badging {
BadgeManager::BadgeManager(Profile* profile) { BadgeManager::BadgeManager(Profile* profile) {
// The delegate is also set for Chrome OS but is set from the constructor of
// web_apps_chromeos.cc.
#if defined(OS_MAC) #if defined(OS_MAC)
SetDelegate(std::make_unique<BadgeManagerDelegateMac>(profile, this)); SetDelegate(std::make_unique<BadgeManagerDelegateMac>(profile, this));
#elif defined(OS_WIN) #elif defined(OS_WIN)
......
...@@ -149,7 +149,7 @@ class BadgeManager : public KeyedService, public blink::mojom::BadgeService { ...@@ -149,7 +149,7 @@ class BadgeManager : public KeyedService, public blink::mojom::BadgeService {
receivers_; receivers_;
// Delegate which handles actual setting and clearing of the badge. // Delegate which handles actual setting and clearing of the badge.
// Note: This is currently only set on Windows and MacOS. // Note: This is currently set on Windows, MacOS and Chrome OS.
std::unique_ptr<BadgeManagerDelegate> delegate_; std::unique_ptr<BadgeManagerDelegate> delegate_;
// Maps app_id to badge contents. // Maps app_id to badge contents.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment