#include "components/services/storage/service_worker/service_worker_database.h"
#include <optional>
#include "base/command_line.h"
#include "base/debug/crash_logging.h"
#include "base/files/file_util.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/no_destructor.h"
#include "base/notreached.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "components/services/storage/filesystem_proxy_factory.h"
#include "components/services/storage/public/mojom/service_worker_database.mojom-forward.h"
#include "components/services/storage/service_worker/service_worker_database.pb.h"
#include "services/network/public/cpp/web_sandbox_flags.h"
#include "services/network/public/mojom/ip_address_space.mojom-shared.h"
#include "services/network/public/mojom/referrer_policy.mojom.h"
#include "services/network/public/mojom/service_worker_router_info.mojom-shared.h"
#include "services/network/public/mojom/web_sandbox_flags.mojom-shared.h"
#include "third_party/blink/public/common/service_worker/service_worker_router_rule.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_ancestor_frame_type.mojom.h"
#include "third_party/leveldatabase/env_chromium.h"
#include "third_party/leveldatabase/leveldb_chrome.h"
#include "third_party/leveldatabase/src/include/leveldb/db.h"
#include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
#include "url/origin.h"
namespace storage {
namespace service_worker_internals {
const char kDatabaseVersionKey[] = …;
const char kNextRegIdKey[] = …;
const char kNextResIdKey[] = …;
const char kNextVerIdKey[] = …;
const char kUniqueOriginKey[] = …;
const char kRegKeyPrefix[] = …;
const char kRegUserDataKeyPrefix[] = …;
const char kRegHasUserDataKeyPrefix[] = …;
const char kRegIdToOriginKeyPrefix[] = …;
const char kResKeyPrefix[] = …;
const char kKeySeparator = …;
const char kUncommittedResIdKeyPrefix[] = …;
const char kPurgeableResIdKeyPrefix[] = …;
const int64_t kCurrentSchemaVersion = …;
const int kRouterRuleVersion = …;
}
namespace {
constexpr size_t kWriteBufferSize = …;
class ServiceWorkerEnv : public leveldb_env::ChromiumEnv { … };
bool RemovePrefix(const std::string& str,
const std::string& prefix,
std::string* out) { … }
std::string CreateRegistrationKeyPrefix(const blink::StorageKey& key) { … }
std::string CreateRegistrationKey(int64_t registration_id,
const blink::StorageKey& key) { … }
std::string CreateResourceRecordKeyPrefix(int64_t version_id) { … }
std::string CreateResourceRecordKey(int64_t version_id, int64_t resource_id) { … }
std::string CreateUniqueOriginKey(const blink::StorageKey& key) { … }
std::string CreateResourceIdKey(const char* key_prefix, int64_t resource_id) { … }
std::string CreateUserDataKeyPrefix(int64_t registration_id) { … }
std::string CreateUserDataKey(int64_t registration_id,
const std::string& user_data_name) { … }
std::string CreateHasUserDataKeyPrefix(const std::string& user_data_name) { … }
std::string CreateHasUserDataKey(int64_t registration_id,
const std::string& user_data_name) { … }
std::string CreateRegistrationIdToStorageKey(int64_t registration_id) { … }
void PutUniqueOriginToBatch(const blink::StorageKey& key,
leveldb::WriteBatch* batch) { … }
void PutPurgeableResourceIdToBatch(int64_t resource_id,
leveldb::WriteBatch* batch) { … }
ServiceWorkerDatabase::Status ParseId(const std::string& serialized,
int64_t* out) { … }
ServiceWorkerDatabase::Status LevelDBStatusToServiceWorkerDBStatus(
const leveldb::Status& status) { … }
int64_t AccumulateResourceSizeInBytes(
const std::vector<mojom::ServiceWorkerResourceRecordPtr>& resources) { … }
std::optional<std::vector<liburlpattern::Part>> ConvertToBlinkParts(
const google::protobuf::RepeatedPtrField<
storage::ServiceWorkerRegistrationData::RouterRules::RuleV1::Condition::
URLPattern::Part>& parts) { … }
void ConvertToProtoParts(
const std::vector<liburlpattern::Part> parts,
google::protobuf::RepeatedPtrField<
storage::ServiceWorkerRegistrationData::RouterRules::RuleV1::Condition::
URLPattern::Part>* out_parts) { … }
bool WriteToBlinkCondition(
const ServiceWorkerRegistrationData::RouterRules::RuleV1::Condition&
condition,
blink::ServiceWorkerRouterCondition& out) { … }
class AddConditionHelper { … };
void WriteConditionToProtoWithHelper(
const blink::ServiceWorkerRouterCondition& condition,
AddConditionHelper& out) { … }
void WriteConditionToProto(
const blink::ServiceWorkerRouterCondition& condition,
ServiceWorkerRegistrationData::RouterRules::RuleV1* out) { … }
}
const char* ServiceWorkerDatabase::StatusToString(
ServiceWorkerDatabase::Status status) { … }
ServiceWorkerDatabase::ServiceWorkerDatabase(const base::FilePath& path)
: … { … }
ServiceWorkerDatabase::~ServiceWorkerDatabase() { … }
ServiceWorkerDatabase::DeletedVersion::DeletedVersion() = default;
ServiceWorkerDatabase::DeletedVersion::DeletedVersion(const DeletedVersion&) =
default;
ServiceWorkerDatabase::DeletedVersion::~DeletedVersion() = default;
ServiceWorkerDatabase::Status ServiceWorkerDatabase::GetNextAvailableIds(
int64_t* next_avail_registration_id,
int64_t* next_avail_version_id,
int64_t* next_avail_resource_id) { … }
ServiceWorkerDatabase::Status
ServiceWorkerDatabase::GetStorageKeysWithRegistrations(
std::set<blink::StorageKey>* keys) { … }
ServiceWorkerDatabase::Status
ServiceWorkerDatabase::GetRegistrationsForStorageKey(
const blink::StorageKey& key,
std::vector<mojom::ServiceWorkerRegistrationDataPtr>* registrations,
std::vector<std::vector<mojom::ServiceWorkerResourceRecordPtr>>*
opt_resources_list) { … }
ServiceWorkerDatabase::Status ServiceWorkerDatabase::GetUsageForStorageKey(
const blink::StorageKey& key,
int64_t& out_usage) { … }
ServiceWorkerDatabase::Status ServiceWorkerDatabase::GetAllRegistrations(
std::vector<mojom::ServiceWorkerRegistrationDataPtr>* registrations) { … }
ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadRegistration(
int64_t registration_id,
const blink::StorageKey& key,
mojom::ServiceWorkerRegistrationDataPtr* registration,
std::vector<mojom::ServiceWorkerResourceRecordPtr>* resources) { … }
ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadRegistrationStorageKey(
int64_t registration_id,
blink::StorageKey* key) { … }
ServiceWorkerDatabase::Status ServiceWorkerDatabase::WriteRegistration(
const mojom::ServiceWorkerRegistrationData& registration,
const std::vector<mojom::ServiceWorkerResourceRecordPtr>& resources,
DeletedVersion* deleted_version) { … }
ServiceWorkerDatabase::Status ServiceWorkerDatabase::UpdateVersionToActive(
int64_t registration_id,
const blink::StorageKey& key) { … }
ServiceWorkerDatabase::Status ServiceWorkerDatabase::UpdateLastCheckTime(
int64_t registration_id,
const blink::StorageKey& key,
const base::Time& time) { … }
ServiceWorkerDatabase::Status
ServiceWorkerDatabase::UpdateNavigationPreloadEnabled(
int64_t registration_id,
const blink::StorageKey& key,
bool enable) { … }
ServiceWorkerDatabase::Status
ServiceWorkerDatabase::UpdateNavigationPreloadHeader(
int64_t registration_id,
const blink::StorageKey& key,
const std::string& value) { … }
ServiceWorkerDatabase::Status ServiceWorkerDatabase::UpdateFetchHandlerType(
int64_t registration_id,
const blink::StorageKey& key,
const blink::mojom::ServiceWorkerFetchHandlerType type) { … }
ServiceWorkerDatabase::Status
ServiceWorkerDatabase::UpdateResourceSha256Checksums(
int64_t registration_id,
const blink::StorageKey& key,
const base::flat_map<int64_t, std::string>& updated_sha256_checksums) { … }
ServiceWorkerDatabase::Status ServiceWorkerDatabase::DeleteRegistration(
int64_t registration_id,
const blink::StorageKey& key,
DeletedVersion* deleted_version) { … }
ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadUserData(
int64_t registration_id,
const std::vector<std::string>& user_data_names,
std::vector<std::string>* user_data_values) { … }
ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadUserDataByKeyPrefix(
int64_t registration_id,
const std::string& user_data_name_prefix,
std::vector<std::string>* user_data_values) { … }
ServiceWorkerDatabase::Status
ServiceWorkerDatabase::ReadUserKeysAndDataByKeyPrefix(
int64_t registration_id,
const std::string& user_data_name_prefix,
base::flat_map<std::string, std::string>* user_data_map) { … }
ServiceWorkerDatabase::Status ServiceWorkerDatabase::WriteUserData(
int64_t registration_id,
const blink::StorageKey& key,
const std::vector<mojom::ServiceWorkerUserDataPtr>& user_data) { … }
ServiceWorkerDatabase::Status ServiceWorkerDatabase::DeleteUserData(
int64_t registration_id,
const std::vector<std::string>& user_data_names) { … }
ServiceWorkerDatabase::Status
ServiceWorkerDatabase::DeleteUserDataByKeyPrefixes(
int64_t registration_id,
const std::vector<std::string>& user_data_name_prefixes) { … }
ServiceWorkerDatabase::Status ServiceWorkerDatabase::RewriteDB() { … }
ServiceWorkerDatabase::Status
ServiceWorkerDatabase::ReadUserDataForAllRegistrations(
const std::string& user_data_name,
std::vector<mojom::ServiceWorkerUserDataPtr>* user_data) { … }
ServiceWorkerDatabase::Status
ServiceWorkerDatabase::ReadUserDataForAllRegistrationsByKeyPrefix(
const std::string& user_data_name_prefix,
std::vector<mojom::ServiceWorkerUserDataPtr>* user_data) { … }
ServiceWorkerDatabase::Status
ServiceWorkerDatabase::DeleteUserDataForAllRegistrationsByKeyPrefix(
const std::string& user_data_name_prefix) { … }
ServiceWorkerDatabase::Status ServiceWorkerDatabase::GetUncommittedResourceIds(
std::vector<int64_t>* ids) { … }
ServiceWorkerDatabase::Status
ServiceWorkerDatabase::WriteUncommittedResourceIds(
const std::vector<int64_t>& ids) { … }
ServiceWorkerDatabase::Status ServiceWorkerDatabase::GetPurgeableResourceIds(
std::vector<int64_t>* ids) { … }
ServiceWorkerDatabase::Status ServiceWorkerDatabase::ClearPurgeableResourceIds(
const std::vector<int64_t>& ids) { … }
ServiceWorkerDatabase::Status
ServiceWorkerDatabase::PurgeUncommittedResourceIds(
const std::vector<int64_t>& ids) { … }
ServiceWorkerDatabase::Status ServiceWorkerDatabase::DeleteAllDataForOrigins(
const std::set<url::Origin>& origins,
std::vector<int64_t>* newly_purgeable_resources) { … }
ServiceWorkerDatabase::Status ServiceWorkerDatabase::DestroyDatabase() { … }
ServiceWorkerDatabase::Status ServiceWorkerDatabase::LazyOpen(
bool create_if_missing) { … }
bool ServiceWorkerDatabase::IsNewOrNonexistentDatabase(
ServiceWorkerDatabase::Status status) { … }
ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadNextAvailableId(
const char* id_key,
int64_t* next_avail_id) { … }
ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadRegistrationData(
int64_t registration_id,
const blink::StorageKey& key,
mojom::ServiceWorkerRegistrationDataPtr* registration) { … }
network::mojom::ReferrerPolicy ConvertReferrerPolicyFromProtocolBufferToMojom(
ServiceWorkerRegistrationData::ReferrerPolicyValue value) { … }
network::mojom::IPAddressSpace ConvertIPAddressSpaceFromProtocolBufferToMojom(
ServiceWorkerRegistrationData::IPAddressSpace value) { … }
ServiceWorkerDatabase::Status ServiceWorkerDatabase::ParseRegistrationData(
const std::string& serialized,
const blink::StorageKey& key,
mojom::ServiceWorkerRegistrationDataPtr* out) { … }
ServiceWorkerRegistrationData::CrossOriginEmbedderPolicyValue
ConvertCrossOriginEmbedderPolicyValueFromMojomToProtocolBuffer(
network::mojom::CrossOriginEmbedderPolicyValue value) { … }
ServiceWorkerRegistrationData::ReferrerPolicyValue
ConvertReferrerPolicyFromMojomToProtocolBuffer(
network::mojom::ReferrerPolicy value) { … }
ServiceWorkerRegistrationData::IPAddressSpace
ConvertIPAddressSpaceFromMojomToProtocolBuffer(
network::mojom::IPAddressSpace value) { … }
void ServiceWorkerDatabase::WriteRegistrationDataInBatch(
const mojom::ServiceWorkerRegistrationData& registration,
leveldb::WriteBatch* batch) { … }
ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadResourceRecords(
const mojom::ServiceWorkerRegistrationData& registration,
std::vector<mojom::ServiceWorkerResourceRecordPtr>* resources) { … }
ServiceWorkerDatabase::Status ServiceWorkerDatabase::ParseResourceRecord(
const std::string& serialized,
mojom::ServiceWorkerResourceRecordPtr* out) { … }
void ServiceWorkerDatabase::WriteResourceRecordInBatch(
const mojom::ServiceWorkerResourceRecord& resource,
int64_t version_id,
leveldb::WriteBatch* batch) { … }
ServiceWorkerDatabase::Status ServiceWorkerDatabase::DeleteResourceRecords(
int64_t version_id,
std::vector<int64_t>* newly_purgeable_resources,
leveldb::WriteBatch* batch) { … }
ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadResourceIds(
const char* id_key_prefix,
std::vector<int64_t>* ids) { … }
ServiceWorkerDatabase::Status ServiceWorkerDatabase::WriteResourceIdsInBatch(
const char* id_key_prefix,
const std::vector<int64_t>& ids,
leveldb::WriteBatch* batch) { … }
ServiceWorkerDatabase::Status ServiceWorkerDatabase::DeleteResourceIdsInBatch(
const char* id_key_prefix,
const std::vector<int64_t>& ids,
leveldb::WriteBatch* batch) { … }
ServiceWorkerDatabase::Status
ServiceWorkerDatabase::DeleteUserDataForRegistration(
int64_t registration_id,
leveldb::WriteBatch* batch) { … }
ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadDatabaseVersion(
int64_t* db_version) { … }
ServiceWorkerDatabase::Status ServiceWorkerDatabase::WriteBatch(
leveldb::WriteBatch* batch) { … }
void ServiceWorkerDatabase::BumpNextRegistrationIdIfNeeded(
int64_t used_id,
leveldb::WriteBatch* batch) { … }
void ServiceWorkerDatabase::BumpNextResourceIdIfNeeded(
int64_t used_id,
leveldb::WriteBatch* batch) { … }
void ServiceWorkerDatabase::BumpNextVersionIdIfNeeded(
int64_t used_id,
leveldb::WriteBatch* batch) { … }
bool ServiceWorkerDatabase::IsOpen() { … }
void ServiceWorkerDatabase::Disable(const base::Location& from_here,
Status status) { … }
void ServiceWorkerDatabase::HandleOpenResult(const base::Location& from_here,
Status status) { … }
void ServiceWorkerDatabase::HandleReadResult(const base::Location& from_here,
Status status) { … }
void ServiceWorkerDatabase::HandleWriteResult(const base::Location& from_here,
Status status) { … }
bool ServiceWorkerDatabase::IsDatabaseInMemory() const { … }
}