Commit 78f882f3 authored by Rayan Kanso's avatar Rayan Kanso Committed by Commit Bot

[Background Fetch] Create Metadata proto for persistent storage.

The metadata will store additional developer-provided fields that will
help retain & recover the state of the background fetch.
Create/Get/Update registration database tasks are updated to support
the new metadata proto.

Bug: 826257, 757760
Change-Id: I5b97638d3ab90e482911fb50479e5b8c312b4331
Reviewed-on: https://chromium-review.googlesource.com/984356
Commit-Queue: Rayan Kanso <rayankans@chromium.org>
Reviewed-by: default avatarDan Elphick <delphick@chromium.org>
Cr-Commit-Position: refs/heads/master@{#547669}
parent 5eeed90f
...@@ -9,8 +9,9 @@ option optimize_for = LITE_RUNTIME; ...@@ -9,8 +9,9 @@ option optimize_for = LITE_RUNTIME;
package content.proto; package content.proto;
// Stores per-registration (as opposed to per-request) data. // Stores per-registration (as opposed to per-request) data.
// https://wicg.github.io/background-fetch/#background-fetch-registration
// //
// Next tag: 5 // Next Tag: 7
message BackgroundFetchRegistration { message BackgroundFetchRegistration {
// See definition of |unique_id| in BackgroundFetchRegistrationId. // See definition of |unique_id| in BackgroundFetchRegistrationId.
optional string unique_id = 1; optional string unique_id = 1;
...@@ -18,12 +19,58 @@ message BackgroundFetchRegistration { ...@@ -18,12 +19,58 @@ message BackgroundFetchRegistration {
// See definition of |developer_id| in BackgroundFetchRegistrationId. // See definition of |developer_id| in BackgroundFetchRegistrationId.
optional bytes developer_id = 2; optional bytes developer_id = 2;
optional string origin = 3; optional uint64 upload_total = 3;
optional uint64 uploaded = 4;
optional uint64 download_total = 5;
optional uint64 downloaded = 6;
}
// Developer provided options.
// https://wicg.github.io/background-fetch/#background-fetch-manager
//
// Next Tag: 4
message BackgroundFetchOptions {
optional string title = 1;
// https://w3c.github.io/manifest/#icons-member
// Note that sizes can have multiple values (e.g. "32x32 64x64").
//
// Next Tag: 4
message IconDefinition {
optional string src = 1;
optional string sizes = 2;
optional string type = 3;
}
// Example value:
// icons: {
// src: "icon/lowres.webp"
// sizes: "48x48"
// type: "image/webp"
// }
// icons: {
// src: "icon/hd_hi.ico"
// sizes: "72x72 96x96 128x128 256x256"
// }
repeated IconDefinition icons = 2;
optional uint64 download_total = 3;
}
// Stores information about the background fetch that will be persisted
// in memory. This information should be everything needed to reconstruct
// the state of an interrupted background fetch.
//
// Next Tag: 6
message BackgroundFetchMetadata {
optional int64 creation_microseconds_since_unix_epoch = 1;
optional string origin = 2;
optional int64 creation_microseconds_since_unix_epoch = 4; optional BackgroundFetchRegistration registration = 3;
optional BackgroundFetchOptions options = 4;
// The notification title provided by the developer. Can be updated by // Defaults to BackgroundFetchOptions.title.
// calling `BackgroundFetchUpdateEvent.updateUI`. // Can be updated by calling `BackgroundFetchUpdateEvent.updateUI`.
// https://wicg.github.io/background-fetch/#backgroundfetchupdateevent. // https://wicg.github.io/background-fetch/#backgroundfetchupdateevent.
optional string title = 5; optional string ui_title = 5;
} }
...@@ -21,7 +21,7 @@ value: "<unique_id>" ...@@ -21,7 +21,7 @@ value: "<unique_id>"
``` ```
``` ```
key: "bgfetch_registration_<unique_id>" key: "bgfetch_registration_<unique_id>"
value: "<serialized content::proto::BackgroundFetchRegistration>" value: "<serialized content::proto::BackgroundFetchMetadata>"
``` ```
``` ```
key: "bgfetch_request_<unique_id>_<request_index>" key: "bgfetch_request_<unique_id>_<request_index>"
......
...@@ -68,10 +68,11 @@ void CleanupTask::DidGetActiveUniqueIds( ...@@ -68,10 +68,11 @@ void CleanupTask::DidGetActiveUniqueIds(
for (const auto& entry : registration_data) { for (const auto& entry : registration_data) {
int64_t service_worker_registration_id = entry.first; int64_t service_worker_registration_id = entry.first;
proto::BackgroundFetchRegistration registration_proto; proto::BackgroundFetchMetadata metadata_proto;
if (registration_proto.ParseFromString(entry.second)) { if (metadata_proto.ParseFromString(entry.second)) {
if (registration_proto.has_unique_id()) { if (metadata_proto.registration().has_unique_id()) {
const std::string& unique_id = registration_proto.unique_id(); const std::string& unique_id =
metadata_proto.registration().unique_id();
if (!active_unique_ids.count(unique_id) && if (!active_unique_ids.count(unique_id) &&
!ref_counted_unique_ids().count(unique_id)) { !ref_counted_unique_ids().count(unique_id)) {
// This |unique_id| can be safely cleaned up. Re-use // This |unique_id| can be safely cleaned up. Re-use
......
...@@ -48,7 +48,7 @@ void CreateRegistrationTask::DidGetUniqueId( ...@@ -48,7 +48,7 @@ void CreateRegistrationTask::DidGetUniqueId(
ServiceWorkerStatusCode status) { ServiceWorkerStatusCode status) {
switch (ToDatabaseStatus(status)) { switch (ToDatabaseStatus(status)) {
case DatabaseStatus::kNotFound: case DatabaseStatus::kNotFound:
StoreRegistration(); StoreMetadata();
return; return;
case DatabaseStatus::kOk: case DatabaseStatus::kOk:
// Can't create a registration since there is already an active // Can't create a registration since there is already an active
...@@ -68,27 +68,37 @@ void CreateRegistrationTask::DidGetUniqueId( ...@@ -68,27 +68,37 @@ void CreateRegistrationTask::DidGetUniqueId(
} }
} }
proto::BackgroundFetchRegistration proto::BackgroundFetchMetadata CreateRegistrationTask::CreateMetadataProto()
CreateRegistrationTask::CreateRegistrationProto() const { const {
int64_t registration_creation_microseconds_since_unix_epoch = proto::BackgroundFetchMetadata metadata_proto;
(base::Time::Now() - base::Time::UnixEpoch()).InMicroseconds();
// Set BackgroundFetchRegistration fields.
// First serialize per-registration (as opposed to per-request) data. // Upload/Download stats default to correct initial values.
// TODO(crbug.com/757760): Serialize BackgroundFetchOptions as part of this. auto* registration_proto = metadata_proto.mutable_registration();
proto::BackgroundFetchRegistration registration_proto; registration_proto->set_unique_id(registration_->unique_id);
registration_proto.set_unique_id(registration_->unique_id); registration_proto->set_developer_id(registration_->developer_id);
registration_proto.set_developer_id(registration_->developer_id);
registration_proto.set_origin(registration_id_.origin().Serialize()); // Set Options fields.
registration_proto.set_creation_microseconds_since_unix_epoch( auto* options_proto = metadata_proto.mutable_options();
registration_creation_microseconds_since_unix_epoch); options_proto->set_title(options_.title);
options_proto->set_download_total(options_.download_total);
for (const auto& icon : options_.icons) {
auto* icon_definition_proto = options_proto->add_icons();
icon_definition_proto->set_src(icon.src);
icon_definition_proto->set_sizes(icon.sizes);
icon_definition_proto->set_type(icon.type);
}
// TODO(crbug.com/826257): Write options to the proto. // Set other metadata fields.
registration_proto.set_title(options_.title); metadata_proto.set_origin(registration_id_.origin().Serialize());
metadata_proto.set_creation_microseconds_since_unix_epoch(
(base::Time::Now() - base::Time::UnixEpoch()).InMicroseconds());
metadata_proto.set_ui_title(options_.title);
return registration_proto; return metadata_proto;
} }
void CreateRegistrationTask::StoreRegistration() { void CreateRegistrationTask::StoreMetadata() {
DCHECK(!registration_); DCHECK(!registration_);
DCHECK(!registration_id_.origin().unique()); DCHECK(!registration_id_.origin().unique());
...@@ -104,11 +114,10 @@ void CreateRegistrationTask::StoreRegistration() { ...@@ -104,11 +114,10 @@ void CreateRegistrationTask::StoreRegistration() {
std::vector<std::pair<std::string, std::string>> entries; std::vector<std::pair<std::string, std::string>> entries;
entries.reserve(requests_.size() * 2 + 1); entries.reserve(requests_.size() * 2 + 1);
const proto::BackgroundFetchRegistration registration_proto = const proto::BackgroundFetchMetadata metadata_proto = CreateMetadataProto();
CreateRegistrationProto(); std::string serialized_metadata_proto;
std::string serialized_registration_proto;
if (!registration_proto.SerializeToString(&serialized_registration_proto)) { if (!metadata_proto.SerializeToString(&serialized_metadata_proto)) {
// TODO(crbug.com/780025): Log failures to UMA. // TODO(crbug.com/780025): Log failures to UMA.
std::move(callback_).Run(blink::mojom::BackgroundFetchError::STORAGE_ERROR, std::move(callback_).Run(blink::mojom::BackgroundFetchError::STORAGE_ERROR,
nullptr /* registration */); nullptr /* registration */);
...@@ -120,7 +129,7 @@ void CreateRegistrationTask::StoreRegistration() { ...@@ -120,7 +129,7 @@ void CreateRegistrationTask::StoreRegistration() {
ActiveRegistrationUniqueIdKey(registration_id_.developer_id()), ActiveRegistrationUniqueIdKey(registration_id_.developer_id()),
registration_id_.unique_id()); registration_id_.unique_id());
entries.emplace_back(RegistrationKey(registration_id_.unique_id()), entries.emplace_back(RegistrationKey(registration_id_.unique_id()),
std::move(serialized_registration_proto)); std::move(serialized_metadata_proto));
// Signed integers are used for request indexes to avoid unsigned gotchas. // Signed integers are used for request indexes to avoid unsigned gotchas.
for (int i = 0; i < base::checked_cast<int>(requests_.size()); i++) { for (int i = 0; i < base::checked_cast<int>(requests_.size()); i++) {
...@@ -129,7 +138,7 @@ void CreateRegistrationTask::StoreRegistration() { ...@@ -129,7 +138,7 @@ void CreateRegistrationTask::StoreRegistration() {
"TODO: Serialize FetchAPIRequest as value"); "TODO: Serialize FetchAPIRequest as value");
entries.emplace_back( entries.emplace_back(
PendingRequestKey( PendingRequestKey(
registration_proto.creation_microseconds_since_unix_epoch(), metadata_proto.creation_microseconds_since_unix_epoch(),
registration_id_.unique_id(), i), registration_id_.unique_id(), i),
std::string()); std::string());
} }
...@@ -137,12 +146,11 @@ void CreateRegistrationTask::StoreRegistration() { ...@@ -137,12 +146,11 @@ void CreateRegistrationTask::StoreRegistration() {
service_worker_context()->StoreRegistrationUserData( service_worker_context()->StoreRegistrationUserData(
registration_id_.service_worker_registration_id(), registration_id_.service_worker_registration_id(),
registration_id_.origin().GetURL(), entries, registration_id_.origin().GetURL(), entries,
base::Bind(&CreateRegistrationTask::DidStoreRegistration, base::BindRepeating(&CreateRegistrationTask::DidStoreMetadata,
weak_factory_.GetWeakPtr())); weak_factory_.GetWeakPtr()));
} }
void CreateRegistrationTask::DidStoreRegistration( void CreateRegistrationTask::DidStoreMetadata(ServiceWorkerStatusCode status) {
ServiceWorkerStatusCode status) {
DCHECK(registration_); DCHECK(registration_);
switch (ToDatabaseStatus(status)) { switch (ToDatabaseStatus(status)) {
......
...@@ -40,11 +40,11 @@ class CreateRegistrationTask : public DatabaseTask { ...@@ -40,11 +40,11 @@ class CreateRegistrationTask : public DatabaseTask {
void DidGetUniqueId(const std::vector<std::string>& data, void DidGetUniqueId(const std::vector<std::string>& data,
ServiceWorkerStatusCode status); ServiceWorkerStatusCode status);
void StoreRegistration(); void StoreMetadata();
void DidStoreRegistration(ServiceWorkerStatusCode status); void DidStoreMetadata(ServiceWorkerStatusCode status);
proto::BackgroundFetchRegistration CreateRegistrationProto() const; proto::BackgroundFetchMetadata CreateMetadataProto() const;
BackgroundFetchRegistrationId registration_id_; BackgroundFetchRegistrationId registration_id_;
std::vector<ServiceWorkerFetchRequest> requests_; std::vector<ServiceWorkerFetchRequest> requests_;
......
...@@ -68,12 +68,13 @@ void DeleteRegistrationTask::DidGetRegistration( ...@@ -68,12 +68,13 @@ void DeleteRegistrationTask::DidGetRegistration(
#if DCHECK_IS_ON() #if DCHECK_IS_ON()
if (ToDatabaseStatus(status) == DatabaseStatus::kOk) { if (ToDatabaseStatus(status) == DatabaseStatus::kOk) {
DCHECK_EQ(1u, data.size()); DCHECK_EQ(1u, data.size());
proto::BackgroundFetchRegistration registration_proto; proto::BackgroundFetchMetadata metadata_proto;
if (registration_proto.ParseFromString(data[0]) && if (metadata_proto.ParseFromString(data[0]) &&
registration_proto.has_developer_id()) { metadata_proto.registration().has_developer_id()) {
service_worker_context()->GetRegistrationUserData( service_worker_context()->GetRegistrationUserData(
service_worker_registration_id_, service_worker_registration_id_,
{ActiveRegistrationUniqueIdKey(registration_proto.developer_id())}, {ActiveRegistrationUniqueIdKey(
metadata_proto.registration().developer_id())},
base::BindOnce(&DCheckRegistrationNotActive, unique_id_)); base::BindOnce(&DCheckRegistrationNotActive, unique_id_));
} else { } else {
NOTREACHED() NOTREACHED()
......
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
#include <utility> #include <utility>
#include "content/browser/background_fetch/background_fetch.pb.h"
#include "content/browser/background_fetch/storage/database_helpers.h" #include "content/browser/background_fetch/storage/database_helpers.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h" #include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "url/gurl.h" #include "url/gurl.h"
...@@ -87,31 +86,44 @@ void GetRegistrationTask::DidGetRegistration( ...@@ -87,31 +86,44 @@ void GetRegistrationTask::DidGetRegistration(
} }
} }
void GetRegistrationTask::CreateRegistration( void GetRegistrationTask::InitializeRegistration(
const std::string& registration_data) { const proto::BackgroundFetchRegistration& registration_proto,
proto::BackgroundFetchRegistration registration_proto; BackgroundFetchRegistration* registration) {
if (!registration_proto.ParseFromString(registration_data)) { DCHECK(registration);
// per-registration data.
registration->developer_id = registration_proto.developer_id();
registration->unique_id = registration_proto.unique_id();
// Download/Upload stats.
registration->upload_total = registration_proto.upload_total();
registration->uploaded = registration_proto.uploaded();
registration->download_total = registration_proto.download_total();
registration->downloaded = registration_proto.downloaded();
}
void GetRegistrationTask::CreateRegistration(const std::string& metadata) {
proto::BackgroundFetchMetadata metadata_proto;
if (!metadata_proto.ParseFromString(metadata)) {
std::move(callback_).Run(blink::mojom::BackgroundFetchError::STORAGE_ERROR, std::move(callback_).Run(blink::mojom::BackgroundFetchError::STORAGE_ERROR,
nullptr /* registration */); nullptr /* registration */);
Finished(); Finished();
return; return;
} }
auto registration = std::make_unique<BackgroundFetchRegistration>(); const auto& registration_proto = metadata_proto.registration();
if (registration_proto.developer_id() != developer_id_ || if (registration_proto.developer_id() != developer_id_ ||
!origin_.IsSameOriginWith( !origin_.IsSameOriginWith(
url::Origin::Create(GURL(registration_proto.origin())))) { url::Origin::Create(GURL(metadata_proto.origin())))) {
std::move(callback_).Run(blink::mojom::BackgroundFetchError::STORAGE_ERROR, std::move(callback_).Run(blink::mojom::BackgroundFetchError::STORAGE_ERROR,
nullptr /* registration */); nullptr /* registration */);
Finished(); Finished();
return; return;
} }
registration->developer_id = registration_proto.developer_id(); // TODO(rayankans): Initialize all the other parts of the metadata.
registration->unique_id = registration_proto.unique_id(); auto registration = std::make_unique<BackgroundFetchRegistration>();
InitializeRegistration(metadata_proto.registration(), registration.get());
// TODO(delphick): Initialize all the other parts of the registration once
// they're persisted.
std::move(callback_).Run(blink::mojom::BackgroundFetchError::NONE, std::move(callback_).Run(blink::mojom::BackgroundFetchError::NONE,
std::move(registration)); std::move(registration));
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <vector> #include <vector>
#include "base/callback_forward.h" #include "base/callback_forward.h"
#include "content/browser/background_fetch/background_fetch.pb.h"
#include "content/browser/background_fetch/storage/database_task.h" #include "content/browser/background_fetch/storage/database_task.h"
#include "content/common/service_worker/service_worker_status_code.h" #include "content/common/service_worker/service_worker_status_code.h"
#include "url/origin.h" #include "url/origin.h"
...@@ -43,7 +44,11 @@ class GetRegistrationTask : public DatabaseTask { ...@@ -43,7 +44,11 @@ class GetRegistrationTask : public DatabaseTask {
void DidGetRegistration(const std::vector<std::string>& data, void DidGetRegistration(const std::vector<std::string>& data,
ServiceWorkerStatusCode status); ServiceWorkerStatusCode status);
void CreateRegistration(const std::string& registration_data); void InitializeRegistration(
const proto::BackgroundFetchRegistration& registration_proto,
BackgroundFetchRegistration* registration);
void CreateRegistration(const std::string& metadata);
int64_t service_worker_registration_id_; int64_t service_worker_registration_id_;
url::Origin origin_; url::Origin origin_;
......
...@@ -64,9 +64,9 @@ void MarkRegistrationForDeletionTask::DidGetActiveUniqueId( ...@@ -64,9 +64,9 @@ void MarkRegistrationForDeletionTask::DidGetActiveUniqueId(
return; return;
} }
proto::BackgroundFetchRegistration registration_proto; proto::BackgroundFetchMetadata metadata_proto;
if (registration_proto.ParseFromString(data[1]) && if (metadata_proto.ParseFromString(data[1]) &&
registration_proto.has_creation_microseconds_since_unix_epoch()) { metadata_proto.has_creation_microseconds_since_unix_epoch()) {
// Mark registration as no longer active. Also deletes pending request // Mark registration as no longer active. Also deletes pending request
// keys, since those are globally sorted and requests within deactivated // keys, since those are globally sorted and requests within deactivated
// registrations are no longer eligible to be started. Pending request // registrations are no longer eligible to be started. Pending request
...@@ -75,7 +75,7 @@ void MarkRegistrationForDeletionTask::DidGetActiveUniqueId( ...@@ -75,7 +75,7 @@ void MarkRegistrationForDeletionTask::DidGetActiveUniqueId(
registration_id_.service_worker_registration_id(), registration_id_.service_worker_registration_id(),
{ActiveRegistrationUniqueIdKey(registration_id_.developer_id()), {ActiveRegistrationUniqueIdKey(registration_id_.developer_id()),
PendingRequestKeyPrefix( PendingRequestKeyPrefix(
registration_proto.creation_microseconds_since_unix_epoch(), metadata_proto.creation_microseconds_since_unix_epoch(),
registration_id_.unique_id())}, registration_id_.unique_id())},
base::Bind(&MarkRegistrationForDeletionTask::DidDeactivate, base::Bind(&MarkRegistrationForDeletionTask::DidDeactivate,
weak_factory_.GetWeakPtr())); weak_factory_.GetWeakPtr()));
......
...@@ -60,19 +60,19 @@ void UpdateRegistrationUITask::DidGetUniqueId( ...@@ -60,19 +60,19 @@ void UpdateRegistrationUITask::DidGetUniqueId(
} }
void UpdateRegistrationUITask::UpdateUI( void UpdateRegistrationUITask::UpdateUI(
const std::string& serialized_registration_proto) { const std::string& serialized_metadata_proto) {
proto::BackgroundFetchRegistration registration_proto; proto::BackgroundFetchMetadata metadata_proto;
if (!registration_proto.ParseFromString(serialized_registration_proto)) { if (!metadata_proto.ParseFromString(serialized_metadata_proto)) {
std::move(callback_).Run(blink::mojom::BackgroundFetchError::STORAGE_ERROR); std::move(callback_).Run(blink::mojom::BackgroundFetchError::STORAGE_ERROR);
Finished(); // Destroys |this|. Finished(); // Destroys |this|.
return; return;
} }
registration_proto.set_title(updated_title_); metadata_proto.set_ui_title(updated_title_);
service_worker_context()->StoreRegistrationUserData( service_worker_context()->StoreRegistrationUserData(
service_worker_registration_id_, origin_.GetURL(), service_worker_registration_id_, origin_.GetURL(),
{{RegistrationKey(unique_id_), registration_proto.SerializeAsString()}}, {{RegistrationKey(unique_id_), metadata_proto.SerializeAsString()}},
base::BindRepeating(&UpdateRegistrationUITask::DidUpdateUI, base::BindRepeating(&UpdateRegistrationUITask::DidUpdateUI,
weak_factory_.GetWeakPtr())); weak_factory_.GetWeakPtr()));
} }
......
...@@ -38,7 +38,7 @@ class UpdateRegistrationUITask : public DatabaseTask { ...@@ -38,7 +38,7 @@ class UpdateRegistrationUITask : public DatabaseTask {
void DidGetUniqueId(const std::vector<std::string>& data, void DidGetUniqueId(const std::vector<std::string>& data,
ServiceWorkerStatusCode status); ServiceWorkerStatusCode status);
void UpdateUI(const std::string& serialized_registration_proto); void UpdateUI(const std::string& serialized_metadata_proto);
void DidUpdateUI(ServiceWorkerStatusCode status); void DidUpdateUI(ServiceWorkerStatusCode status);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment