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

#include "chrome/browser/web_applications/sampling_metrics_provider.h"

#include "base/containers/contains.h"
#include "base/metrics/histogram_macros.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/ui/browser_window/public/browser_window_interface.h"
#include "chrome/browser/ui/browser_window/public/browser_window_interface_iterator.h"
#include "chrome/browser/web_applications/daily_metrics_helper.h"
#include "chrome/browser/web_applications/mojom/user_display_mode.mojom.h"
#include "chrome/browser/web_applications/web_app_provider.h"
#include "chrome/browser/web_applications/web_app_registrar.h"
#include "chrome/browser/web_applications/web_app_tab_helper.h"
#include "chrome/browser/web_applications/web_app_utils.h"
#include "components/services/app_service/public/cpp/preferred_apps_list.h"
#include "components/tabs/public/tab_interface.h"
#include "components/webapps/browser/banners/app_banner_manager.h"
#include "components/webapps/browser/banners/installable_web_app_check_result.h"
#include "components/webapps/browser/banners/web_app_banner_data.h"

namespace web_app {

namespace {

// Decreasing this number will improve accuracy at the expense of more frequent
// client-side work.
constexpr int kTimerIntervalInSeconds = 5 * 60;

using IdSet = std::set<webapps::AppId>;

// Emits UKM metrics for the given tab. The tab may be for an app window or a
// normal browser window.
void EmitUkmMetricsForTab(tabs::TabInterface* tab) {
  BrowserWindowInterface* browser = tab->GetBrowserWindowInterface();
  CHECK(browser);
  Profile* profile = browser->GetProfile();
  auto* web_app_helper =
      web_app::WebAppTabHelper::FromWebContents(tab->GetContents());
  CHECK(web_app_helper);
  std::optional<webapps::AppId> app_id = web_app_helper->app_id();
  CHECK(app_id);

  auto* provider = web_app::WebAppProvider::GetForWebApps(profile);
  auto& registrar = provider->registrar_unsafe();
  DailyInteraction interaction;

  interaction.start_url = registrar.GetAppStartUrl(*app_id);
  interaction.installed = registrar.IsInstallState(
      *app_id, {proto::INSTALLED_WITHOUT_OS_INTEGRATION,
                proto::INSTALLED_WITH_OS_INTEGRATION});
  auto install_source =
      provider->registrar_unsafe().GetLatestAppInstallSource(*app_id);
  if (install_source) {
    interaction.install_source = static_cast<int>(*install_source);
  }
  DisplayMode display_mode =
      provider->registrar_unsafe().GetAppEffectiveDisplayMode(*app_id);
  interaction.effective_display_mode = static_cast<int>(display_mode);

#if BUILDFLAG(IS_CHROMEOS)
  if (apps::AppServiceProxyFactory::IsAppServiceAvailableForProfile(profile)) {
    auto* proxy = apps::AppServiceProxyFactory::GetForProfile(profile);
    interaction.captures_links =
        proxy->PreferredAppsList().IsPreferredAppForSupportedLinks(*app_id);
  }
#else
  interaction.captures_links = registrar.CapturesLinksInScope(*app_id);
#endif
  interaction.promotable = !registrar.IsDiyApp(*app_id);

  if (tab->IsActivated() && browser->IsActive()) {
    interaction.foreground_duration = base::Seconds(kTimerIntervalInSeconds);
  } else {
    interaction.background_duration = base::Seconds(kTimerIntervalInSeconds);
  }
  // Note that with this new sampling approach we are no longer tracking the
  // concept of session, and thus don't fill in num_sessions.
  FlushOldRecordsAndUpdate(interaction, profile);
}

// Checks whether metrics should be emitted. If so, updates `emitted_ids` and
// emits metrics.
void MaybeEmitUkmMetricsForTab(tabs::TabInterface* tab, IdSet& emitted_ids) {
  CHECK(tab->GetContents());
  auto* web_app_helper =
      web_app::WebAppTabHelper::FromWebContents(tab->GetContents());
  if (!web_app_helper) {
    return;
  }
  std::optional<webapps::AppId> app_id = web_app_helper->app_id();

  // A tab in an app window doesn't necessarily have to be in-scope of that
  // app. In can be out of scope, or simply not have it's navigation committed
  // yet.
  if (!app_id) {
    return;
  }

  // We only emit UKM metrics a single time for a given AppId.
  if (base::Contains(emitted_ids, *app_id)) {
    return;
  }

  auto* provider = web_app::WebAppProvider::GetForWebApps(
      tab->GetBrowserWindowInterface()->GetProfile());
  auto& registrar = provider->registrar_unsafe();
  std::optional<mojom::UserDisplayMode> user_display_mode =
      registrar.GetAppUserDisplayMode(*app_id);
  CHECK(user_display_mode);
  switch (*user_display_mode) {
    case mojom::UserDisplayMode::kBrowser:
      // Emit metrics only if the app is configured to run in a tab
      // window, and is running in a tab.
      if (tab->GetBrowserWindowInterface()->GetType() ==
          BrowserWindowInterface::Type::TYPE_NORMAL) {
        emitted_ids.insert(*app_id);
        EmitUkmMetricsForTab(tab);
      }
      break;
    case mojom::UserDisplayMode::kStandalone:
      // Emit metrics only if the app is configured to run in a standalone
      // window, and is running in a standalone window.
      if (tab->GetBrowserWindowInterface()->GetAppBrowserController()) {
        emitted_ids.insert(*app_id);
        EmitUkmMetricsForTab(tab);
      }
      break;
    case mojom::UserDisplayMode::kTabbed:
      // We don't track metrics for tabbed standalone PWAs.
      break;
  }
}

// Checks whether metrics should be emitted. If so, updates `emitted_ids` and
// emits metrics.
void MaybeEmitUkmMetricsForPromotable(
    tabs::TabInterface* tab,
    const webapps::WebAppBannerData& banner_data,
    IdSet& emitted_ids) {
  const GURL& url = banner_data.manifest().start_url;
  if (base::Contains(emitted_ids, url.spec())) {
    return;
  }

  emitted_ids.insert(url.spec());
  DailyInteraction interaction;
  interaction.start_url = url;
  interaction.installed = false;
  if (!banner_data.manifest().display_override.empty()) {
    interaction.effective_display_mode =
        static_cast<int>(banner_data.manifest().display_override[0]);
  } else {
    interaction.effective_display_mode =
        static_cast<int>(banner_data.manifest().display);
  }
  interaction.promotable = true;
  FlushOldRecordsAndUpdate(interaction,
                           tab->GetBrowserWindowInterface()->GetProfile());
}

}  // namespace

SamplingMetricsProvider::SamplingMetricsProvider() {
  timer_.Start(FROM_HERE, base::Seconds(kTimerIntervalInSeconds),
               base::BindRepeating(&SamplingMetricsProvider::EmitMetrics));
}

SamplingMetricsProvider::~SamplingMetricsProvider() = default;

void SamplingMetricsProvider::EmitMetrics() {
  // Total number of PWAs, including backgrounded, separated by tabbed vs
  // standalone.
  int standalone_pwas_count = 0;
  int tabbed_pwas_count = 0;

  // Whether the foreground window has a PWA as its foreground tab, separated by
  // tabbed vs standalone.
  bool standalone_pwas_in_active_use = false;
  bool tabbed_pwas_in_active_use = false;

  // Number of tabbed PWAs, split by most common configurations.
  int tabbed_pwas_user_display_mode_browser_count = 0;
  int tabbed_pwas_user_display_mode_browser_installed_by_user_count = 0;

  int tabbed_pwas_display_mode_standalone_count = 0;
  int tabbed_pwas_display_mode_standalone_installed_by_user_count = 0;

  IdSet emitted_ukm_ids;
  for (BrowserWindowInterface* browser : GetAllBrowserWindowInterfaces()) {
    if (!AreWebAppsEnabled(browser->GetProfile())) {
      continue;
    }
    // If this is a standalone app window.
    if (browser->GetAppBrowserController()) {
      // A browser may be being closed due to empty tabs. See
      // https://crbug.com/378020140.
      if (!browser->GetActiveTabInterface()) {
        continue;
      }

      ++standalone_pwas_count;

      // TODO(https://crbug.com/358404364): This function does not work on macOS
      // for app windows.
      if (browser->IsActive()) {
        standalone_pwas_in_active_use = true;
      }

      MaybeEmitUkmMetricsForTab(browser->GetActiveTabInterface(),
                                emitted_ukm_ids);
    }

    // If this is a PWA-tab in a normal browser window.
    if (browser->GetType() == BrowserWindowInterface::Type::TYPE_NORMAL) {
      auto* provider =
          web_app::WebAppProvider::GetForWebApps(browser->GetProfile());
      auto& registrar = provider->registrar_unsafe();

      for (tabs::TabInterface* tab : browser->GetAllTabInterfaces()) {
        auto* web_app_helper =
            web_app::WebAppTabHelper::FromWebContents(tab->GetContents());
        std::optional<webapps::AppId> app_id = web_app_helper->app_id();
        if (app_id) {
          ++tabbed_pwas_count;
          if (tab->IsActivated() && browser->IsActive()) {
            tabbed_pwas_in_active_use = true;
          }

          std::optional<mojom::UserDisplayMode> user_display_mode =
              registrar.GetAppUserDisplayMode(*app_id);
          bool installed_by_user = registrar.WasInstalledByUser(*app_id);
          if (user_display_mode == mojom::UserDisplayMode::kBrowser) {
            ++tabbed_pwas_user_display_mode_browser_count;
            if (installed_by_user) {
              ++tabbed_pwas_user_display_mode_browser_installed_by_user_count;
            }
          }

          if (user_display_mode == mojom::UserDisplayMode::kStandalone) {
            ++tabbed_pwas_display_mode_standalone_count;
            if (installed_by_user) {
              ++tabbed_pwas_display_mode_standalone_installed_by_user_count;
            }
          }
          MaybeEmitUkmMetricsForTab(tab, emitted_ukm_ids);
        } else {
          // If the tab does not have an app id, it might be promotable.
          auto* app_banner_manager =
              webapps::AppBannerManager::FromWebContents(tab->GetContents());
          if (app_banner_manager) {
            std::optional<webapps::WebAppBannerData> banner_data =
                app_banner_manager->GetCurrentWebAppBannerData();
            webapps::InstallableWebAppCheckResult installable =
                app_banner_manager->GetInstallableWebAppCheckResult();

            if (banner_data &&
                installable ==
                    webapps::InstallableWebAppCheckResult::kYes_Promotable) {
              MaybeEmitUkmMetricsForPromotable(tab, *banner_data,
                                               emitted_ukm_ids);
            }
          }
        }
      }
    }
  }

  int pwas_count = standalone_pwas_count + tabbed_pwas_count;
  bool pwas_in_active_use =
      standalone_pwas_in_active_use || tabbed_pwas_in_active_use;
  UMA_HISTOGRAM_COUNTS_100("WebApp.Engagement2.Count", pwas_count);
  UMA_HISTOGRAM_BOOLEAN("WebApp.Engagement2.Active", pwas_in_active_use);

  UMA_HISTOGRAM_COUNTS_100("WebApp.Engagement2.Standalone.Count",
                           standalone_pwas_count);
  UMA_HISTOGRAM_COUNTS_100("WebApp.Engagement2.Tabbed.Count",
                           tabbed_pwas_count);
  UMA_HISTOGRAM_BOOLEAN("WebApp.Engagement2.Standalone.Active",
                        standalone_pwas_in_active_use);
  UMA_HISTOGRAM_BOOLEAN("WebApp.Engagement2.Tabbed.Active",
                        tabbed_pwas_in_active_use);

  UMA_HISTOGRAM_COUNTS_100(
      "WebApp.Engagement2.Tabbed.UserDisplayModeBrowser.Count",
      tabbed_pwas_user_display_mode_browser_count);
  UMA_HISTOGRAM_COUNTS_100(
      "WebApp.Engagement2.Tabbed.UserDisplayModeBrowserInstalledByUser.Count",
      tabbed_pwas_user_display_mode_browser_installed_by_user_count);
  UMA_HISTOGRAM_COUNTS_100(
      "WebApp.Engagement2.Tabbed.UserDisplayModeStandalone.Count",
      tabbed_pwas_display_mode_standalone_count);
  UMA_HISTOGRAM_COUNTS_100(
      "WebApp.Engagement2.Tabbed.UserDisplayModeStandaloneInstalledByUser."
      "Count",
      tabbed_pwas_display_mode_standalone_installed_by_user_count);
}

}  // namespace web_app
