chromium/ash/public/cpp/desk_template.cc

// Copyright 2021 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/public/cpp/desk_template.h"

#include "ash/constants/ash_features.h"
#include "ash/public/cpp/window_properties.h"
#include "base/i18n/time_formatting.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "chromeos/ui/base/app_types.h"
#include "chromeos/ui/base/window_properties.h"
#include "components/sync_device_info/local_device_info_util.h"
#include "components/tab_groups/tab_group_info.h"
#include "ui/aura/window.h"

namespace ash {

namespace {

std::string TabGroupDataToString(const app_restore::RestoreData* restore_data) {
  std::string result = "tab groups:[";

  for (const auto& app : restore_data->app_id_to_launch_list()) {
    for (const auto& window : app.second) {
      for (const auto& tab_group :
           window.second->browser_extra_info.tab_group_infos) {
        result += "\n" + tab_group.ToString() + ",";
      }
    }
  }

  result += "]\n";
  return result;
}

}  // namespace

DeskTemplate::DeskTemplate(base::Uuid uuid,
                           DeskTemplateSource source,
                           const std::string& name,
                           const base::Time created_time,
                           DeskTemplateType type)
    : uuid_(std::move(uuid)),
      source_(source),
      type_(type),
      created_time_(created_time),
      template_name_(base::UTF8ToUTF16(name)),
      device_form_factor_(syncer::GetLocalDeviceFormFactor()) {}

DeskTemplate::DeskTemplate(base::Uuid uuid,
                           DeskTemplateSource source,
                           const std::string& name,
                           const base::Time created_time,
                           DeskTemplateType type,
                           bool should_launch_on_startup,
                           base::Value policy)
    : uuid_(std::move(uuid)),
      source_(source),
      type_(type),
      created_time_(created_time),
      template_name_(base::UTF8ToUTF16(name)),
      should_launch_on_startup_(should_launch_on_startup),
      device_form_factor_(syncer::GetLocalDeviceFormFactor()) {
  policy_definition_ = std::move(policy);
}

DeskTemplate::~DeskTemplate() = default;

// static
bool DeskTemplate::IsAppTypeSupported(aura::Window* window) {
  // For now we'll ignore crostini windows in desk templates.
  const chromeos::AppType app_type = window->GetProperty(chromeos::kAppTypeKey);
  switch (app_type) {
    case chromeos::AppType::NON_APP:
    case chromeos::AppType::CROSTINI_APP:
      return false;
    case chromeos::AppType::LACROS:
    case chromeos::AppType::ARC_APP:
    case chromeos::AppType::BROWSER:
    case chromeos::AppType::CHROME_APP:
    case chromeos::AppType::SYSTEM_APP:
      return true;
  }
}

constexpr char DeskTemplate::kIncognitoWindowIdentifier[];

std::unique_ptr<DeskTemplate> DeskTemplate::Clone() const {
  std::unique_ptr<DeskTemplate> desk_template = std::make_unique<DeskTemplate>(
      uuid_, source_, base::UTF16ToUTF8(template_name_), created_time_, type_);
  if (WasUpdatedSinceCreation())
    desk_template->set_updated_time(updated_time_);
  if (desk_restore_data_)
    desk_template->set_desk_restore_data(desk_restore_data_->Clone());
  desk_template->set_launch_id(launch_id_);
  desk_template->set_client_cache_guid(client_cache_guid_);
  desk_template->should_launch_on_startup_ = should_launch_on_startup_;
  desk_template->policy_definition_ = policy_definition_.Clone();
  desk_template->lacros_profile_id_ = lacros_profile_id_;
  return desk_template;
}

void DeskTemplate::SetDeskUuid(base::Uuid desk_uuid) {
  DCHECK(desk_restore_data_);
  desk_restore_data_->SetDeskUuid(desk_uuid);
}

std::string DeskTemplate::ToString() const {
  std::string result = GetDeskTemplateInfo(/*for_debugging=*/false);

  if (desk_restore_data_)
    result += desk_restore_data_->ToString();
  return result;
}

std::string DeskTemplate::ToDebugString() const {
  std::string result = GetDeskTemplateInfo(/*for_debugging=*/true);

  result += "Time created: " + base::TimeFormatHTTP(created_time_) + "\n";
  result += "Time updated: " + base::TimeFormatHTTP(updated_time_) + "\n";
  result += "launch id: " + base::NumberToString(launch_id_) + "\n";
  result += "auto launch: ";
  result += should_launch_on_startup_ ? "yes\n" : "no\n";
  result +=
      "Lacros profile ID: " + base::NumberToString(lacros_profile_id_) + "\n";

  // Converting to value and printing the debug string may be more
  // intensive but gives more complete information which increases
  // the utility of this function.
  if (desk_restore_data_) {
    result += desk_restore_data_->ConvertToValue().DebugString();
    result += TabGroupDataToString(desk_restore_data_.get());
  }
  return result;
}

std::string DeskTemplate::GetDeskTemplateInfo(bool for_debugging) const {
  std::string result =
      "Template name: " + base::UTF16ToUTF8(template_name_) + "\n";
  if (for_debugging)
    result += "GUID: " + uuid_.AsLowercaseString() + "\n";
  result += "Source: ";
  switch (source_) {
    case DeskTemplateSource::kUnknownSource:
      result += "unknown\n";
      break;
    case DeskTemplateSource::kUser:
      result += "user\n";
      break;
    case DeskTemplateSource::kPolicy:
      result += "policy\n";
      break;
  }
  result += "Type: ";
  switch (type_) {
    case DeskTemplateType::kTemplate:
      result += "template\n";
      break;
    case DeskTemplateType::kSaveAndRecall:
      result += "save and recall\n";
      break;
    case DeskTemplateType::kFloatingWorkspace:
      result += "floating workspace\n";
      break;
    case DeskTemplateType::kUnknown:
      result += "unknown\n";
      break;
  }
  return result;
}

}  // namespace ash