chromium/ash/quick_pair/companion_app/companion_app_broker_impl.cc

// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ash/quick_pair/companion_app/companion_app_broker_impl.h"

#include <algorithm>
#include <set>
#include <string>

#include "ash/constants/ash_features.h"
#include "ash/login_status.h"
#include "ash/public/cpp/new_window_delegate.h"
#include "ash/quick_pair/common/quick_pair_browser_delegate.h"
#include "ash/session/session_controller_impl.h"
#include "ash/shell.h"
#include "components/cross_device/logging/logging.h"

namespace {

bool IsLoggedIn(ash::LoginStatus status) {
  switch (status) {
    case ash::LoginStatus::NOT_LOGGED_IN:
    case ash::LoginStatus::LOCKED:
    case ash::LoginStatus::KIOSK_APP:
    case ash::LoginStatus::GUEST:
    case ash::LoginStatus::PUBLIC:
      return false;
    case ash::LoginStatus::USER:
    case ash::LoginStatus::CHILD:
    default:
      return true;
  }
}

}  // namespace

namespace ash {
namespace quick_pair {

CompanionAppBrokerImpl::CompanionAppBrokerImpl() {}

CompanionAppBrokerImpl::~CompanionAppBrokerImpl() = default;

void CompanionAppBrokerImpl::AddObserver(Observer* observer) {
  observers_.AddObserver(observer);
}

void CompanionAppBrokerImpl::RemoveObserver(Observer* observer) {
  observers_.RemoveObserver(observer);
}

bool CompanionAppBrokerImpl::MaybeShowCompanionAppActions(
    scoped_refptr<Device> device) {
  CHECK(features::IsFastPairPwaCompanionEnabled());

  // TODO(b/274973687): Make this logic more generalized once metadata
  // includes companion app ID.
  const auto metadata_id = device->metadata_id();

  const std::string& device_ids =
      ash::features::kFastPairPwaCompanionDeviceIds.Get();

  std::set<std::string> target_ids{
      "08A97F", "5A36A5", "6EDAF7", "9ADB11", "A7D7A0", "C8E228",
      "D87A3E", "F2020E", "F58DE7", "30346C", "7862CE",
  };

  if (!target_ids.contains(metadata_id) &&
      device_ids.find(metadata_id) == std::string::npos) {
    return false;
  }

  bool has_browser_link =
      GURL(ash::features::kFastPairPwaCompanionInstallUri.Get()).is_valid();
  bool has_play_link =
      GURL(ash::features::kFastPairPwaCompanionPlayStoreUri.Get()).is_valid();
  bool companion_installed =
      QuickPairBrowserDelegate::Get()->CompanionAppInstalled(
          ash::features::kFastPairPwaCompanionAppId.Get());

  signin::IdentityManager* identity_manager =
      QuickPairBrowserDelegate::Get()->GetIdentityManager();
  bool is_guest =
      !identity_manager ||
      !IsLoggedIn(Shell::Get()->session_controller()->login_status());

  // Do not show notification if there is no way to install or open the app.
  if (((!has_play_link && !companion_installed) || is_guest) &&
      !has_browser_link) {
    return false;
  }

  // Skip to opening the companion directly if no Play store link is available,
  // the app is already installed, or we are in guest-mode (guests cannot
  // install apps).
  if (!has_play_link || companion_installed || is_guest) {
    CD_LOG(VERBOSE, Feature::FP) << __func__
                                 << ": Showing \"Launch companion app\" "
                                    "notification.";

    for (auto& observer : observers_) {
      observer.ShowLaunchCompanionApp(device);
    }
  } else {
    for (auto& observer : observers_) {
      observer.ShowInstallCompanionApp(device);
    }
  }

  return true;
}

void CompanionAppBrokerImpl::InstallCompanionApp(scoped_refptr<Device> device) {
  CHECK(features::IsFastPairPwaCompanionEnabled());

  CD_LOG(VERBOSE, Feature::FP)
      << __func__ << ": Opening play store page for companion app.";

  // TODO(b/274973687): Make more generalized once device metadata includes link
  QuickPairBrowserDelegate::Get()->OpenPlayStorePage(
      GURL(ash::features::kFastPairPwaCompanionPlayStoreUri.Get()));
}

void CompanionAppBrokerImpl::LaunchCompanionApp(scoped_refptr<Device> device) {
  CHECK(features::IsFastPairPwaCompanionEnabled());

  const std::string& app_id = ash::features::kFastPairPwaCompanionAppId.Get();
  if (QuickPairBrowserDelegate::Get()->CompanionAppInstalled(app_id)) {
    CD_LOG(VERBOSE, Feature::FP) << __func__
                                 << ": Found installed app. Launching "
                                    "companion app.";

    QuickPairBrowserDelegate::Get()->LaunchCompanionApp(app_id);
  } else {
    CD_LOG(VERBOSE, Feature::FP) << __func__
                                 << ": No Play store link or installed app. "
                                    "Opening companion web page.";

    NewWindowDelegate::GetPrimary()->OpenUrl(
        GURL(ash::features::kFastPairPwaCompanionInstallUri.Get()),
        NewWindowDelegate::OpenUrlFrom::kUserInteraction,
        NewWindowDelegate::Disposition::kNewForegroundTab);
  }
}

}  // namespace quick_pair
}  // namespace ash