// Copyright (c) 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef CHROME_BROWSER_SERVICES_GCM_GCM_PROFILE_SERVICE_H_ #define CHROME_BROWSER_SERVICES_GCM_GCM_PROFILE_SERVICE_H_ #include #include #include "base/basictypes.h" #include "base/callback.h" #include "base/compiler_specific.h" #include "base/gtest_prod_util.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "chrome/browser/services/gcm/default_gcm_app_handler.h" #include "components/keyed_service/core/keyed_service.h" #include "components/signin/core/browser/signin_manager_base.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" #include "google_apis/gcm/gcm_client.h" class Profile; namespace base { class Value; } namespace extensions { class ExtensionGCMAppHandlerTest; } namespace user_prefs { class PrefRegistrySyncable; } namespace gcm { class GCMAppHandler; class GCMClientFactory; class GCMProfileServiceTestConsumer; // Acts as a bridge between GCM API and GCMClient layer. It is profile based. class GCMProfileService : public KeyedService, public content::NotificationObserver, public SigninManagerBase::Observer { public: typedef base::Callback RegisterCallback; typedef base::Callback SendCallback; typedef base::Callback UnregisterCallback; typedef base::Callback RequestGCMStatisticsCallback; // Any change made to this enum should have corresponding change in the // GetGCMEnabledStateString(...) function. enum GCMEnabledState { // GCM is always enabled. GCMClient will always load and connect with GCM. ALWAYS_ENABLED, // GCM is only enabled for apps. GCMClient will start to load and connect // with GCM only when GCM API is used. ENABLED_FOR_APPS, // GCM is always disabled. GCMClient will never load and connect with GCM. ALWAYS_DISABLED }; // Returns the GCM enabled state. static GCMEnabledState GetGCMEnabledState(Profile* profile); // Returns text representation of a GCMEnabledState enum entry. static std::string GetGCMEnabledStateString(GCMEnabledState state); // Register profile-specific prefs for GCM. static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry); explicit GCMProfileService(Profile* profile); virtual ~GCMProfileService(); void Initialize(scoped_ptr gcm_client_factory); void Start(); void Stop(); // KeyedService implementation. virtual void Shutdown() OVERRIDE; // Adds a handler for a given app. virtual void AddAppHandler(const std::string& app_id, GCMAppHandler* handler); // Remove the handler for a given app. virtual void RemoveAppHandler(const std::string& app_id); // Registers |sender_id| for an app. A registration ID will be returned by // the GCM server. // |app_id|: application ID. // |sender_ids|: list of IDs of the servers that are allowed to send the // messages to the application. These IDs are assigned by the // Google API Console. // |callback|: to be called once the asynchronous operation is done. virtual void Register(const std::string& app_id, const std::vector& sender_ids, RegisterCallback callback); // Unregisters an app from using GCM. // |app_id|: application ID. // |callback|: to be called once the asynchronous operation is done. virtual void Unregister(const std::string& app_id, UnregisterCallback callback); // Sends a message to a given receiver. // |app_id|: application ID. // |receiver_id|: registration ID of the receiver party. // |message|: message to be sent. // |callback|: to be called once the asynchronous operation is done. virtual void Send(const std::string& app_id, const std::string& receiver_id, const GCMClient::OutgoingMessage& message, SendCallback callback); // For testing purpose. GCMClient* GetGCMClientForTesting() const; // Returns the user name if the profile is signed in. std::string SignedInUserName() const; // Returns true if the gcm client is ready. bool IsGCMClientReady() const; // Get GCM client internal states and statistics. If it has not been created // then stats won't be modified. void RequestGCMStatistics(RequestGCMStatisticsCallback callback); private: friend class GCMProfileServiceTestConsumer; friend class extensions::ExtensionGCMAppHandlerTest; class DelayedTaskController; class IOWorker; typedef std::map GCMAppHandlerMap; // Overridden from content::NotificationObserver: virtual void Observe(int type, const content::NotificationSource& source, const content::NotificationDetails& details) OVERRIDE; // Overridden from SigninManagerBase::Observer: virtual void GoogleSigninSucceeded(const std::string& username, const std::string& password) OVERRIDE; virtual void GoogleSignedOut(const std::string& username) OVERRIDE; // Ensures that the GCMClient is loaded and the GCM check-in is done when // the profile was signed in. void EnsureLoaded(); // Remove cached data when GCM service is stopped. void RemoveCachedData(); // Checks out of GCM when the profile has been signed out. This will erase // all the cached and persisted data. void CheckOut(); // Resets the GCMClient instance. This is called when the profile is being // destroyed. void ResetGCMClient(); // Ensures that the app is ready for GCM functions and events. GCMClient::Result EnsureAppReady(const std::string& app_id); // Should be called when an app with |app_id| is trying to un/register. // Checks whether another un/registration is in progress. bool IsAsyncOperationPending(const std::string& app_id) const; void DoRegister(const std::string& app_id, const std::vector& sender_ids); void DoUnregister(const std::string& app_id); void DoSend(const std::string& app_id, const std::string& receiver_id, const GCMClient::OutgoingMessage& message); // Callbacks posted from IO thread to UI thread. void RegisterFinished(const std::string& app_id, const std::string& registration_id, GCMClient::Result result); void UnregisterFinished(const std::string& app_id, GCMClient::Result result); void SendFinished(const std::string& app_id, const std::string& message_id, GCMClient::Result result); void MessageReceived(const std::string& app_id, GCMClient::IncomingMessage message); void MessagesDeleted(const std::string& app_id); void MessageSendError(const std::string& app_id, const GCMClient::SendErrorDetails& send_error_details); void GCMClientReady(); // Returns the handler for the given app. GCMAppHandler* GetAppHandler(const std::string& app_id); void RequestGCMStatisticsFinished(GCMClient::GCMStatistics stats); // The profile which owns this object. Profile* profile_; // Flag to indicate if GCMClient is ready. bool gcm_client_ready_; // The username of the signed-in profile. std::string username_; content::NotificationRegistrar registrar_; scoped_ptr delayed_task_controller_; // For all the work occured in IO thread. scoped_refptr io_worker_; // App handler map (from app_id to handler pointer). // The handler is not owned. GCMAppHandlerMap app_handlers_; // The default handler when no app handler can be found in the map. DefaultGCMAppHandler default_app_handler_; // Callback map (from app_id to callback) for Register. std::map register_callbacks_; // Callback map (from app_id to callback) for Unregister. std::map unregister_callbacks_; // Callback map (from to callback) for Send. std::map, SendCallback> send_callbacks_; // Callback for RequestGCMStatistics. RequestGCMStatisticsCallback request_gcm_statistics_callback_; // Used to pass a weak pointer to the IO worker. base::WeakPtrFactory weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(GCMProfileService); }; } // namespace gcm #endif // CHROME_BROWSER_SERVICES_GCM_GCM_PROFILE_SERVICE_H_