// Copyright 2018 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/web_app_database.h"

#include <set>
#include <string>
#include <utility>
#include <vector>

#include "base/check.h"
#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/metrics/histogram_functions.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "chrome/browser/web_applications/proto/web_app.pb.h"
#include "chrome/browser/web_applications/proto/web_app_launch_handler.pb.h"
#include "chrome/browser/web_applications/web_app.h"
#include "chrome/browser/web_applications/web_app_database_factory.h"
#include "chrome/browser/web_applications/web_app_database_serialization.h"
#include "chrome/browser/web_applications/web_app_helpers.h"
#include "chrome/browser/web_applications/web_app_proto_utils.h"
#include "chrome/browser/web_applications/web_app_registry_update.h"
#include "chrome/browser/web_applications/web_app_utils.h"
#include "chrome/common/chrome_features.h"
#include "components/sync/base/data_type.h"
#include "components/sync/model/data_type_store.h"
#include "components/sync/model/metadata_batch.h"
#include "components/sync/model/metadata_change_list.h"
#include "components/sync/model/model_error.h"
#include "components/sync/protocol/web_app_specifics.pb.h"
#include "components/webapps/browser/installable/installable_metrics.h"
#include "components/webapps/common/web_app_id.h"
#include "url/gurl.h"

namespace web_app {

WebAppDatabase::WebAppDatabase(AbstractWebAppDatabaseFactory* database_factory,
                               ReportErrorCallback error_callback)
    : database_factory_(database_factory),
      error_callback_(std::move(error_callback)) {
  DCHECK(database_factory_);
}

WebAppDatabase::~WebAppDatabase() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
}

