Commit 1b775321 authored by Xiqi Ruan's avatar Xiqi Ruan Committed by Commit Bot

cros: Per-App time limit change will direct to FL app

If Family Link is not installed, open Play store instead.

Bug: 1056458
Change-Id: I31e3356fbe9efba93fd75e9f786d9b84ecc87655
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2135383
Commit-Queue: Xiqi Ruan <xiqiruan@chromium.org>
Reviewed-by: default avatarDominick Ng <dominickn@chromium.org>
Reviewed-by: default avatarAga Wronska <agawronska@chromium.org>
Reviewed-by: default avatarJames Cook <jamescook@chromium.org>
Cr-Commit-Position: refs/heads/master@{#762011}
parent 2adff7cc
...@@ -16,6 +16,14 @@ ...@@ -16,6 +16,14 @@
namespace chromeos { namespace chromeos {
// static
const char ChildUserService::kFamilyLinkHelperAppPackageName[] =
"com.google.android.apps.kids.familylinkhelper";
// static
const char ChildUserService::kFamilyLinkHelperAppPlayStoreURL[] =
"https://play.google.com/store/apps/"
"details?id=com.google.android.apps.kids.familylinkhelper";
ChildUserService::TestApi::TestApi(ChildUserService* service) ChildUserService::TestApi::TestApi(ChildUserService* service)
: service_(service) {} : service_(service) {}
......
...@@ -53,6 +53,11 @@ class ChildUserService : public KeyedService, ...@@ -53,6 +53,11 @@ class ChildUserService : public KeyedService,
ChildUserService* const service_; ChildUserService* const service_;
}; };
// Family Link helper(for child and teens) is an app available to supervised
// users and the companion app of Family Link app(for parents).
static const char kFamilyLinkHelperAppPackageName[];
static const char kFamilyLinkHelperAppPlayStoreURL[];
explicit ChildUserService(content::BrowserContext* context); explicit ChildUserService(content::BrowserContext* context);
ChildUserService(const ChildUserService&) = delete; ChildUserService(const ChildUserService&) = delete;
ChildUserService& operator=(const ChildUserService&) = delete; ChildUserService& operator=(const ChildUserService&) = delete;
......
...@@ -98,6 +98,12 @@ void AppServiceWrapper::ResumeApp(const AppId& app_id) { ...@@ -98,6 +98,12 @@ void AppServiceWrapper::ResumeApp(const AppId& app_id) {
GetAppProxy()->UnpauseApps(apps); GetAppProxy()->UnpauseApps(apps);
} }
void AppServiceWrapper::LaunchApp(const std::string& app_service_id) {
GetAppProxy()->Launch(app_service_id, ui::EventFlags::EF_NONE,
apps::mojom::LaunchSource::kFromParentalControls,
display::kDefaultDisplayId);
}
std::vector<AppId> AppServiceWrapper::GetInstalledApps() const { std::vector<AppId> AppServiceWrapper::GetInstalledApps() const {
std::vector<AppId> installed_apps; std::vector<AppId> installed_apps;
GetAppCache().ForEachApp([&installed_apps](const apps::AppUpdate& update) { GetAppCache().ForEachApp([&installed_apps](const apps::AppUpdate& update) {
...@@ -157,6 +163,10 @@ std::string AppServiceWrapper::GetAppServiceId(const AppId& app_id) const { ...@@ -157,6 +163,10 @@ std::string AppServiceWrapper::GetAppServiceId(const AppId& app_id) const {
return AppServiceIdFromAppId(app_id, profile_); return AppServiceIdFromAppId(app_id, profile_);
} }
bool AppServiceWrapper::IsAppInstalled(const std::string& app_id) {
return GetAppCache().GetAppType(app_id) != apps::mojom::AppType::kUnknown;
}
AppId AppServiceWrapper::AppIdFromAppServiceId( AppId AppServiceWrapper::AppIdFromAppServiceId(
const std::string& app_service_id, const std::string& app_service_id,
apps::mojom::AppType app_type) const { apps::mojom::AppType app_type) const {
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#ifndef CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_TIME_LIMITS_APP_SERVICE_WRAPPER_H_ #ifndef CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_TIME_LIMITS_APP_SERVICE_WRAPPER_H_
#define CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_TIME_LIMITS_APP_SERVICE_WRAPPER_H_ #define CHROME_BROWSER_CHROMEOS_CHILD_ACCOUNTS_TIME_LIMITS_APP_SERVICE_WRAPPER_H_
#include <string>
#include <vector> #include <vector>
#include "base/callback_forward.h" #include "base/callback_forward.h"
...@@ -105,6 +106,10 @@ class AppServiceWrapper : public apps::AppRegistryCache::Observer, ...@@ -105,6 +106,10 @@ class AppServiceWrapper : public apps::AppRegistryCache::Observer,
// will be removed from the icon. // will be removed from the icon.
void ResumeApp(const AppId& app_id); void ResumeApp(const AppId& app_id);
// Launches app identified by |app_service_id| with no event flags explicitly
// and default display id.
void LaunchApp(const std::string& app_service_id);
// Returns installed apps that are relevant for Per-App Time Limits feature. // Returns installed apps that are relevant for Per-App Time Limits feature.
// Installed apps of unsupported types will not be included. // Installed apps of unsupported types will not be included.
std::vector<AppId> GetInstalledApps() const; std::vector<AppId> GetInstalledApps() const;
...@@ -125,6 +130,9 @@ class AppServiceWrapper : public apps::AppRegistryCache::Observer, ...@@ -125,6 +130,9 @@ class AppServiceWrapper : public apps::AppRegistryCache::Observer,
// It does not make sense to call it for other apps. // It does not make sense to call it for other apps.
std::string GetAppServiceId(const AppId& app_id) const; std::string GetAppServiceId(const AppId& app_id) const;
// Return true if the App with |app_service_id| is installed.
bool IsAppInstalled(const std::string& app_service_id);
// Returns AppId from |app_service_id| and |app_type|. // Returns AppId from |app_service_id| and |app_type|.
AppId AppIdFromAppServiceId(const std::string& app_service_id, AppId AppIdFromAppServiceId(const std::string& app_service_id,
apps::mojom::AppType app_type) const; apps::mojom::AppType app_type) const;
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "base/values.h" #include "base/values.h"
#include "chrome/browser/chromeos/child_accounts/child_user_service.h"
#include "chrome/browser/chromeos/child_accounts/time_limits/app_activity_registry.h" #include "chrome/browser/chromeos/child_accounts/time_limits/app_activity_registry.h"
#include "chrome/browser/chromeos/child_accounts/time_limits/app_service_wrapper.h" #include "chrome/browser/chromeos/child_accounts/time_limits/app_service_wrapper.h"
#include "chrome/browser/chromeos/child_accounts/time_limits/app_time_limit_utils.h" #include "chrome/browser/chromeos/child_accounts/time_limits/app_time_limit_utils.h"
...@@ -26,6 +27,7 @@ ...@@ -26,6 +27,7 @@
#include "chrome/browser/notifications/notification_display_service.h" #include "chrome/browser/notifications/notification_display_service.h"
#include "chrome/browser/notifications/notification_handler.h" #include "chrome/browser/notifications/notification_handler.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/app_list/arc/arc_app_utils.h"
#include "chrome/common/chrome_features.h" #include "chrome/common/chrome_features.h"
#include "chrome/common/pref_names.h" #include "chrome/common/pref_names.h"
#include "chrome/grit/generated_resources.h" #include "chrome/grit/generated_resources.h"
...@@ -152,58 +154,6 @@ std::string GetNotificationIdFor(const std::string& app_name, ...@@ -152,58 +154,6 @@ std::string GetNotificationIdFor(const std::string& app_name,
return base::StrCat({notification_id, app_name}); return base::StrCat({notification_id, app_name});
} }
void ShowNotificationForApp(const std::string& app_name,
AppNotification notification,
base::Optional<base::TimeDelta> time_limit,
Profile* profile,
base::Optional<gfx::ImageSkia> icon) {
DCHECK(notification == AppNotification::kFiveMinutes ||
notification == AppNotification::kOneMinute ||
notification == AppNotification::kTimeLimitChanged ||
notification == AppNotification::kBlocked ||
notification == AppNotification::kAvailable);
DCHECK(notification == AppNotification::kTimeLimitChanged ||
notification == AppNotification::kBlocked ||
notification == AppNotification::kAvailable || time_limit.has_value());
// Alright we have all the messages that we want.
const base::string16 app_name_16 = base::UTF8ToUTF16(app_name);
const base::string16 title =
GetNotificationTitleFor(app_name_16, notification);
const base::string16 message =
GetNotificationMessageFor(app_name_16, notification, time_limit);
// Family link display source.
const base::string16 notification_source =
l10n_util::GetStringUTF16(IDS_TIME_LIMIT_NOTIFICATION_DISPLAY_SOURCE);
std::string notification_id = GetNotificationIdFor(app_name, notification);
std::unique_ptr<message_center::Notification> message_center_notification =
ash::CreateSystemNotification(
message_center::NOTIFICATION_TYPE_SIMPLE, notification_id, title,
message, notification_source, GURL(),
message_center::NotifierId(
message_center::NotifierType::SYSTEM_COMPONENT,
kFamilyLinkSourceId),
message_center::RichNotificationData(),
base::MakeRefCounted<message_center::NotificationDelegate>(),
ash::kNotificationSupervisedUserIcon,
message_center::SystemNotificationWarningLevel::NORMAL);
if (icon.has_value())
message_center_notification->set_icon(gfx::Image(icon.value()));
auto* notification_display_service =
NotificationDisplayService::GetForProfile(profile);
if (!notification_display_service)
return;
notification_display_service->Display(NotificationHandler::Type::TRANSIENT,
*message_center_notification,
/*metadata=*/nullptr);
}
} // namespace } // namespace
AppTimeController::TestApi::TestApi(AppTimeController* controller) AppTimeController::TestApi::TestApi(AppTimeController* controller)
...@@ -429,8 +379,9 @@ void AppTimeController::ShowAppTimeLimitNotification( ...@@ -429,8 +379,9 @@ void AppTimeController::ShowAppTimeLimitNotification(
int size_hint_in_dp = 48; int size_hint_in_dp = 48;
app_service_wrapper_->GetAppIcon( app_service_wrapper_->GetAppIcon(
app_id, size_hint_in_dp, app_id, size_hint_in_dp,
base::BindOnce(&ShowNotificationForApp, app_name, notification, base::BindOnce(&AppTimeController::ShowNotificationForApp,
time_limit, profile_)); weak_ptr_factory_.GetWeakPtr(), app_name, notification,
time_limit));
} }
void AppTimeController::OnAppLimitReached(const AppId& app_id, void AppTimeController::OnAppLimitReached(const AppId& app_id,
...@@ -564,5 +515,77 @@ bool AppTimeController::HasTimeCrossedResetBoundary() const { ...@@ -564,5 +515,77 @@ bool AppTimeController::HasTimeCrossedResetBoundary() const {
return now < last_limits_reset_time_ || now >= kDay + last_limits_reset_time_; return now < last_limits_reset_time_ || now >= kDay + last_limits_reset_time_;
} }
void AppTimeController::OpenFamilyLinkApp() {
const std::string app_id = arc::ArcPackageNameToAppId(
chromeos::ChildUserService::kFamilyLinkHelperAppPackageName, profile_);
if (app_service_wrapper_->IsAppInstalled(app_id)) {
// Launch Family Link Help app since it is available.
app_service_wrapper_->LaunchApp(app_id);
return;
}
// No Family Link Help app installed, so try to launch Play Store to Family
// Link Help app install page.
arc::LaunchPlayStoreWithUrl(
chromeos::ChildUserService::kFamilyLinkHelperAppPlayStoreURL);
}
void AppTimeController::ShowNotificationForApp(
const std::string& app_name,
AppNotification notification,
base::Optional<base::TimeDelta> time_limit,
base::Optional<gfx::ImageSkia> icon) {
DCHECK(notification == AppNotification::kFiveMinutes ||
notification == AppNotification::kOneMinute ||
notification == AppNotification::kTimeLimitChanged ||
notification == AppNotification::kBlocked ||
notification == AppNotification::kAvailable);
DCHECK(notification == AppNotification::kTimeLimitChanged ||
notification == AppNotification::kBlocked ||
notification == AppNotification::kAvailable || time_limit.has_value());
// Alright we have all the messages that we want.
const base::string16 app_name_16 = base::UTF8ToUTF16(app_name);
const base::string16 title =
GetNotificationTitleFor(app_name_16, notification);
const base::string16 message =
GetNotificationMessageFor(app_name_16, notification, time_limit);
// Family link display source.
const base::string16 notification_source =
l10n_util::GetStringUTF16(IDS_TIME_LIMIT_NOTIFICATION_DISPLAY_SOURCE);
std::string notification_id = GetNotificationIdFor(app_name, notification);
std::unique_ptr<message_center::Notification> message_center_notification =
ash::CreateSystemNotification(
message_center::NOTIFICATION_TYPE_SIMPLE, notification_id, title,
message, notification_source, GURL(),
message_center::NotifierId(
message_center::NotifierType::SYSTEM_COMPONENT,
kFamilyLinkSourceId),
message_center::RichNotificationData(),
notification == AppNotification::kTimeLimitChanged
? base::MakeRefCounted<
message_center::HandleNotificationClickDelegate>(
base::BindRepeating(&AppTimeController::OpenFamilyLinkApp,
weak_ptr_factory_.GetWeakPtr()))
: base::MakeRefCounted<message_center::NotificationDelegate>(),
ash::kNotificationSupervisedUserIcon,
message_center::SystemNotificationWarningLevel::NORMAL);
if (icon.has_value())
message_center_notification->set_icon(gfx::Image(icon.value()));
auto* notification_display_service =
NotificationDisplayService::GetForProfile(profile_);
if (!notification_display_service)
return;
notification_display_service->Display(NotificationHandler::Type::TRANSIENT,
*message_center_notification,
/*metadata=*/nullptr);
}
} // namespace app_time } // namespace app_time
} // namespace chromeos } // namespace chromeos
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include "base/memory/weak_ptr.h"
#include "base/optional.h" #include "base/optional.h"
#include "base/time/default_tick_clock.h" #include "base/time/default_tick_clock.h"
#include "base/time/time.h" #include "base/time/time.h"
...@@ -28,6 +29,10 @@ namespace base { ...@@ -28,6 +29,10 @@ namespace base {
class OneShotTimer; class OneShotTimer;
} // namespace base } // namespace base
namespace gfx {
class ImageSkia;
} // namespace gfx
namespace chromeos { namespace chromeos {
namespace app_time { namespace app_time {
...@@ -140,6 +145,12 @@ class AppTimeController : public SystemClockClient::Observer, ...@@ -140,6 +145,12 @@ class AppTimeController : public SystemClockClient::Observer,
// Called when the system time or timezone may have changed. // Called when the system time or timezone may have changed.
bool HasTimeCrossedResetBoundary() const; bool HasTimeCrossedResetBoundary() const;
void OpenFamilyLinkApp();
void ShowNotificationForApp(const std::string& app_name,
AppNotification notification,
base::Optional<base::TimeDelta> time_limit,
base::Optional<gfx::ImageSkia> icon);
// Profile // Profile
Profile* const profile_; Profile* const profile_;
...@@ -165,6 +176,8 @@ class AppTimeController : public SystemClockClient::Observer, ...@@ -165,6 +176,8 @@ class AppTimeController : public SystemClockClient::Observer,
// Metrics information to be recorded for PerAppTimeLimits. // Metrics information to be recorded for PerAppTimeLimits.
int patl_policy_update_count_ = 0; int patl_policy_update_count_ = 0;
int apps_with_limit_ = 0; int apps_with_limit_ = 0;
base::WeakPtrFactory<AppTimeController> weak_ptr_factory_{this};
}; };
} // namespace app_time } // namespace app_time
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "base/values.h" #include "base/values.h"
#include "chrome/browser/apps/app_service/app_service_proxy.h" #include "chrome/browser/apps/app_service/app_service_proxy.h"
#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
#include "chrome/browser/chromeos/child_accounts/child_user_service.h"
#include "chrome/browser/ui/app_list/arc/arc_app_utils.h" #include "chrome/browser/ui/app_list/arc/arc_app_utils.h"
#include "chrome/browser/ui/browser_navigator.h" #include "chrome/browser/ui/browser_navigator.h"
#include "chrome/browser/ui/browser_navigator_params.h" #include "chrome/browser/ui/browser_navigator_params.h"
...@@ -26,13 +27,6 @@ ...@@ -26,13 +27,6 @@
namespace chromeos { namespace chromeos {
namespace settings { namespace settings {
const char kFamilyLinkHelperAppPackageName[] =
"com.google.android.apps.kids.familylinkhelper";
const char kFamilyLinkChildHelperAppPlayStoreURL[] =
"https://play.google.com/store/apps/"
"details?id=com.google.android.apps.kids.familylinkhelper";
const char kFamilyLinkSiteURL[] = "https://families.google.com/families"; const char kFamilyLinkSiteURL[] = "https://families.google.com/families";
ParentalControlsHandler::ParentalControlsHandler(Profile* profile) ParentalControlsHandler::ParentalControlsHandler(Profile* profile)
...@@ -72,8 +66,8 @@ void ParentalControlsHandler::HandleLaunchFamilyLinkSettings( ...@@ -72,8 +66,8 @@ void ParentalControlsHandler::HandleLaunchFamilyLinkSettings(
apps::AppServiceProxyFactory::GetForProfile(profile_); apps::AppServiceProxyFactory::GetForProfile(profile_);
apps::AppRegistryCache& registry = proxy->AppRegistryCache(); apps::AppRegistryCache& registry = proxy->AppRegistryCache();
const std::string app_id = const std::string app_id = arc::ArcPackageNameToAppId(
arc::ArcPackageNameToAppId(kFamilyLinkHelperAppPackageName, profile_); chromeos::ChildUserService::kFamilyLinkHelperAppPackageName, profile_);
if (registry.GetAppType(app_id) != apps::mojom::AppType::kUnknown) { if (registry.GetAppType(app_id) != apps::mojom::AppType::kUnknown) {
// Launch FLH app since it is available. // Launch FLH app since it is available.
proxy->Launch(app_id, ui::EventFlags::EF_NONE, proxy->Launch(app_id, ui::EventFlags::EF_NONE,
...@@ -84,7 +78,8 @@ void ParentalControlsHandler::HandleLaunchFamilyLinkSettings( ...@@ -84,7 +78,8 @@ void ParentalControlsHandler::HandleLaunchFamilyLinkSettings(
// No FLH app installed, so try to launch Play Store to FLH app install page. // No FLH app installed, so try to launch Play Store to FLH app install page.
// If there is no Play Store available LaunchPlayStoreWithUrl() will return // If there is no Play Store available LaunchPlayStoreWithUrl() will return
// false. // false.
if (arc::LaunchPlayStoreWithUrl(kFamilyLinkChildHelperAppPlayStoreURL)) { if (arc::LaunchPlayStoreWithUrl(
chromeos::ChildUserService::kFamilyLinkHelperAppPlayStoreURL)) {
return; return;
} }
// As a last resort, launch browser to the family link site. // As a last resort, launch browser to the family link site.
......
...@@ -178,7 +178,8 @@ enum LaunchSource { ...@@ -178,7 +178,8 @@ enum LaunchSource {
kFromAppListQueryContextMenu = 4, // Query-dependent results; context menu. kFromAppListQueryContextMenu = 4, // Query-dependent results; context menu.
kFromAppListRecommendation = 5, // Query-less recommendations (smaller kFromAppListRecommendation = 5, // Query-less recommendations (smaller
// icons). // icons).
kFromParentalControls = 6, // Parental Controls Settings Section. kFromParentalControls = 6, // Parental Controls Settings Section and
// Per App time notification.
kFromShelf = 7, // Shelf. kFromShelf = 7, // Shelf.
kFromFileManager = 8, // FileManager. kFromFileManager = 8, // FileManager.
kFromLink = 9, // Left-licking on links in the browser. kFromLink = 9, // Left-licking on links in the browser.
......
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