| // Copyright 2025 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef FUCHSIA_WEB_WEBENGINE_BROWSER_PUSH_MESSAGING_SERVICE_IMPL_H_ |
| #define FUCHSIA_WEB_WEBENGINE_BROWSER_PUSH_MESSAGING_SERVICE_IMPL_H_ |
| |
| #include <memory> |
| #include <optional> |
| |
| #include "base/sequence_checker.h" |
| #include "base/version_info/channel.h" |
| #include "components/gcm_driver/gcm_app_handler.h" |
| #include "components/gcm_driver/gcm_driver.h" |
| #include "components/gcm_driver/instance_id/instance_id.h" |
| #include "components/gcm_driver/instance_id/instance_id_driver.h" |
| #include "components/push_messaging/app_identifier.h" |
| #include "content/public/browser/browser_thread.h" |
| #include "content/public/browser/push_messaging_service.h" |
| |
| class GURL; |
| |
| namespace content { |
| class BrowserContext; |
| } // namespace content |
| |
| namespace os_crypt_async { |
| class OSCryptAsync; |
| } // namespace os_crypt_async |
| |
| namespace network { |
| class NetworkConnectionTracker; |
| } // namespace network |
| |
| // The PushMessagingService implementation dedicated for WebEngine since the |
| // //chrome/browser/push_messaging implementation uses Profile which is not a |
| // concept in //fuchsia_web. |
| // Most of the implementations are copied from |
| // //chrome/browser/push_messaging/push_messaging_service_impl but modified to |
| // fit the limits of WebEngine. |
| // |
| // The principle of this implementation is to ensure the WebAPI compatibility |
| // between a full functional Chrome and WebEngine. WebApp should function the |
| // same except for the designated specific behaviors in this implementation, |
| // e.g. no notification support; no per-profile messaging; no user controllable |
| // permission. |
| // |
| // TODO(crbug.com/424479300): Move more shared logic from |
| // //chrome/browser/push_messaging/ to //contents/browser/push_messaging/ and |
| // //components/push_messaging/ to reduce the duplications. |
| class PushMessagingServiceImpl final : public content::PushMessagingService, |
| public gcm::GCMAppHandler { |
| public: |
| PushMessagingServiceImpl(content::BrowserContext&, |
| os_crypt_async::OSCryptAsync&, |
| network::NetworkConnectionTracker&); |
| ~PushMessagingServiceImpl() override; |
| |
| // PushMessagingService implementations. |
| void SubscribeFromDocument(const GURL& origin, |
| int64_t service_worker_registration_id, |
| int render_process_id, |
| int render_frame_id, |
| blink::mojom::PushSubscriptionOptionsPtr options, |
| bool user_gesture, |
| RegisterCallback callback) override; |
| void SubscribeFromWorker(const GURL& origin, |
| int64_t service_worker_registration_id, |
| int render_process_id, |
| blink::mojom::PushSubscriptionOptionsPtr options, |
| RegisterCallback callback) override; |
| void GetSubscriptionInfo(const GURL& origin, |
| int64_t service_worker_registration_id, |
| const std::string& sender_id, |
| const std::string& subscription_id, |
| SubscriptionInfoCallback callback) override; |
| void Unsubscribe(blink::mojom::PushUnregistrationReason reason, |
| const GURL& origin, |
| int64_t service_worker_registration_id, |
| const std::string& sender_id, |
| UnregisterCallback callback) override; |
| bool SupportNonVisibleMessages() override; |
| void DidDeleteServiceWorkerRegistration( |
| const GURL& origin, |
| int64_t service_worker_registration_id) override; |
| void DidDeleteServiceWorkerDatabase() override; |
| |
| // GCMAppHandler implementations. |
| void ShutdownHandler() override; |
| void OnStoreReset() override; |
| void OnMessage(const std::string& app_id, |
| const gcm::IncomingMessage& message) override; |
| void OnMessagesDeleted(const std::string& app_id) override; |
| void OnSendError( |
| const std::string& app_id, |
| const gcm::GCMClient::SendErrorDetails& send_error_details) override; |
| void OnSendAcknowledged(const std::string& app_id, |
| const std::string& message_id) override; |
| bool CanHandle(const std::string& app_id) const override; |
| |
| private: |
| gcm::GCMDriver& GetGCMDriver(); |
| instance_id::InstanceIDDriver& GetInstanceIDDriver(); |
| |
| void RequestProxyResolvingSocketFactoryOnUIThread( |
| mojo::PendingReceiver<network::mojom::ProxyResolvingSocketFactory> |
| receiver); |
| |
| static void RequestProxyResolvingSocketFactory( |
| base::WeakPtr<PushMessagingServiceImpl> self, |
| mojo::PendingReceiver<network::mojom::ProxyResolvingSocketFactory> |
| receiver); |
| |
| scoped_refptr<network::SharedURLLoaderFactory> GetSharedURLLoaderFactory() |
| const; |
| |
| version_info::Channel GetChannel() const; |
| |
| std::string GetProductCategoryForSubtypes() const; |
| |
| // Shared implementation for both SubscribeFromDocument and |
| // SubscribeFromWorker. |
| void DoSubscribe(const GURL& origin, |
| int64_t service_worker_registration_id, |
| blink::mojom::PushSubscriptionOptionsPtr options, |
| RegisterCallback callback); |
| |
| void DidSubscribe(const push_messaging::AppIdentifier& app_identifier, |
| const std::string& sender_id, |
| RegisterCallback callback, |
| const std::string& subscription_id, |
| instance_id::InstanceID::Result result); |
| |
| // An O(N) search on all the subscriptions to find the match of |
| // |origin| and |service_worker_registration_id|. |
| std::optional<push_messaging::AppIdentifier> FindByServiceWorker( |
| const GURL& origin, |
| int64_t service_worker_registration_id) const; |
| |
| void DidSubscribeWithEncryptionInfo( |
| const push_messaging::AppIdentifier& app_identifier, |
| RegisterCallback callback, |
| const std::string& subscription_id, |
| const GURL& endpoint, |
| std::string p256dh, |
| std::string auth_secret); |
| |
| void Unsubscribe(const push_messaging::AppIdentifier& app_id, |
| blink::mojom::PushUnregistrationReason reason, |
| UnregisterCallback callback); |
| |
| void DidClearPushSubscriptionId(blink::mojom::PushUnregistrationReason reason, |
| const push_messaging::AppIdentifier& app_id, |
| UnregisterCallback callback); |
| |
| void DidDeleteID(const std::string& app_id, instance_id::InstanceID::Result); |
| // RemoveInstanceID must be run asynchronously, since it calls |
| // InstanceIDDriver::RemoveInstanceID which deletes the InstanceID itself. |
| // Calling that immediately would cause a use-after-free in our caller. |
| void RemoveInstanceID(const std::string& app_id); |
| |
| void DidUnsubscribe(gcm::GCMClient::Result); |
| |
| void DidValidateSubscription(const std::string& app_id, |
| const std::string& sender_id, |
| const GURL& endpoint, |
| const std::optional<base::Time>& expiration_time, |
| SubscriptionInfoCallback callback, |
| bool is_valid); |
| |
| void DidGetEncryptionInfo(const GURL& endpoint, |
| const std::optional<base::Time>& expiration_time, |
| SubscriptionInfoCallback callback, |
| std::string p256dh, |
| std::string auth_secret) const; |
| |
| void DidDeliverMessage(const push_messaging::AppIdentifier& app_id, |
| blink::mojom::PushEventStatus status); |
| |
| // Class variables |
| |
| // Lazy initialized. |
| std::unique_ptr<gcm::GCMDriver> gcm_driver_; |
| |
| // Lazy initialized. |
| std::unique_ptr<instance_id::InstanceIDDriver> instance_id_driver_; |
| |
| // Outlive this instance. |
| content::BrowserContext& parent_context_; |
| os_crypt_async::OSCryptAsync& os_crypt_async_; |
| network::NetworkConnectionTracker& network_connection_tracker_; |
| |
| // TODO(http://crbug.com/424479300): Implement the persistent storage of the |
| // |app_ids_|. |
| // |
| // map<app_id, AppIdentifier>, the AppIdentifier.app_id must match the map |
| // key. |
| std::unordered_map<std::string, push_messaging::AppIdentifier> app_ids_; |
| |
| // Number of on-the-fly subscriptions, i.e. DoSubscribe was called, but not |
| // DidSubscribe. |
| int pending_subscriptions_{0}; |
| |
| SEQUENCE_CHECKER(sequence_checker_); |
| |
| // Must be the last member variable. |
| base::WeakPtrFactory<PushMessagingServiceImpl> weak_ptr_factory_{this}; |
| }; |
| |
| #endif // FUCHSIA_WEB_WEBENGINE_BROWSER_PUSH_MESSAGING_SERVICE_IMPL_H_ |