blob: af42067c7d1585cd3bcca17d06340676804f0cef [file] [log] [blame]
// 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 <map>
#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 "components/browser_context_keyed_service/browser_context_keyed_service.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 Extension;
}
namespace user_prefs {
class PrefRegistrySyncable;
}
namespace gcm {
class GCMEventRouter;
class GCMProfileServiceTest;
// Acts as a bridge between GCM API and GCMClient layer. It is profile based.
class GCMProfileService : public BrowserContextKeyedService,
public content::NotificationObserver {
public:
typedef base::Callback<void(const std::string& registration_id,
GCMClient::Result result)> RegisterCallback;
typedef base::Callback<void(const std::string& message_id,
GCMClient::Result result)> SendCallback;
// For testing purpose.
class TestingDelegate {
public:
virtual GCMEventRouter* GetEventRouter() const = 0;
virtual void CheckInFinished(const GCMClient::CheckInInfo& checkin_info,
GCMClient::Result result) = 0;
virtual void LoadingFromPersistentStoreFinished() = 0;
};
// Returns true if the GCM support is enabled.
static bool IsGCMEnabled();
// Register profile-specific prefs for GCM.
static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
explicit GCMProfileService(Profile* profile);
// Constructor for testing purpose.
GCMProfileService(Profile* profile, TestingDelegate* testing_delegate);
virtual ~GCMProfileService();
// Registers |sender_id| for an app. A registration ID will be returned by
// the GCM server.
// |app_id|: application ID.
// |cert|: SHA-1 of public key of the application, in base16 format.
// |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<std::string>& sender_ids,
const std::string& cert,
RegisterCallback 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);
protected:
// Flag that could be set by the testing code to enable GCM. Otherwise,
// tests from official build will fail.
static bool enable_gcm_for_testing_;
private:
friend class GCMProfileServiceTest;
friend class GCMProfileServiceRegisterTest;
FRIEND_TEST_ALL_PREFIXES(GCMProfileServiceTest, CheckInFromPrefsStore);
FRIEND_TEST_ALL_PREFIXES(GCMProfileServiceTest, CheckOut);
FRIEND_TEST_ALL_PREFIXES(GCMProfileServiceRegisterTest, Unregister);
class IOWorker;
struct RegistrationInfo {
RegistrationInfo();
~RegistrationInfo();
std::vector<std::string> sender_ids;
std::string registration_id;
};
// Overridden from content::NotificationObserver:
virtual void Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) OVERRIDE;
void Init();
// Allows a signed-in user to use the GCM. If the check-in info can be found
// in the prefs store, use it directly. Otherwise, a check-in communication
// will be made with the GCM.
void AddUser();
// Stops the user from using the GCM after the user signs out. This simply
// removes the cached and persisted check-in info.
void RemoveUser();
// Unregisters an app from using the GCM after it has been uninstalled.
void Unregister(const std::string& app_id);
void CheckInFinished(GCMClient::CheckInInfo checkin_info,
GCMClient::Result result);
void RegisterFinished(std::string app_id,
std::string registration_id,
GCMClient::Result result);
void SendFinished(std::string app_id,
std::string message_id,
GCMClient::Result result);
void MessageReceived(std::string app_id,
GCMClient::IncomingMessage message);
void MessagesDeleted(std::string app_id);
void MessageSendError(std::string app_id,
std::string message_id,
GCMClient::Result result);
// Returns the event router to fire the event for the given app.
GCMEventRouter* GetEventRouter(const std::string& app_id);
// Used to persist registration info into the app's state store.
void DeleteRegistrationInfo(const std::string& app_id);
void WriteRegistrationInfo(const std::string& app_id);
void ReadRegistrationInfo(const std::string& app_id);
void ReadRegistrationInfoFinished(std::string app_id,
scoped_ptr<base::Value> value);
bool ParsePersistedRegistrationInfo(scoped_ptr<base::Value> value,
RegistrationInfo* registration_info);
// Returns the key used to identify the registration info saved into the
// app's state store. Used for testing purpose.
static const char* GetPersistentRegisterKeyForTesting();
// The profile which owns this object.
Profile* profile_;
// The username of the signed-in profile.
std::string username_;
content::NotificationRegistrar registrar_;
// For all the work occured in IO thread.
scoped_refptr<IOWorker> io_worker_;
// Callback map (from app_id to callback) for Register.
std::map<std::string, RegisterCallback> register_callbacks_;
// Callback map (from <app_id, message_id> to callback) for Send.
std::map<std::pair<std::string, std::string>, SendCallback> send_callbacks_;
// Map from app_id to registration info (sender ids & registration ID).
typedef std::map<std::string, RegistrationInfo> RegistrationInfoMap;
RegistrationInfoMap registration_info_map_;
// Event router to talk with JS API.
scoped_ptr<GCMEventRouter> js_event_router_;
// For testing purpose.
TestingDelegate* testing_delegate_;
// Used to pass a weak pointer to the IO worker.
base::WeakPtrFactory<GCMProfileService> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(GCMProfileService);
};
} // namespace gcm
#endif // CHROME_BROWSER_SERVICES_GCM_GCM_PROFILE_SERVICE_H_