blob: 8ee72aada4989075c2382ad208273c769163d59c [file] [log] [blame]
// Copyright 2025 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/model/web_app_comparison.h"
#include "base/strings/to_string.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/web_applications/proto/web_app.pb.h"
#include "chrome/browser/web_applications/web_app.h"
#include "chrome/browser/web_applications/web_app_install_info.h"
#include "chrome/browser/web_applications/web_app_proto_utils.h"
namespace web_app {
std::ostream& operator<<(std::ostream& os, PendingUpdateComparison value) {
switch (value) {
case PendingUpdateComparison::kNotPending:
return os << "kNotPending";
case PendingUpdateComparison::kHasPendingAndNotEquals:
return os << "kHasPendingAndNotEquals";
case PendingUpdateComparison::kHasPendingAndEquals:
return os << "kHasPendingAndEquals";
}
}
WebAppComparison::WebAppComparison() = default;
WebAppComparison::WebAppComparison(const WebAppComparison&) = default;
WebAppComparison& WebAppComparison::operator=(const WebAppComparison&) =
default;
WebAppComparison::WebAppComparison(WebAppComparison&&) = default;
WebAppComparison& WebAppComparison::operator=(WebAppComparison&&) = default;
WebAppComparison::~WebAppComparison() = default;
bool WebAppComparison::ExistingAppWithoutPendingEqualsNewUpdate() const {
return name_equality_ && primary_icons_equality_ &&
shortcut_menu_item_infos_equality_ && other_fields_equality_;
}
bool WebAppComparison::ExistingAppWithPendingEqualsNewUpdate() const {
bool effective_name_equality;
if (name_equality_) {
effective_name_equality =
pending_name_equality_ == PendingUpdateComparison::kNotPending;
} else {
effective_name_equality =
pending_name_equality_ == PendingUpdateComparison::kHasPendingAndEquals;
}
bool effective_primary_icon_equality;
if (primary_icons_equality_) {
effective_primary_icon_equality =
pending_primary_icons_equality_ == PendingUpdateComparison::kNotPending;
} else {
effective_primary_icon_equality =
pending_primary_icons_equality_ ==
PendingUpdateComparison::kHasPendingAndEquals;
}
return effective_name_equality && effective_primary_icon_equality &&
other_fields_equality_ && shortcut_menu_item_infos_equality_;
}
bool WebAppComparison::IsNameChangeOnly() const {
return !name_equality_ && primary_icons_equality_ &&
shortcut_menu_item_infos_equality_ && other_fields_equality_;
}
bool WebAppComparison::IsSecuritySensitiveChangesOnly() const {
return !name_equality_ && !primary_icons_equality_ &&
shortcut_menu_item_infos_equality_ && other_fields_equality_;
}
base::DictValue WebAppComparison::ToDict() const {
return base::DictValue()
.Set("name_equality", name_equality_)
.Set("pending_name_equality", base::ToString(pending_name_equality_))
.Set("primary_icons_equality", primary_icons_equality_)
.Set("pending_primary_icons_equality",
base::ToString(pending_primary_icons_equality_))
.Set("shortcut_menu_item_infos_equality",
shortcut_menu_item_infos_equality_)
.Set("other_fields_equality", other_fields_equality_);
}
// static
WebAppComparison WebAppComparison::CompareWebApps(
const WebApp& existing_web_app,
const WebAppInstallInfo& new_install_info) {
CHECK_EQ(existing_web_app.manifest_id(), new_install_info.manifest_id());
WebAppComparison diff;
diff.name_equality_ = [&]() {
std::u16string new_title;
base::TrimWhitespace(new_install_info.title, base::TRIM_ALL, &new_title);
return new_title == base::UTF8ToUTF16(existing_web_app.untranslated_name());
}();
diff.pending_name_equality_ = [&]() {
if (!existing_web_app.pending_update_info().has_value() ||
!existing_web_app.pending_update_info()->has_name()) {
return PendingUpdateComparison::kNotPending;
}
std::u16string new_title;
base::TrimWhitespace(new_install_info.title, base::TRIM_ALL, &new_title);
return new_title == base::UTF8ToUTF16(
existing_web_app.pending_update_info()->name())
? PendingUpdateComparison::kHasPendingAndEquals
: PendingUpdateComparison::kHasPendingAndNotEquals;
}();
diff.primary_icons_equality_ =
existing_web_app.trusted_icons() == new_install_info.trusted_icons;
diff.pending_primary_icons_equality_ = [&]() {
if (!existing_web_app.pending_update_info().has_value() ||
existing_web_app.pending_update_info()->trusted_icons().empty()) {
return PendingUpdateComparison::kNotPending;
}
std::optional<std::vector<apps::IconInfo>> transformed = ParseAppIconInfos(
"PendingUpdateInfo",
existing_web_app.pending_update_info()->trusted_icons());
if (transformed == new_install_info.trusted_icons) {
return PendingUpdateComparison::kHasPendingAndEquals;
}
return PendingUpdateComparison::kHasPendingAndNotEquals;
}();
diff.shortcut_menu_item_infos_equality_ =
existing_web_app.shortcuts_menu_item_infos() ==
new_install_info.shortcuts_menu_item_infos;
diff.other_fields_equality_ = [&]() {
if (existing_web_app.start_url() != new_install_info.start_url()) {
return false;
}
if (existing_web_app.theme_color() != new_install_info.theme_color) {
return false;
}
if (existing_web_app.scope() != new_install_info.scope) {
return false;
}
if (existing_web_app.display_mode() != new_install_info.display_mode) {
return false;
}
if (existing_web_app.display_mode_override() !=
new_install_info.display_override) {
return false;
}
if (existing_web_app.share_target() != new_install_info.share_target) {
return false;
}
if (existing_web_app.protocol_handlers() !=
new_install_info.protocol_handlers) {
return false;
}
if (existing_web_app.note_taking_new_note_url() !=
new_install_info.note_taking_new_note_url) {
return false;
}
if (existing_web_app.background_color() !=
new_install_info.background_color) {
return false;
}
if (existing_web_app.dark_mode_theme_color() !=
new_install_info.dark_mode_theme_color) {
return false;
}
if (existing_web_app.dark_mode_background_color() !=
new_install_info.dark_mode_background_color) {
return false;
}
if (existing_web_app.launch_handler() != new_install_info.launch_handler) {
return false;
}
if (existing_web_app.permissions_policy() !=
new_install_info.permissions_policy) {
return false;
}
if (existing_web_app.scope_extensions() !=
new_install_info.scope_extensions) {
return false;
}
if (existing_web_app.related_applications() !=
new_install_info.related_applications) {
return false;
}
if (existing_web_app.file_handlers() != new_install_info.file_handlers) {
return false;
}
if (existing_web_app.tab_strip() != new_install_info.tab_strip) {
return false;
}
// Add new manifest properties here to be considered for update.
return true;
}();
return diff;
}
} // namespace web_app