void WebAppDatabase::OpenDatabase(RegistryOpenedCallback callback) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK(!store_);

  syncer::OnceDataTypeStoreFactory store_factory =
      database_factory_->GetStoreFactory();

  std::move(store_factory)
      .Run(syncer::WEB_APPS,
           base::BindOnce(&WebAppDatabase::OnDatabaseOpened,
                          weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}

void WebAppDatabase::Write(
    const RegistryUpdateData& update_data,
    std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
    CompletionCallback callback) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  CHECK(opened_);

  std::unique_ptr<syncer::DataTypeStore::WriteBatch> write_batch =
      store_->CreateWriteBatch();

  // |update_data| can be empty here but we should write |metadata_change_list|
  // anyway.
  write_batch->TakeMetadataChangesFrom(std::move(metadata_change_list));

  for (const std::unique_ptr<WebApp>& web_app : update_data.apps_to_create) {
    auto proto = WebAppToProto(*web_app);
    write_batch->WriteData(web_app->app_id(), proto->SerializeAsString());
  }

  for (const std::unique_ptr<WebApp>& web_app : update_data.apps_to_update) {
    auto proto = WebAppToProto(*web_app);
    write_batch->WriteData(web_app->app_id(), proto->SerializeAsString());
  }

  for (const webapps::AppId& app_id : update_data.apps_to_delete) {
    write_batch->DeleteData(app_id);
  }

  store_->CommitWriteBatch(
      std::move(write_batch),
      base::BindOnce(&WebAppDatabase::OnDataWritten,
                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}

// static
int WebAppDatabase::GetCurrentDatabaseVersion() {
  return 4;
}

WebAppDatabase::ProtobufState::ProtobufState() = default;
WebAppDatabase::ProtobufState::~ProtobufState() = default;
WebAppDatabase::ProtobufState::ProtobufState(ProtobufState&&) = default;
WebAppDatabase::ProtobufState& WebAppDatabase::ProtobufState::operator=(
    ProtobufState&&) = default;

WebAppDatabase::ProtobufState WebAppDatabase::ParseProtobufs(
    const syncer::DataTypeStore::RecordList& data_records) const {
  ProtobufState state;
  for (const syncer::DataTypeStore::Record& record : data_records) {
    if (record.id == kDatabaseMetadataKey) {
      bool success = state.metadata.ParseFromString(record.value);
      if (!success) {
        DLOG(ERROR)
            << "WebApps LevelDB parse error: can't parse metadata proto.";
        // TODO: Consider logging a histogram
      }
      continue;
    }

    proto::WebApp app_proto;
    bool success = app_proto.ParseFromString(record.value);
    if (!success) {
      DLOG(ERROR) << "WebApps LevelDB parse error: can't parse app proto.";
      // TODO: Consider logging a histogram
    }
    state.apps.emplace(record.id, std::move(app_proto));
  }
  return state;
}

void WebAppDatabase::MigrateDatabase(ProtobufState& state) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  // Migration should happen when we have gotten a `store_`, but haven't
  // finished opening the database yet.
  CHECK(store_);
  CHECK(!opened_);

  bool did_change_metadata = false;
  std::set<webapps::AppId> changed_apps;

  // Upgrade from version 0 to version 1. This migrates the kSync source to
  // a combination of kSync and kUserInstalled.
  if (state.metadata.version() < 1 && GetCurrentDatabaseVersion() >= 1) {
    MigrateInstallSourceAddUserInstalled(state, changed_apps);
    base::UmaHistogramSparse("WebApp.Database.VersionUpgradedTo", 1);
    state.metadata.set_version(1);
    did_change_metadata = true;
  }

  // Upgrade from version 1 to version 2.
  if (state.metadata.version() < 2 && GetCurrentDatabaseVersion() >= 2) {
    MigrateShortcutAppsToDiyApps(state, changed_apps);
    MigrateDefaultDisplayModeToPlatformDisplayMode(state, changed_apps);
    MigratePartiallyInstalledAppsToCorrectState(state, changed_apps);
    base::UmaHistogramSparse("WebApp.Database.VersionUpgradedTo", 2);
    state.metadata.set_version(2);
    did_change_metadata = true;
  }

  // Upgrade from version 2 to version 3.
  if (state.metadata.version() < 3 && GetCurrentDatabaseVersion() >= 3) {
    MigrateDeprecatedLaunchHandlerToClientMode(state, changed_apps);
    MigrateScopeToRemoveRefAndQuery(state, changed_apps);
    MigrateToRelativeManifestIdNoFragment(state, changed_apps);
    base::UmaHistogramSparse("WebApp.Database.VersionUpgradedTo", 3);
    state.metadata.set_version(3);
    did_change_metadata = true;
  }

  // Upgrade from version 3 to version 4.
  if (state.metadata.version() < 4 && GetCurrentDatabaseVersion() >= 4) {
    MigratePendingUpdateInfoWasIgnored(state, changed_apps);
    base::UmaHistogramSparse("WebApp.Database.VersionUpgradedTo", 4);
    state.metadata.set_version(4);
    did_change_metadata = true;
  }

  CHECK_EQ(state.metadata.version(), GetCurrentDatabaseVersion());

  if (did_change_metadata || !changed_apps.empty()) {
    std::unique_ptr<syncer::DataTypeStore::WriteBatch> write_batch =
        store_->CreateWriteBatch();
    if (did_change_metadata) {
      write_batch->WriteData(std::string(kDatabaseMetadataKey),
                             state.metadata.SerializeAsString());
    }
    for (const auto& app_id : changed_apps) {
      CHECK(state.apps.contains(app_id));
      write_batch->WriteData(app_id, state.apps[app_id].SerializeAsString());
    }
    store_->CommitWriteBatch(
        std::move(write_batch),
        base::BindOnce(&WebAppDatabase::OnDataWritten,
                       weak_ptr_factory_.GetWeakPtr(), base::DoNothing()));
  }
}

void WebAppDatabase::MigrateInstallSourceAddUserInstalled(
    ProtobufState& state,
    std::set<webapps::AppId>& changed_apps) {
  // Migrating from version 0 to version 1.
  CHECK_LT(state.metadata.version(), 1);
  const bool is_syncing_apps = database_factory_->IsSyncingApps();
  int apps_migrated_count = 0;
  for (auto& [app_id, app_proto] : state.apps) {
    if (!app_proto.sources().sync()) {
      continue;
    }
    bool changed = false;
    if (!app_proto.sources().user_installed()) {
      app_proto.mutable_sources()->set_user_installed(true);
      changed = true;
    }
    if (!is_syncing_apps) {
      app_proto.mutable_sources()->set_sync(false);
      changed = true;
    }
    if (changed) {
      changed_apps.insert(app_id);
      apps_migrated_count++;
    }
  }
  base::UmaHistogramCounts1000(
      "WebApp.Migrations.InstallSourceAddUserInstalled", apps_migrated_count);
}

void WebAppDatabase::MigrateShortcutAppsToDiyApps(
    WebAppDatabase::ProtobufState& state,
    std::set<webapps::AppId>& changed_apps) {
  // Migrating from version 1 to version 2.
  CHECK_LT(state.metadata.version(), 2);
  int shortcut_to_diy_apps = 0;
  for (auto& [app_id, app_proto] : state.apps) {
    bool is_shortcut =
        !app_proto.has_scope() || app_proto.scope().empty() ||
        (app_proto.has_latest_install_source() &&
         app_proto.latest_install_source() ==
             static_cast<uint32_t>(
                 webapps::WebappInstallSource::MENU_CREATE_SHORTCUT));
    if (!is_shortcut) {
      continue;
    }
    changed_apps.insert(app_id);
    app_proto.set_is_diy_app(true);
    app_proto.set_was_shortcut_app(true);
    shortcut_to_diy_apps++;
    if (app_proto.has_scope() && !app_proto.scope().empty() &&
        GURL(app_proto.scope()).is_valid()) {
      continue;
    }
    // Populate the scope if it was empty or invalid.
    if (!app_proto.has_sync_data() || !app_proto.sync_data().has_start_url()) {
      DLOG(ERROR) << "Missing sync data or start_url for shortcut app "
                  << app_id;
      continue;
    }
    GURL start_url(app_proto.sync_data().start_url());
    if (!start_url.is_valid()) {
      // Cannot recover scope, mark for potential cleanup later if needed.
      DLOG(ERROR) << "Invalid start_url for shortcut app " << app_id << ":"
                  << start_url.possibly_invalid_spec();
      continue;
    }
    app_proto.set_scope(start_url.GetWithoutFilename().spec());
  }
  base::UmaHistogramCounts1000("WebApp.Migrations.ShortcutAppsToDiy2",
                               shortcut_to_diy_apps);
}

void WebAppDatabase::MigrateDefaultDisplayModeToPlatformDisplayMode(
    WebAppDatabase::ProtobufState& state,
    std::set<webapps::AppId>& changed_apps) {
  // Migrating from version 1 to version 2.
  CHECK_LT(state.metadata.version(), 2);
  int apps_migrated_count = 0;
  for (auto& [app_id, app_proto] : state.apps) {
    if (!app_proto.has_sync_data()) {
      // Cannot migrate without sync data.
      continue;
    }
    sync_pb::WebAppSpecifics* sync_data = app_proto.mutable_sync_data();
    if (!HasCurrentPlatformUserDisplayMode(*sync_data)) {
      sync_pb::WebAppSpecifics_UserDisplayMode udm =
          ResolvePlatformSpecificUserDisplayMode(*sync_data);
      SetPlatformSpecificUserDisplayMode(udm, sync_data);
      changed_apps.insert(app_id);
      apps_migrated_count++;
    }
  }
  base::UmaHistogramCounts1000("WebApp.Migrations.DefaultDisplayModeToPlatform",
                               apps_migrated_count);
}

// Corrects the install_state for apps that claim OS integration but lack the
// necessary OS integration state data.
void WebAppDatabase::MigratePartiallyInstalledAppsToCorrectState(
    WebAppDatabase::ProtobufState& state,
    std::set<webapps::AppId>& changed_apps) {
  // Migrating from version 1 to version 2.
  CHECK_LT(state.metadata.version(), 2);
  int install_state_fixed_count = 0;
  for (auto& [app_id, app_proto] : state.apps) {
    if (app_proto.install_state() !=
        proto::InstallState::INSTALLED_WITH_OS_INTEGRATION) {
      continue;
    }
    // Check if any OS integration state exists. A simple check for shortcut
    // presence is sufficient as a proxy for any OS integration.
    if (app_proto.has_current_os_integration_states() &&
        app_proto.current_os_integration_states().has_shortcut()) {
      continue;
    }
    app_proto.set_install_state(
        proto::InstallState::INSTALLED_WITHOUT_OS_INTEGRATION);
    changed_apps.insert(app_id);
    install_state_fixed_count++;
  }
  base::UmaHistogramCounts1000(
      "WebApp.Migrations.PartiallyInstalledAppsToCorrectState",
      install_state_fixed_count);
}

void WebAppDatabase::MigrateDeprecatedLaunchHandlerToClientMode(
    ProtobufState& state,
    std::set<webapps::AppId>& changed_apps) {
  // Migrating from version 2 to version 3.
  CHECK_LT(state.metadata.version(), 3);
  int apps_migrated_count = 0;
  for (auto& [app_id, app_proto] : state.apps) {
    if (!app_proto.has_launch_handler()) {
      continue;
    }

    bool changed = false;
    proto::LaunchHandler* launch_handler = app_proto.mutable_launch_handler();

    // If client_mode is unspecified, try migrating from deprecated fields.
    if (launch_handler->client_mode() ==
        proto::LaunchHandler::CLIENT_MODE_UNSPECIFIED) {
      proto::LaunchHandler::ClientMode migrated_client_mode =
          proto::LaunchHandler::CLIENT_MODE_UNSPECIFIED;
      switch (launch_handler->route_to()) {
        case proto::LaunchHandler_DeprecatedRouteTo_UNSPECIFIED_ROUTE:
          break;
        case proto::LaunchHandler_DeprecatedRouteTo_AUTO_ROUTE:
          migrated_client_mode = proto::LaunchHandler::CLIENT_MODE_AUTO;
          break;
        case proto::LaunchHandler_DeprecatedRouteTo_NEW_CLIENT:
          migrated_client_mode = proto::LaunchHandler::CLIENT_MODE_NAVIGATE_NEW;
          break;
        case proto::LaunchHandler_DeprecatedRouteTo_EXISTING_CLIENT:
          if (launch_handler->navigate_existing_client() ==
              proto::LaunchHandler_DeprecatedNavigateExistingClient_NEVER) {
            migrated_client_mode =
                proto::LaunchHandler::CLIENT_MODE_FOCUS_EXISTING;
          } else {
            migrated_client_mode =
                proto::LaunchHandler::CLIENT_MODE_NAVIGATE_EXISTING;
          }
          break;
        case proto::LaunchHandler_DeprecatedRouteTo_EXISTING_CLIENT_NAVIGATE:
          migrated_client_mode =
              proto::LaunchHandler::CLIENT_MODE_NAVIGATE_EXISTING;
          break;
        case proto::LaunchHandler_DeprecatedRouteTo_EXISTING_CLIENT_RETAIN:
          migrated_client_mode =
              proto::LaunchHandler::CLIENT_MODE_FOCUS_EXISTING;
          break;
      }
      launch_handler->set_client_mode(migrated_client_mode);
      changed = true;
    } else if (launch_handler->client_mode() ==
               proto::LaunchHandler::CLIENT_MODE_AUTO) {
      // If client_mode is set to auto, and client_mode_valid_and_specified is
      // explicitly false, treat client_mode as unspecified.
      if (launch_handler->has_client_mode_valid_and_specified() &&
          !launch_handler->client_mode_valid_and_specified()) {
        launch_handler->set_client_mode(
            proto::LaunchHandler::CLIENT_MODE_UNSPECIFIED);
        changed = true;
      }
    }

    // Clear deprecated fields if they exist.
    if (launch_handler->has_route_to()) {
      launch_handler->clear_route_to();
      changed = true;
    }
    if (launch_handler->has_navigate_existing_client()) {
      launch_handler->clear_navigate_existing_client();
      changed = true;
    }
    if (launch_handler->has_client_mode_valid_and_specified()) {
      launch_handler->clear_client_mode_valid_and_specified();
      changed = true;
    }

    if (changed) {
      changed_apps.insert(app_id);
      apps_migrated_count++;
    }
  }
  base::UmaHistogramCounts1000(
      "WebApp.Migrations.DeprecatedLaunchHandlerToClientMode",
      apps_migrated_count);
}

void WebAppDatabase::MigrateScopeToRemoveRefAndQuery(
    ProtobufState& state,
    std::set<webapps::AppId>& changed_apps) {
  // Migrating from version 2 to version 3.
  CHECK_LT(state.metadata.version(), 3);
  int apps_migrated_count = 0;
  for (auto& [app_id, app_proto] : state.apps) {
    if (!app_proto.has_scope()) {
      continue;
    }
    GURL scope(app_proto.scope());
    if (!scope.is_valid()) {
      continue;
    }

    if (scope.has_query() || scope.has_ref()) {
      GURL::Replacements replacements;
      replacements.ClearQuery();
      replacements.ClearRef();
      GURL clean_scope = scope.ReplaceComponents(replacements);
      app_proto.set_scope(clean_scope.spec());
      changed_apps.insert(app_id);
      apps_migrated_count++;
    }
  }
  base::UmaHistogramCounts1000("WebApp.Migrations.ScopeRefQueryRemoved",
                               apps_migrated_count);
}

void WebAppDatabase::MigrateToRelativeManifestIdNoFragment(
    ProtobufState& state,
    std::set<webapps::AppId>& changed_apps) {
  // Migrating from version 2 to version 3.
  CHECK_LT(state.metadata.version(), 3);
  int apps_migrated_count = 0;
  int fragment_removed_count = 0;
  for (auto& [app_id, app_proto] : state.apps) {
    if (!app_proto.has_sync_data()) {
      continue;
    }
    sync_pb::WebAppSpecifics* sync_data = app_proto.mutable_sync_data();
    if (!sync_data->has_start_url()) {
      continue;
    }
    GURL start_url(sync_data->start_url());
    if (!start_url.is_valid()) {
      continue;
    }

    // Calculate the expected manifest_id and relative path without fragment.
    webapps::ManifestId expected_manifest_id;
    if (sync_data->has_relative_manifest_id()) {
      expected_manifest_id =
          GenerateManifestId(sync_data->relative_manifest_id(), start_url);
    } else {
      expected_manifest_id = GenerateManifestIdFromStartUrlOnly(start_url);
    }
    if (!expected_manifest_id.is_valid()) {
      continue;
    }
    std::string expected_relative_path =
        RelativeManifestIdPath(expected_manifest_id);

    bool changed = false;
    if (!sync_data->has_relative_manifest_id()) {
      // Populate if missing.
      sync_data->set_relative_manifest_id(expected_relative_path);
      changed = true;
    } else if (sync_data->relative_manifest_id() != expected_relative_path) {
      // Correct if different (e.g., had a fragment).
      sync_data->set_relative_manifest_id(expected_relative_path);
      changed = true;
      fragment_removed_count++;
    }

    if (changed) {
      changed_apps.insert(app_id);
      apps_migrated_count++;
    }
  }
  base::UmaHistogramCounts1000(
      "WebApp.Migrations.RelativeManifestIdFragmentRemoved",
      fragment_removed_count);
  base::UmaHistogramCounts1000(
      "WebApp.Migrations.RelativeManifestIdPopulatedOrFixed",
      apps_migrated_count);
}

void WebAppDatabase::MigratePendingUpdateInfoWasIgnored(
    ProtobufState& state,
    std::set<webapps::AppId>& changed_apps) {
  // Migrating from version 3 to version 4.
  CHECK_LT(state.metadata.version(), 4);
  int apps_migrated_count = 0;

  for (auto& [app_id, app_proto] : state.apps) {
    // Bypass apps that don't have a pending update info, or has the
    // `was_ignored` field set.
    if (!app_proto.has_pending_update_info() ||
        app_proto.pending_update_info().has_was_ignored()) {
      continue;
    }

    apps_migrated_count++;
    app_proto.mutable_pending_update_info()->set_was_ignored(false);
    changed_apps.insert(app_id);
  }
  // Record histograms correctly.
  base::UmaHistogramCounts1000(
      "WebApp.Migrations.PendingInfoWasIgnoredMigrated", apps_migrated_count);
}

void WebAppDatabase::OnDatabaseOpened(
    RegistryOpenedCallback callback,
    const std::optional<syncer::ModelError>& error,
    std::unique_ptr<syncer::DataTypeStore> store) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  if (error) {
    error_callback_.Run(*error);
    DLOG(ERROR) << "WebApps LevelDB opening error: " << error->ToString();
    return;
  }

  store_ = std::move(store);
  store_->ReadAllDataAndMetadata(
      base::BindOnce(&WebAppDatabase::OnAllDataAndMetadataRead,
                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}

void WebAppDatabase::OnAllDataAndMetadataRead(
    RegistryOpenedCallback callback,
    const std::optional<syncer::ModelError>& error,
    std::unique_ptr<syncer::DataTypeStore::RecordList> data_records,
    std::unique_ptr<syncer::MetadataBatch> metadata_batch) {
  TRACE_EVENT0("ui", "WebAppDatabase::OnAllMetadataRead");
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  if (error) {
    error_callback_.Run(*error);
    DLOG(ERROR) << "WebApps LevelDB read error: " << error->ToString();
    return;
  }

  ProtobufState state = ParseProtobufs(*data_records);
  MigrateDatabase(state);

  Registry registry;
  for (const auto& [app_id, app_proto] : state.apps) {
    std::unique_ptr<WebApp> web_app = ParseWebAppProto(app_proto);
    base::UmaHistogramBoolean("WebApp.Database.ValidProto", web_app != nullptr);
    if (!web_app) {
      continue;
    }

    // Record whether the derived app_id matches the database key.
    bool mismatch = (web_app->app_id() != app_id);
    base::UmaHistogramBoolean("WebApp.Database.AppIdMatch", !mismatch);

    if (mismatch) {
      DLOG(ERROR) << "WebApps LevelDB error: app_id doesn't match storage key "
                  << app_id << " vs " << web_app->app_id() << ", from "
                  << web_app->manifest_id();
      continue;
    }
    registry.emplace(app_id, std::move(web_app));
  }

  opened_ = true;
  // This should be a tail call: a callback code may indirectly call |this|
  // methods, like WebAppDatabase::Write()
  std::move(callback).Run(std::move(registry), std::move(metadata_batch));
}

void WebAppDatabase::OnDataWritten(
    CompletionCallback callback,
    const std::optional<syncer::ModelError>& error) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  if (error) {
    error_callback_.Run(*error);
    DLOG(ERROR) << "WebApps LevelDB write error: " << error->ToString();
  }

  std::move(callback).Run(!error);
}

}  // namespace web_app
