chromium/chrome/browser/ash/system_web_apps/apps/chrome_file_manager_ui_delegate.cc

// Copyright 2020 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/ash/system_web_apps/apps/chrome_file_manager_ui_delegate.h"

#include "base/metrics/histogram_functions.h"
#include "base/task/sequenced_task_runner.h"
#include "base/time/time.h"
#include "base/values.h"
#include "chrome/browser/ash/drive/file_system_util.h"
#include "chrome/browser/ash/file_manager/file_manager_string_util.h"
#include "chrome/browser/ash/file_manager/io_task_controller.h"
#include "chrome/browser/ash/file_manager/volume_manager.h"
#include "chrome/browser/ash/policy/dlp/files_policy_notification_manager.h"
#include "chrome/browser/ash/policy/dlp/files_policy_notification_manager_factory.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/webui/plural_string_handler.h"
#include "components/drive/drive_pref_names.h"
#include "components/drive/file_errors.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_message_handler.h"

ChromeFileManagerUIDelegate::ChromeFileManagerUIDelegate(content::WebUI* web_ui)
    : web_ui_(web_ui) {
  DCHECK(web_ui_);
}

ChromeFileManagerUIDelegate::~ChromeFileManagerUIDelegate() = default;

base::Value::Dict ChromeFileManagerUIDelegate::GetLoadTimeData() const {
  base::Value::Dict dict = GetFileManagerStrings();

  const std::string locale = g_browser_process->GetApplicationLocale();
  AddFileManagerFeatureStrings(locale, Profile::FromWebUI(web_ui_), &dict);
  return dict;
}

std::unique_ptr<content::WebUIMessageHandler>
ChromeFileManagerUIDelegate::GetPluralStringHandler() const {
  auto plural_string_handler = std::make_unique<PluralStringHandler>();
  for (const auto [key, value] : GetFileManagerPluralStrings()) {
    plural_string_handler->AddLocalizedString(key, value.GetInt());
  }
  return plural_string_handler;
}

void ChromeFileManagerUIDelegate::ProgressPausedTasks() const {
  file_manager::VolumeManager* const volume_manager =
      file_manager::VolumeManager::Get(Profile::FromWebUI(web_ui_));

  if (volume_manager && volume_manager->io_task_controller()) {
    volume_manager->io_task_controller()->ProgressPausedTasks();
  }
}

void ChromeFileManagerUIDelegate::ShouldPollDriveHostedPinStates(bool enabled) {
  if (poll_hosted_pin_states_ == enabled) {
    return;
  }
  poll_hosted_pin_states_ = enabled;
  if (enabled) {
    PollHostedPinStates();
  }
}

void ChromeFileManagerUIDelegate::ShowPolicyNotifications() const {
  policy::FilesPolicyNotificationManager* fpnm =
      policy::FilesPolicyNotificationManagerFactory::GetForBrowserContext(
          Profile::FromWebUI(web_ui_));
  if (fpnm) {
    fpnm->ShowBlockedNotifications();
  }
}

void ChromeFileManagerUIDelegate::PollHostedPinStates() {
  if (!poll_hosted_pin_states_) {
    return;
  }
  if (drive::DriveIntegrationService* const service =
          drive::util::GetIntegrationServiceByProfile(
              Profile::FromWebUI(web_ui_))) {
    VLOG(1) << "Polling hosted file pin states";
    service->PollHostedFilePinStates();
  }

  base::TimeDelta poll_delay =
      drive::util::IsDriveFsBulkPinningAvailable(Profile::FromWebUI(web_ui_))
          ? base::Seconds(15)
          : base::Minutes(3);

  // After the `poll_delay` call `GetDocsOfflineStats`, the
  // `PollHostedFilePinStates` function caches the number of items pinned /
  // available offline, ensure there's enough time for that data to be
  // retrieved.
  base::SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask(
      FROM_HERE,
      base::BindOnce(&ChromeFileManagerUIDelegate::PollDocsOfflineStats,
                     weak_ptr_factory_.GetWeakPtr(), poll_delay),
      poll_delay);
}

void ChromeFileManagerUIDelegate::PollDocsOfflineStats(
    const base::TimeDelta poll_delay) {
  if (drive::DriveIntegrationService* const service =
          drive::util::GetIntegrationServiceByProfile(
              Profile::FromWebUI(web_ui_))) {
    VLOG(1) << "Getting docs offline stats";
    service->GetDocsOfflineStats(
        base::BindOnce(&ChromeFileManagerUIDelegate::RecordDocsOfflineStats,
                       weak_ptr_factory_.GetWeakPtr()));
  }

  base::SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask(
      FROM_HERE,
      base::BindOnce(&ChromeFileManagerUIDelegate::PollHostedPinStates,
                     weak_ptr_factory_.GetWeakPtr()),
      poll_delay);
}

void ChromeFileManagerUIDelegate::RecordDocsOfflineStats(
    drive::FileError error,
    drivefs::mojom::DocsOfflineStatsPtr stats) {
  if (error != drive::FileError::FILE_ERROR_OK || !stats ||
      stats->total == -1 || stats->available_offline == -1) {
    VLOG(1) << "Not recording the Docs offline UMA stat";
    return;
  }

  const int32_t availability_percent =
      stats->total == 0 ? 0 : (stats->available_offline * 100 / stats->total);

  // Only emitted if a change in percentage is detected.
  if (total_available_offline_hosted_files_ != stats->available_offline ||
      total_hosted_files_ != stats->total) {
    base::UmaHistogramPercentage(
        "FileBrowser.GoogleDrive.DSSAvailabilityPercentage",
        availability_percent);
  }

  // Emitted after 1 day has elapsed since it was last emitted.
  if (Profile* const profile = Profile::FromWebUI(web_ui_)) {
    PrefService* const prefs = profile->GetPrefs();
    DCHECK(prefs);

    const base::TimeDelta time_since_last_update =
        base::Time::Now() -
        prefs->GetTime(drive::prefs::kDriveFsDSSAvailabilityLastEmitted);
    if (time_since_last_update > base::Days(1)) {
      base::UmaHistogramPercentage(
          "FileBrowser.GoogleDrive.DailyDSSAvailabilityPercentage",
          availability_percent);
    }

    if (time_since_last_update > base::Days(1) ||
        time_since_last_update.is_negative()) {
      prefs->SetTime(drive::prefs::kDriveFsDSSAvailabilityLastEmitted,
                     base::Time::Now());
    }
  }

  total_available_offline_hosted_files_ = stats->available_offline;
  total_hosted_files_ = stats->total;
}