blob: c6a6b9d918467852be2454ee7614740df64928c7 [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/appcache/appcache_backfillers.h"
#include "content/browser/appcache/appcache_update_job.h"
#include "sql/statement.h"
#include "storage/browser/quota/padding_key.h"
#include "url/gurl.h"
namespace content {
namespace {
int64_t ComputeEntryPaddingSize(std::string response_url,
std::string manifest_url) {
if (GURL(response_url).GetOrigin() == GURL(manifest_url).GetOrigin())
return 0;
return storage::ComputeResponsePadding(
response_url, storage::GetDefaultPaddingKey(), /*has_metadata=*/false,
/*loaded_with_credentials=*/false);
}
// Iterates over each Cache record; execute |callable| on each iteration.
//
// ForEachCallable: (int64_t cache_id, int64_t group_id) -> bool.
//
// Returns whether the database queries succeeded.
template <typename ForEachCallable>
bool ForEachCache(sql::Database* db, const ForEachCallable& callable) {
static const char kSql[] = "SELECT cache_id, group_id FROM Caches";
sql::Statement statement(db->GetUniqueStatement(kSql));
while (statement.Step()) {
int64_t cache_id = statement.ColumnInt64(0);
int64_t group_id = statement.ColumnInt64(1);
if (!callable(cache_id, group_id))
return false;
}
return true;
}
} // namespace
// AppCacheBackfillerVersion8
bool AppCacheBackfillerVersion8::BackfillPaddingSizes() {
return ForEachCache(db_, [&](int64_t cache_id, int64_t group_id) -> bool {
base::Optional<std::string> manifest_url = GetManifestUrlForGroup(group_id);
if (!manifest_url.has_value())
return false;
int64_t cache_padding_size = 0;
if (!ForEachEntry(
cache_id,
[&](std::string response_url, int64_t response_id) -> bool {
int64_t entry_padding_size =
ComputeEntryPaddingSize(response_url, manifest_url.value());
cache_padding_size += entry_padding_size;
return UpdateEntryPaddingSize(response_id, entry_padding_size);
})) {
return false;
}
return UpdateCachePaddingSize(cache_id, cache_padding_size);
});
}
template <typename ForEachCallable>
bool AppCacheBackfillerVersion8::ForEachEntry(int64_t cache_id,
const ForEachCallable& callable) {
static const char kSql[] =
"SELECT url, response_id, cache_id FROM Entries WHERE cache_id = ?";
sql::Statement statement(db_->GetUniqueStatement(kSql));
statement.BindInt64(0, cache_id);
while (statement.Step()) {
std::string url = statement.ColumnString(0);
int64_t response_id = statement.ColumnInt64(1);
if (!callable(url, response_id))
return false;
}
return true;
}
base::Optional<std::string> AppCacheBackfillerVersion8::GetManifestUrlForGroup(
int64_t group_id) {
static const char kSql[] =
"SELECT manifest_url, group_id FROM Groups WHERE group_id = ?";
sql::Statement statement(db_->GetUniqueStatement(kSql));
statement.BindInt64(0, group_id);
if (!statement.Step())
return base::nullopt;
return statement.ColumnString(0);
}
bool AppCacheBackfillerVersion8::UpdateEntryPaddingSize(int64_t response_id,
int64_t padding_size) {
static const char kSql[] =
"UPDATE Entries SET padding_size = ? WHERE response_id = ?";
sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
statement.BindInt64(0, padding_size);
statement.BindInt64(1, response_id);
return statement.Run();
}
bool AppCacheBackfillerVersion8::UpdateCachePaddingSize(int64_t cache_id,
int64_t padding_size) {
static const char kSql[] =
"UPDATE Caches SET padding_size = ? WHERE cache_id = ?";
sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
statement.BindInt64(0, padding_size);
statement.BindInt64(1, cache_id);
return statement.Run();
}
// AppCacheBackfillerVersion9
bool AppCacheBackfillerVersion9::BackfillManifestParserVersionAndScope() {
return ForEachCache(db_, [&](int64_t cache_id, int64_t group_id) -> bool {
base::Optional<std::string> manifest_url = GetManifestUrlForGroup(group_id);
if (!manifest_url.has_value())
return false;
// |manifest_parser_version| should be set to 0 to recognize that scope
// checking wasn't enabled when this group record was written.
int64_t manifest_parser_version = 0;
if (!UpdateCacheManifestParserVersion(cache_id, manifest_parser_version))
return false;
// This is where pre-version 9 DBs will end up with a manifest scope
// that previously didn't have one. Update using the entire origin for a
// scope. Will end up getting "fixed" on the next update from version 0 to
// version 1 once manifest scoping is enabled.
std::string manifest_scope = "/";
return UpdateCacheManifestScope(cache_id, manifest_scope);
});
}
bool AppCacheBackfillerVersion9::UpdateCacheManifestParserVersion(
int64_t cache_id,
int64_t manifest_parser_version) {
static const char kSql[] =
"UPDATE Caches SET manifest_parser_version = ? WHERE"
" cache_id = ?";
sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
statement.BindInt64(0, manifest_parser_version);
statement.BindInt64(1, cache_id);
return statement.Run();
}
bool AppCacheBackfillerVersion9::UpdateCacheManifestScope(
int64_t cache_id,
const std::string& manifest_scope) {
static const char kSql[] =
"UPDATE Caches SET manifest_scope = ? WHERE"
" cache_id = ?";
sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
statement.BindString(0, manifest_scope);
statement.BindInt64(1, cache_id);
return statement.Run();
}
base::Optional<std::string> AppCacheBackfillerVersion9::GetManifestUrlForGroup(
int64_t group_id) {
static const char kSql[] =
"SELECT manifest_url, group_id FROM Groups WHERE group_id = ?";
sql::Statement statement(db_->GetUniqueStatement(kSql));
statement.BindInt64(0, group_id);
if (!statement.Step())
return base::nullopt;
return statement.ColumnString(0);
}
} // namespace content