blob: 72a838efc43e508d055344ce8653021d55e205ca [file] [log] [blame]
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_INVALIDATION_IMPL_INVALIDATOR_REGISTRAR_WITH_MEMORY_H_
#define COMPONENTS_INVALIDATION_IMPL_INVALIDATOR_REGISTRAR_WITH_MEMORY_H_
#include <map>
#include <optional>
#include <set>
#include <string>
#include "base/feature_list.h"
#include "base/memory/raw_ptr.h"
#include "base/observer_list.h"
#include "base/sequence_checker.h"
#include "components/invalidation/public/invalidation_export.h"
#include "components/invalidation/public/invalidation_handler.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
class PrefRegistrySimple;
class PrefService;
namespace invalidation {
class Invalidation;
// A helper class for FCMInvalidationService. It helps keep track of registered
// handlers and which topic registrations are associated with each handler.
class INVALIDATION_EXPORT InvalidatorRegistrarWithMemory {
public:
InvalidatorRegistrarWithMemory(PrefService* prefs,
const std::string& sender_id);
InvalidatorRegistrarWithMemory(const InvalidatorRegistrarWithMemory& other) =
delete;
InvalidatorRegistrarWithMemory& operator=(
const InvalidatorRegistrarWithMemory& other) = delete;
// It is an error to have registered handlers on destruction.
~InvalidatorRegistrarWithMemory();
// RegisterProfilePrefs and RegisterPrefs register the same prefs, because on
// device level (sign in screen, device local account) we spin up separate
// InvalidationService and on profile level (when user signed in) we have
// another InvalidationService, and we want to keep profile data in an
// encrypted area of disk. While device data which is public can be kept in an
// unencrypted area.
static void RegisterProfilePrefs(PrefRegistrySimple* registry);
static void RegisterPrefs(PrefRegistrySimple* registry);
// Starts sending notifications to |handler|. |handler| must not be nullptr,
// and it must not already be registered.
void AddObserver(InvalidationHandler* handler);
bool HasObserver(const InvalidationHandler* handler) const;
// Stops sending notifications to |handler|. |handler| must not be nullptr,
// and it must already be registered. Note that this doesn't unregister the
// topics associated with |handler| from the server.
void RemoveObserver(const InvalidationHandler* handler);
// Updates the set of topics associated with |handler|. |handler| must not be
// nullptr, and must already be registered. A topic must be registered for at
// most one handler. If any of the |topics| is already registered to a
// different handler, returns false. Note that this also updates the
// *subscribed* topics - assuming that whoever called this will also send
// (un)subscription requests to the server. However, this method does *not*
// unsubscribe from the topics which were not registered since browser
// startup.
[[nodiscard]] bool UpdateRegisteredTopics(InvalidationHandler* handler,
const TopicMap& topics);
// Returns all topics currently registered to |handler|.
TopicMap GetRegisteredTopics(InvalidationHandler* handler) const;
// Returns the set of all topics that (we think) we are subscribed to on the
// server. This is the set of topics which were registered to some handler and
// not unregistered (via UpdateRegisteredTopics()). This includes topics whose
// *handler* has been unregistered without unregistering the topic itself
// first (e.g. because Chrome was restarted and the handler hasn't registered
// itself again yet).
TopicMap GetAllSubscribedTopics() const;
// Dispatches incoming invalidation to the corresponding handler based on its
// topic.
// Invalidations for topics with no corresponding handler are returned.
std::optional<Invalidation> DispatchInvalidationToHandlers(
const Invalidation& invalidation);
// Dispatches a notification that the client has successfully subscribed to
// `topic` to handlers.
void DispatchSuccessfullySubscribedToHandlers(const Topic& topic);
// Updates the invalidator state to the given one and then notifies
// all handlers. Note that the order is important; handlers that
// call GetInvalidatorState() when notified will see the new state.
void UpdateInvalidatorState(InvalidatorState state);
// Returns the current invalidator state. When called from within
// InvalidationHandler::OnInvalidatorStateChange(), this returns the
// updated state.
InvalidatorState GetInvalidatorState() const;
private:
// Checks if any of the |new_topics| is already registered for a *different*
// handler than the given one.
bool HasDuplicateTopicRegistration(InvalidationHandler* handler,
const TopicMap& new_topics) const;
SEQUENCE_CHECKER(sequence_checker_);
base::ObserverList<InvalidationHandler, true> handlers_;
// Note: When a handler is unregistered, its entry is removed from
// |registered_handler_to_topics_map_| but NOT from
// |handler_name_to_subscribed_topics_map_|.
std::map<InvalidationHandler*, TopicMap, std::less<>>
registered_handler_to_topics_map_;
std::map<std::string, TopicMap> handler_name_to_subscribed_topics_map_;
InvalidatorState state_;
// This can be either a regular (Profile-attached) PrefService or the local
// state PrefService.
const raw_ptr<PrefService> prefs_;
// The FCM sender ID.
const std::string sender_id_;
};
} // namespace invalidation
#endif // COMPONENTS_INVALIDATION_IMPL_INVALIDATOR_REGISTRAR_WITH_MEMORY_H_