blob: f73dc0c139654716038a4155c0dd87142ef34edf [file] [log] [blame]
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
syntax = "proto3";
package feedstore;
import "components/feed/core/proto/v2/wire/content_id.proto";
import "components/feed/core/proto/v2/wire/feed_action.proto";
import "components/feed/core/proto/v2/wire/stream_structure.proto";
import "components/feed/core/proto/v2/wire/web_feed_matcher.proto";
import "components/feed/core/proto/v2/wire/web_feeds.proto";
option optimize_for = LITE_RUNTIME;
// Actual data stored by the client.
// This data is sourced from the wire protocol, which is converted upon receipt.
//
// This is the 'value' in the key/value store.
// Keys are defined as:
// [Key format] -> [Record field]
// S/<stream-key> -> stream_data
// T/<stream-key>/<sequence-number> -> stream_structures
// c/<stream-key>/<content-id> -> content
// s/<stream-key>/<content-id> -> shared_state
// a/<action-id> -> action
// m -> metadata
// subs -> subscribed_web_feeds
// recommendedIndex -> recommended_web_feed_index
// R/<web_feed_id> -> recommended_web_feed
// W/<operation-id> -> pending_web_feed_operation
// v/<docid>/<timestamp> -> docview
message Record {
oneof data {
StreamData stream_data = 1;
StreamStructureSet stream_structures = 2;
Content content = 3;
StoredAction local_action = 4;
StreamSharedState shared_state = 5;
Metadata metadata = 6;
SubscribedWebFeeds subscribed_web_feeds = 7;
WebFeedInfo recommended_web_feed = 8;
RecommendedWebFeedIndex recommended_web_feed_index = 9;
PendingWebFeedOperation pending_web_feed_operation = 10;
DocView doc_view = 11;
}
}
// List of the hashes for all the contents in a collection (carousel, list,
// or 2-column) if multiple items show up in a row. Otherwise, it just contain
// a single hash value.
message StreamContentHashList {
// The hash of the content URL.
repeated uint32 hashes = 1;
}
// Data about the Feed stream. There is at most one instance of StreamData.
message StreamData {
// Root ContentId, as provided by the server.
feedwire.ContentId content_id = 1;
// Token used to request a 'more' request to the server.
bytes next_page_token = 2;
// The unix timestamp in milliseconds that the most recent content was added.
int64 last_added_time_millis = 4;
// The content IDs of the shared state for this stream.
repeated feedwire.ContentId shared_state_ids = 6;
// Was this feed signed in.
bool signed_in = 7;
// If signed_in, this is the account gaia tied to this stream data.
string gaia = 13;
// If signed_in, this is the account email tied to this stream data.
string email = 14;
// Is activity logging enabled?
bool logging_enabled = 8;
// Has the privacy notice been fulfilled?
bool privacy_notice_fulfilled = 9;
// Stream ID. Should match the id value stored in the record's key.
string stream_key = 10;
// List of hashes for all the contents contained in the stream.
repeated StreamContentHashList content_hashes = 11;
// Root EventID provided by the server.
bytes root_event_id = 12;
reserved 3, 5, 15;
}
// Data that doesn't belong to a stream.
message Metadata {
// Session identifier used for signed-out feed requests and interactions.
message SessionID {
string token = 1;
int64 expiry_time_ms = 2;
}
// Metadata about a specific stream.
message StreamMetadata {
string stream_key = 1;
// Whether the stream data is known to be stale. This can happen in the
// WebFeed stream if the subscription list changes.
bool is_known_stale = 3;
// If this stream has been viewed before, this is the list of content in the
// stream (`StreamData.content_hashes`). This is used to determine whether
// the user has already seen a stored stream's data.
repeated StreamContentHashList view_content_hashes = 4;
message ContentLifetime {
int64 stale_age_ms = 1;
int64 invalid_age_ms = 2;
}
ContentLifetime content_lifetime = 5;
// The unix timestamp in milliseconds that the stream was fetched last time.
int64 last_fetch_time_millis = 6;
// The unix timestamp in milliseconds that the feed response is produced on
// the server. This is returned from the server and based on server clock.
int64 last_server_response_time_millis = 7;
// List of IDs of contents that have been viewed by the user. A content is
// viewed if 2/3rds of it is in the viewport.
repeated uint32 viewed_content_hashes = 8;
reserved 2;
}
// Token used to read or write to the same storage.
bytes consistency_token = 1;
// ID for the next pending action.
int32 next_action_id = 2;
// The most recent session identifier.
SessionID session_id = 3;
// Schema version number. Schema versions:
// 0: Initial version.
// 1: Current version. Added <stream-key> to the key patterns of "content" and
// "shared_state"
// records.
int32 stream_schema_version = 4;
repeated StreamMetadata stream_metadata = 5;
// The GAIA ID associated with the store.
string gaia = 6;
// Whether WAA is enabled for this user, as reported by the last FeedQuery
// response.
bool web_and_app_activity_enabled = 7;
// Whether personalization is enabled for Discover, as reported by the last
// FeedQuery response.
bool discover_personalization_enabled = 8;
// Count of how many times the user has followed from the main menu, so we
// can show appropriate user education help for the following feed.
int32 followed_from_web_page_menu_count = 9;
// The list of IDs representing the most recent contents viewed by the user.
// The size of the list is capped to
// feedstore_util::kMaxMostRecentContentHashes. The IDs are stored in the
// ascending order of the time when the content is viewed by the user.
repeated uint32 most_recent_viewed_content_hashes = 11;
reserved 10;
}
// A set of StreamStructures that should be applied to a stream.
message StreamStructureSet {
// Stream ID. Should match the id value stored in the record's key.
string stream_key = 1;
int32 sequence_number = 2;
repeated StreamStructure structures = 3;
}
// This is the structure of the stream. It is defined through the parent/child
// relationship and an operation. This message will be journaled. Reading
// the journal from start to end will fully define the structure of the stream.
message StreamStructure {
// The defined set of DataOperations
// These operations align with the Operation enum defined in
// data_operation.proto.
enum Operation {
UNKNOWN = 0;
// Clear all the content in the session, creating a new session
CLEAR_ALL = 1;
// Append if not present or update
UPDATE_OR_APPEND = 2;
// Remove the node from its parent
REMOVE = 3;
}
Operation operation = 1;
// The ContentId of the content.
feedwire.ContentId content_id = 2;
// The parent ContentId, or unset if this is the root.
feedwire.ContentId parent_id = 3;
// Type of node as denoted by the server. This type has no meaning for the
// client.
enum Type {
// Default type for operations that don't affect the stream (e.g. operations
// on shared states).
UNKNOWN_TYPE = 0;
// The root of the stream.
STREAM = 1;
// An internal tree node, which may have children.
CARD = 2;
// A leaf node, which provides content.
CONTENT = 3;
// An internal tree node, which may have children.
GROUP = 4;
}
Type type = 4;
// Set iff type=CONTENT
ContentInfo content_info = 5;
// Is this the root of the stream?
bool is_root = 6;
}
message DataOperation {
StreamStructure structure = 1;
// Provided if structure adds content.
Content content = 2;
}
message ContentInfo {
// Score given by server.
float score = 1;
// Unix timestamp (seconds) that content was received by Chrome.
int64 availability_time_seconds = 2;
}
message Content {
feedwire.ContentId content_id = 1;
// Opaque content. The UI layer knows how to parse and render this as a slice.
bytes frame = 2;
repeated feedwire.PrefetchMetadata prefetch_metadata = 3;
// Stream ID. Should match the id value stored in the record's key.
string stream_key = 4;
}
// This represents a shared state item.
message StreamSharedState {
feedwire.ContentId content_id = 1;
// Opaque data required to render content.
bytes shared_state_data = 2;
// Stream ID. Should match the id value stored in the record's key.
string stream_key = 3;
}
// A stored action awaiting upload.
message StoredAction {
// Unique ID for this stored action, provided by the client.
// This is a sequential number, so that the action with the lowest id value
// was recorded chronologically first.
int32 id = 1;
// How many times we have tried to upload the action.
int32 upload_attempt_count = 2;
// The action to upload.
feedwire.FeedAction action = 3;
}
// List of web feeds for which the user is subscribed.
message SubscribedWebFeeds {
repeated WebFeedInfo feeds = 1;
// The unix timestamp in milliseconds that this data was updated from the
// server.
int64 update_time_millis = 2;
}
message RecommendedWebFeedIndex {
message Entry {
string web_feed_id = 1;
repeated feedwire.webfeed.WebFeedMatcher matchers = 2;
}
repeated Entry entries = 1;
// The unix timestamp in milliseconds that this data was updated from the
// server.
int64 update_time_millis = 2;
}
// Reference to an image.
message Image {
string url = 1;
}
// See http://go/chrome-web-feed-api.
message WebFeedInfo {
enum State {
STATE_UNSPECIFIED = 0;
INACTIVE = 1;
ACTIVE = 2;
WAITING_FOR_CONTENT = 4;
}
string web_feed_id = 1;
string title = 2;
string subtitle = 3;
string detail_text = 4;
string visit_uri = 5;
string rss_uri = 6;
Image favicon = 7;
int64 follower_count = 8;
State state = 9;
repeated feedwire.webfeed.WebFeedMatcher matchers = 10;
}
message PendingWebFeedOperation {
enum Kind {
KIND_UNSPECIFIED = 0;
SUBSCRIBE = 1;
UNSUBSCRIBE = 2;
}
// Unique ID, for sorting operations.
int64 id = 1;
// The operation kind.
Kind kind = 2;
// The web feed ID to either subscribe or unsubscribe.
string web_feed_id = 3;
// Number of times the operation has been attempted.
int32 attempts = 4;
// Reason for this change.
feedwire.webfeed.WebFeedChangeReason change_reason = 5;
}
message DocView {
// Unique ID for the content that was viewed.
uint64 docid = 1;
// Unix timestamp when the view occurred.
int64 view_time_millis = 4;
}