README.md
1# Invalidations Component
2
3## Introduction
4Let's start with an example. On Chrome OS there exists a concept called
5"policy" - one can think of them as dynamic flags that change Chrome's
6behaviour. They are changed on the Admin Panel from where they get propagated
7to Chrome OS devices. There is a scheduled "poll job" that fetches those
8policies every N hours, but preferably we would like to have the latest policy
9in matter of minutes/seconds. We could shorten the polling interval to 1
10minute, but that would put a very high unnecessary load on the servers. To
11solve this problem we introduce a concept called "invalidation" where the server
12notifies the devices when their policy changes and then they fetch the new
13policy - note that this way the devices only fetch the policy when needed.
14
15Invalidation Service - the word comes from cache invalidation. Imagine you have
16a database which has some objects in it. Cache is just a quick access copy of
17those objects. When an object changes in the database so should the copy of that
18object in cache.
19
20If we consider the client device as a cache then whenever some object changes in
21the server, so should the copy of this object in the client device. All the
22invalidation related interaction between client device and server is done
23through Invalidation Service.
24
25An **Invalidation** (a message to invalidate some object) is sent and received
26using a publish/subscribe service. In practice, this is Firebase Cloud Messaging
27(FCM, see
28[firebase.google.com/docs/cloud-messaging](https://firebase.google.com/docs/cloud-messaging)
29or [go/fcm](http://go/fcm)) and Fandango (see
30[go/fandango](http://go/fandango)).
31
32In general the whole thing looks as follows:
33![Invalidations component UML](../images/InvalidationService.png)
34
35***
36
37## Terminology
38
39* **InstanceID**: An identifier for "a specific app installed on a specific
40 device". The term comes from GMSCore on Android. Here, an "app" is a client of
41 invalidations, such as Sync, Drive, or Policy. It's just a mostly random
42 string of 8 bytes, created by Chrome.
43* **Registration**: As in "registering with FCM"; means making an InstanceID
44 known to the FCM server. The result of registering is an **InstanceID token**
45 (note that this is different from an InstanceID).
46* **Topic**: A "namespace" or "channel" of messages that clients can subscribe
47 to. For Sync, they correspond to data types. A topic can be either private
48 (i.e. GAIA-keyed) or public. For private topics, a unique ID derived from the
49 user's GAIA ID is appended to the topic name to make it unique (though this
50 is an implementation detail which is hidden from clients).
51* **Subscription**: As in "subscribing to a topic", i.e. telling the server that
52 this client (identified by InstanceID token) is interested in a given topic.
53* **ProjectID** (aka **SenderID**): An ID from the Google Cloud Platform console
54 that identifies a client of invalidations (such as Sync, Drive, or Policy).
55 E.g. for Sync its value is kInvalidationGCMSenderId. Note that (as opposed to
56 InstanceID) this is constant across all users and Chrome instances.
57
58***
59
60## Classes
61
62### InvalidationHandler
63
64An **InvalidationHandler** is a client (receiver) of Invalidations. Every
65feature that wants to receive Invalidations needs to implement an
66InvalidationHandler and register it with InvalidationService (see below).
67InvalidationHandler has the following methods (the list is not exhaustive):
68
69* **OnIncomingInvalidation** is called from InvalidationService to notify
70about incoming Invalidation messages.
71* **GetOwnerName** must return a unique name for this InvalidationHandler.
72
73***
74
75### InvalidationService
76
77**InvalidationService** is the main entry point for clients of the Invalidations
78system. This is where an InvalidationHandler registers/unregisters itself, and
79where it registers the Topics it is interested in. When a message arrives,
80InvalidationService calls OnIncomingInvalidation for the receiving
81InvalidationHandler.
82
83InvalidationService provides the following methods (the list is not exhaustive):
84
85* **RegisterInvalidationHandler** allows an InvalidationHandler to register
86itself as a observer for Invalidations. InvalidationService will only
87dispatch messages to registered handlers.
88* **UpdateInterestedTopics** allows InvalidationHandler to change the set of
89Topics it is interested in.
90* **UnregisterInvalidationHandler** lets an InvalidationHandler unregister
91itself again, after which it stops receiving Invalidations.
92
93An InvalidationService instance is usually tied to a profile (via
94**ProfileInvalidationProviderFactory**), but on ChromeOS there is also a
95device-scoped instance, managed by **AffiliatedInvalidationServiceProvider**
96(used for device policies, which must apply even before any user is signed in).
97
98***
99
100### FCMInvalidationService
101
102**FCMInvalidationService** is the only real (non-test) implementation of
103InvalidationService, using [FCM](http://go/fcm)+[Fandango](http://go/fandango)
104as its publish/subscribe service. It delegates most of the work to
105InvalidatorRegistrarWithMemory and FCMInvalidationListener.
106
107***
108
109### InvalidatorRegistrarWithMemory
110
111**InvalidatorRegistrarWithMemory** maintains the mapping between Topics and
112InvalidationHandlers. When a message arrives via FCMInvalidationListener,
113InvalidatorRegistrarWithMemory dispatches that message (invalidation) to the
114appropriate InvalidationHandler.
115
116InvalidatorRegistrarWithMemory also persists the set of Topics per handler, to
117avoid redundant re-subscriptions after every Chrome restart.
118
119***
120
121### FCMInvalidationListener
122
123**FCMInvalidationListener** gets the list of interesting Topics from
124FCMInvalidationService. It passes the Topics to PerUserTopicSubscriptionManager
125(see below) for subscription/unsubscription, receives Invalidation messages from
126FCMNetworkHandler, and passes Invalidations for the interesting Topics back to
127FCMInvalidationService.
128
129***
130
131### PerUserTopicSubscriptionManager
132
133**PerUserTopicSubscriptionManager** manages subscriptions to Topics, sending
134subscription or unsubscriptions requests to the server as necessary. It persists
135the set of subscribed Topics in prefs to avoid redundant re-subscriptions after
136Chrome restarts.
137
138***
139
140### FCMNetworkHandler
141
142**FCMNetworkHandler** is responsible for communication via GCM channel. It
143provides the following functionality:
144
145* Retrieves the InstanceID token required for the subscription. When this token
146 is received, it is passed to PerUserTopicSubscriptionManager which subscribes
147 to Topics with the given token.
148* Receives messages from GCM driver and passes them up to
149 FCMInvalidationListener, where they are converted to Invalidations.
150