Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / services / gcm / gcm_profile_service.cc
index 77fabbc..0592b0c 100644 (file)
 
 #include "chrome/browser/services/gcm/gcm_profile_service.h"
 
-#include "base/base64.h"
+#include "base/files/file_path.h"
 #include "base/logging.h"
 #include "base/prefs/pref_service.h"
-#include "base/strings/string_number_conversions.h"
-#include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/extensions/extension_service.h"
-#include "chrome/browser/extensions/extension_system.h"
-#include "chrome/browser/extensions/state_store.h"
-#include "chrome/browser/services/gcm/gcm_client_factory.h"
-#include "chrome/browser/services/gcm/gcm_event_router.h"
-#include "chrome/browser/signin/signin_manager.h"
+#include "base/values.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/signin/profile_identity_provider.h"
+#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
+#include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_version_info.h"
 #include "chrome/common/pref_names.h"
+#include "components/signin/core/browser/signin_manager.h"
 #include "components/user_prefs/pref_registry_syncable.h"
-#include "components/webdata/encryptor/encryptor.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/notification_details.h"
-#include "content/public/browser/notification_source.h"
-#include "extensions/common/extension.h"
+#include "google_apis/gaia/identity_provider.h"
+#include "net/url_request/url_request_context_getter.h"
 
-using extensions::Extension;
+#if !defined(OS_ANDROID)
+#include "chrome/browser/ui/webui/signin/login_ui_service_factory.h"
+#endif
 
 namespace gcm {
 
-const char kRegistrationKey[] = "gcm.registration";
-const char kSendersKey[] = "senders";
-const char kRegistrationIDKey[] = "reg_id";
-
-// Helper class to save tasks to run until we're ready to execute them.
-class GCMProfileService::DelayedTaskController {
- public:
-  DelayedTaskController();
-  ~DelayedTaskController();
-
-  // Adds an app to the tracking list. It will be first marked as not ready.
-  // Tasks will be queued for delay execution until the app is marked as ready.
-  void AddApp(const std::string& app_id);
-
-  // Removes the app from the tracking list.
-  void RemoveApp(const std::string& app_id);
-
-  // Adds a task that will be invoked once we're ready.
-  void AddTask(const std::string& app_id, base::Closure task);
-
-  // Marks that GCMClient is ready.
-  void SetGCMClientReady();
-
-  // Marks that the app is ready to have operations performed.
-  void SetAppReady(const std::string& app_id);
-
-  // Returns true if it is ready to perform operations for an app.
-  bool CanRunTaskWithoutDelay(const std::string& app_id) const;
-
-  // Returns true if the app has been tracked for readiness.
-  bool IsAppTracked(const std::string& app_id) const;
-
- private:
-  struct AppTaskQueue {
-    AppTaskQueue();
-    ~AppTaskQueue();
-
-    // The flag that indicates if GCMProfileService completes loading the
-    // persistent data for the app.
-    bool ready;
-
-    // Tasks to be invoked upon ready.
-    std::vector<base::Closure> tasks;
-  };
-
-  void RunTasks(AppTaskQueue* task_queue);
-
-  // Flag that indicates that GCMClient is ready.
-  bool gcm_client_ready_;
-
-  // Map from app_id to callbacks.
-  typedef std::map<std::string, AppTaskQueue*> DelayedTaskMap;
-  DelayedTaskMap delayed_task_map_;
-};
-
-GCMProfileService::DelayedTaskController::AppTaskQueue::AppTaskQueue()
-    : ready(false) {
-}
-
-GCMProfileService::DelayedTaskController::AppTaskQueue::~AppTaskQueue() {
-}
-
-GCMProfileService::DelayedTaskController::DelayedTaskController()
-    : gcm_client_ready_(false) {
-}
-
-GCMProfileService::DelayedTaskController::~DelayedTaskController() {
-  for (DelayedTaskMap::const_iterator iter = delayed_task_map_.begin();
-       iter != delayed_task_map_.end(); ++iter) {
-    delete iter->second;
-  }
-}
-
-void GCMProfileService::DelayedTaskController::AddApp(
-    const std::string& app_id) {
-  DCHECK(delayed_task_map_.find(app_id) == delayed_task_map_.end());
-  delayed_task_map_[app_id] = new AppTaskQueue;
-}
-
-void GCMProfileService::DelayedTaskController::RemoveApp(
-    const std::string& app_id) {
-  delayed_task_map_.erase(app_id);
-}
-
-void GCMProfileService::DelayedTaskController::AddTask(
-    const std::string& app_id, base::Closure task) {
-  DelayedTaskMap::const_iterator iter = delayed_task_map_.find(app_id);
-  DCHECK(iter != delayed_task_map_.end());
-  iter->second->tasks.push_back(task);
-}
-
-void GCMProfileService::DelayedTaskController::SetGCMClientReady() {
-  gcm_client_ready_ = true;
-
-  for (DelayedTaskMap::iterator iter = delayed_task_map_.begin();
-       iter != delayed_task_map_.end();) {
-    if (iter->second->ready) {
-      AppTaskQueue* task_queue = iter->second;
-      RunTasks(task_queue);
-      delete task_queue;
-      delayed_task_map_.erase(iter++);
-    } else {
-      ++iter;
-    }
-  }
-}
-
-void GCMProfileService::DelayedTaskController::SetAppReady(
-    const std::string& app_id) {
-  DelayedTaskMap::iterator iter = delayed_task_map_.find(app_id);
-  DCHECK(iter != delayed_task_map_.end());
-
-  AppTaskQueue* task_queue = iter->second;
-  DCHECK(task_queue);
-  task_queue->ready = true;
-
-  if (gcm_client_ready_) {
-    RunTasks(task_queue);
-    delete task_queue;
-    delayed_task_map_.erase(iter);
-  }
-}
-
-bool GCMProfileService::DelayedTaskController::CanRunTaskWithoutDelay(
-    const std::string& app_id) const {
-  if (!gcm_client_ready_)
-    return false;
-  DelayedTaskMap::const_iterator iter = delayed_task_map_.find(app_id);
-  if (iter == delayed_task_map_.end())
-    return true;
-  return iter->second->ready;
-}
-
-bool GCMProfileService::DelayedTaskController::IsAppTracked(
-    const std::string& app_id) const {
-  return delayed_task_map_.find(app_id) != delayed_task_map_.end();
-}
-
-void GCMProfileService::DelayedTaskController::RunTasks(
-    AppTaskQueue* task_queue) {
-  DCHECK(gcm_client_ready_ && task_queue->ready);
-
-  for (size_t i = 0; i < task_queue->tasks.size(); ++i)
-    task_queue->tasks[i].Run();
-  task_queue->tasks.clear();
-}
-
-class GCMProfileService::IOWorker
-    : public GCMClient::Delegate,
-      public base::RefCountedThreadSafe<GCMProfileService::IOWorker>{
- public:
-  // Called on UI thread.
-  explicit IOWorker(const base::WeakPtr<GCMProfileService>& service);
-
-  // Overridden from GCMClient::Delegate:
-  // Called on IO thread.
-  virtual void OnCheckInFinished(const GCMClient::CheckinInfo& checkin_info,
-                                 GCMClient::Result result) OVERRIDE;
-  virtual void OnRegisterFinished(const std::string& app_id,
-                                  const std::string& registration_id,
-                                  GCMClient::Result result) OVERRIDE;
-  virtual void OnSendFinished(const std::string& app_id,
-                              const std::string& message_id,
-                              GCMClient::Result result) OVERRIDE;
-  virtual void OnMessageReceived(
-      const std::string& app_id,
-      const GCMClient::IncomingMessage& message) OVERRIDE;
-  virtual void OnMessagesDeleted(const std::string& app_id) OVERRIDE;
-  virtual void OnMessageSendError(const std::string& app_id,
-                                  const std::string& message_id,
-                                  GCMClient::Result result) OVERRIDE;
-  virtual GCMClient::CheckinInfo GetCheckinInfo() const OVERRIDE;
-  virtual void OnLoadingCompleted() OVERRIDE;
-
-  // Called on IO thread.
-  void Initialize();
-  void SetUser(const std::string& username);
-  void RemoveUser();
-  void CheckIn();
-  void SetCheckinInfo(const GCMClient::CheckinInfo& checkin_info);
-  void CheckOut();
-  void Register(const std::string& app_id,
-                const std::vector<std::string>& sender_ids,
-                const std::string& cert);
-  void Unregister(const std::string& app_id);
-  void Send(const std::string& app_id,
-            const std::string& receiver_id,
-            const GCMClient::OutgoingMessage& message);
-
- private:
-  friend class base::RefCountedThreadSafe<IOWorker>;
-  virtual ~IOWorker();
-
-  const base::WeakPtr<GCMProfileService> service_;
-
-  // Not owned.
-  GCMClient* gcm_client_;
-
-  // The username (email address) of the signed-in user.
-  std::string username_;
-
-  // The checkin info obtained from the server for the signed in user associated
-  // with the profile.
-  GCMClient::CheckinInfo checkin_info_;
-};
-
-GCMProfileService::IOWorker::IOWorker(
-    const base::WeakPtr<GCMProfileService>& service)
-    : service_(service),
-      gcm_client_(NULL) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
-}
-
-GCMProfileService::IOWorker::~IOWorker() {
-}
-
-void GCMProfileService::IOWorker::Initialize() {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
-
-  gcm_client_ = GCMClientFactory::GetClient();
-
-  content::BrowserThread::PostTask(
-      content::BrowserThread::UI,
-      FROM_HERE,
-      base::Bind(&GCMProfileService::CheckGCMClientLoadingFinished,
-                 service_,
-                 gcm_client_->IsLoading()));
-}
-
-void GCMProfileService::IOWorker::OnCheckInFinished(
-    const GCMClient::CheckinInfo& checkin_info,
-    GCMClient::Result result) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
-
-  checkin_info_ = checkin_info;
-
-  content::BrowserThread::PostTask(
-      content::BrowserThread::UI,
-      FROM_HERE,
-      base::Bind(&GCMProfileService::CheckInFinished,
-                 service_,
-                 checkin_info_,
-                 result));
-}
-
-void GCMProfileService::IOWorker::OnRegisterFinished(
-    const std::string& app_id,
-    const std::string& registration_id,
-    GCMClient::Result result) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
-
-  content::BrowserThread::PostTask(
-      content::BrowserThread::UI,
-      FROM_HERE,
-      base::Bind(&GCMProfileService::RegisterFinished,
-                 service_,
-                 app_id,
-                 registration_id,
-                 result));
-}
-
-void GCMProfileService::IOWorker::OnSendFinished(
-    const std::string& app_id,
-    const std::string& message_id,
-    GCMClient::Result result) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
-
-  content::BrowserThread::PostTask(
-      content::BrowserThread::UI,
-      FROM_HERE,
-      base::Bind(&GCMProfileService::SendFinished,
-                 service_,
-                 app_id,
-                 message_id,
-                 result));
-}
-
-void GCMProfileService::IOWorker::OnMessageReceived(
-    const std::string& app_id,
-    const GCMClient::IncomingMessage& message) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
-
-  content::BrowserThread::PostTask(
-      content::BrowserThread::UI,
-      FROM_HERE,
-      base::Bind(&GCMProfileService::MessageReceived,
-                 service_,
-                 app_id,
-                 message));
-}
-
-void GCMProfileService::IOWorker::OnMessagesDeleted(const std::string& app_id) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
-
-  content::BrowserThread::PostTask(
-      content::BrowserThread::UI,
-      FROM_HERE,
-      base::Bind(&GCMProfileService::MessagesDeleted,
-                 service_,
-                 app_id));
-}
-
-void GCMProfileService::IOWorker::OnMessageSendError(
-    const std::string& app_id,
-    const std::string& message_id,
-    GCMClient::Result result) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
-
-  content::BrowserThread::PostTask(
-      content::BrowserThread::UI,
-      FROM_HERE,
-      base::Bind(&GCMProfileService::MessageSendError,
-                 service_,
-                 app_id,
-                 message_id,
-                 result));
-}
-
-GCMClient::CheckinInfo GCMProfileService::IOWorker::GetCheckinInfo() const {
-  return checkin_info_;
-}
-
-void GCMProfileService::IOWorker::OnLoadingCompleted() {
-  content::BrowserThread::PostTask(
-      content::BrowserThread::UI,
-      FROM_HERE,
-      base::Bind(&GCMProfileService::GCMClientLoadingFinished,
-                 service_));
-}
-
-void GCMProfileService::IOWorker::SetUser(const std::string& username) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
-  DCHECK(username_.empty() && !username.empty());
-
-  username_ = username;
-  gcm_client_->SetUserDelegate(username_, this);
-}
-
-void GCMProfileService::IOWorker::RemoveUser() {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
-
-  if (username_.empty())
-    return;
-  gcm_client_->SetUserDelegate(username_, NULL);
-  username_.clear();
-}
-
-void GCMProfileService::IOWorker::CheckIn() {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
-
-  gcm_client_->CheckIn(username_);
-}
-
-void GCMProfileService::IOWorker::SetCheckinInfo(
-    const GCMClient::CheckinInfo& checkin_info) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
-
-  checkin_info_ = checkin_info;
-}
-
-void GCMProfileService::IOWorker::CheckOut() {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
-
-  checkin_info_.Reset();
-  RemoveUser();
-}
-
-void GCMProfileService::IOWorker::Register(
-    const std::string& app_id,
-    const std::vector<std::string>& sender_ids,
-    const std::string& cert) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
-  DCHECK(!username_.empty() && checkin_info_.IsValid());
-
-  gcm_client_->Register(username_, app_id, cert, sender_ids);
-}
-
-void GCMProfileService::IOWorker::Unregister(const std::string& app_id) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
-  DCHECK(!username_.empty() && checkin_info_.IsValid());
-
-  gcm_client_->Unregister(username_, app_id);
-}
-
-void GCMProfileService::IOWorker::Send(
-    const std::string& app_id,
-    const std::string& receiver_id,
-    const GCMClient::OutgoingMessage& message) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
-  DCHECK(!username_.empty() && checkin_info_.IsValid());
-
-  gcm_client_->Send(username_, app_id, receiver_id, message);
-}
-
-GCMProfileService::RegistrationInfo::RegistrationInfo() {
-}
+// static
+GCMProfileService::GCMEnabledState GCMProfileService::GetGCMEnabledState(
+    Profile* profile) {
+  const base::Value* gcm_enabled_value =
+      profile->GetPrefs()->GetUserPrefValue(prefs::kGCMChannelEnabled);
+  if (!gcm_enabled_value)
+    return ENABLED_FOR_APPS;
 
-GCMProfileService::RegistrationInfo::~RegistrationInfo() {
-}
+  bool gcm_enabled = false;
+  if (!gcm_enabled_value->GetAsBoolean(&gcm_enabled))
+    return ENABLED_FOR_APPS;
 
-bool GCMProfileService::RegistrationInfo::IsValid() const {
-  return !sender_ids.empty() && !registration_id.empty();
+  return gcm_enabled ? ALWAYS_ENABLED : ALWAYS_DISABLED;
 }
 
-bool GCMProfileService::enable_gcm_for_testing_ = false;
-
 // static
-bool GCMProfileService::IsGCMEnabled(Profile* profile) {
-  // GCM is not enabled in incognito mode.
-  if (profile->IsOffTheRecord())
-    return false;
-
-  if (enable_gcm_for_testing_)
-    return true;
-
-  // GCM support is only enabled for Canary/Dev builds.
-  chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel();
-  return channel == chrome::VersionInfo::CHANNEL_UNKNOWN ||
-         channel == chrome::VersionInfo::CHANNEL_CANARY ||
-         channel == chrome::VersionInfo::CHANNEL_DEV;
+std::string GCMProfileService::GetGCMEnabledStateString(GCMEnabledState state) {
+  switch (state) {
+    case GCMProfileService::ALWAYS_ENABLED:
+      return "ALWAYS_ENABLED";
+    case GCMProfileService::ENABLED_FOR_APPS:
+      return "ENABLED_FOR_APPS";
+    case GCMProfileService::ALWAYS_DISABLED:
+      return "ALWAYS_DISABLED";
+    default:
+      NOTREACHED();
+      return std::string();
+  }
 }
 
 // static
 void GCMProfileService::RegisterProfilePrefs(
     user_prefs::PrefRegistrySyncable* registry) {
-  registry->RegisterUint64Pref(
-      prefs::kGCMUserAccountID,
-      0,
-      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
-  registry->RegisterStringPref(
-      prefs::kGCMUserToken,
-      "",
+  // GCM support is only enabled by default for Canary/Dev/Custom builds.
+  chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel();
+  bool on_by_default = false;
+  if (channel == chrome::VersionInfo::CHANNEL_UNKNOWN ||
+      channel == chrome::VersionInfo::CHANNEL_CANARY ||
+      channel == chrome::VersionInfo::CHANNEL_DEV) {
+    on_by_default = true;
+  }
+  registry->RegisterBooleanPref(
+      prefs::kGCMChannelEnabled,
+      on_by_default,
       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
 }
 
 GCMProfileService::GCMProfileService(Profile* profile)
-    : profile_(profile),
-      testing_delegate_(NULL),
-      weak_ptr_factory_(this) {
+    : GCMService(scoped_ptr<IdentityProvider>(new ProfileIdentityProvider(
+          SigninManagerFactory::GetForProfile(profile),
+          ProfileOAuth2TokenServiceFactory::GetForProfile(profile),
+#if defined(OS_ANDROID)
+          NULL))),
+#else
+          LoginUIServiceFactory::GetForProfile(profile)))),
+#endif
+      profile_(profile) {
   DCHECK(!profile->IsOffTheRecord());
 }
 
 GCMProfileService::~GCMProfileService() {
-  if (username_.empty())
-    return;
-  content::BrowserThread::PostTask(
-      content::BrowserThread::IO,
-      FROM_HERE,
-      base::Bind(&GCMProfileService::IOWorker::RemoveUser,
-                 io_worker_));
-}
-
-void GCMProfileService::Initialize() {
-  delayed_task_controller_.reset(new DelayedTaskController);
-
-  // This has to be done first since CheckIn depends on it.
-  io_worker_ = new IOWorker(weak_ptr_factory_.GetWeakPtr());
-
-  // This initializes GCMClient and also does the check to find out if GCMClient
-  // has finished the loading.
-  content::BrowserThread::PostTask(
-      content::BrowserThread::IO,
-      FROM_HERE,
-      base::Bind(&GCMProfileService::IOWorker::Initialize, io_worker_));
-
-  // In case that the profile has been signed in before GCMProfileService is
-  // created.
-  SigninManagerBase* manager = SigninManagerFactory::GetForProfile(profile_);
-  if (manager)
-    AddUser(manager->GetAuthenticatedUsername());
-
-  registrar_.Add(this,
-                 chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL,
-                 content::Source<Profile>(profile_));
-  registrar_.Add(this,
-                 chrome::NOTIFICATION_GOOGLE_SIGNED_OUT,
-                 content::Source<Profile>(profile_));
-  // TODO(jianli): move extension specific logic out of GCMProfileService.
-  registrar_.Add(this,
-                 chrome::NOTIFICATION_EXTENSION_LOADED,
-                 content::Source<Profile>(profile_));
-  registrar_.Add(this,
-                 chrome:: NOTIFICATION_EXTENSION_UNINSTALLED,
-                 content::Source<Profile>(profile_));
-}
-
-void GCMProfileService::Register(const std::string& app_id,
-                                 const std::vector<std::string>& sender_ids,
-                                 const std::string& cert,
-                                 RegisterCallback callback) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
-  DCHECK(!app_id.empty() && !sender_ids.empty() && !callback.is_null());
-
-  // If the profile was not signed in, bail out.
-  if (username_.empty()) {
-    callback.Run(std::string(), GCMClient::NOT_SIGNED_IN);
-    return;
-  }
-
-  // If previous register operation is still in progress, bail out.
-  if (register_callbacks_.find(app_id) != register_callbacks_.end()) {
-    callback.Run(std::string(), GCMClient::ASYNC_OPERATION_PENDING);
-    return;
-  }
-
-  // Delay the register operation until the loading is done.
-  if (!delayed_task_controller_->CanRunTaskWithoutDelay(app_id)) {
-    delayed_task_controller_->AddTask(
-        app_id,
-        base::Bind(&GCMProfileService::DoRegister,
-                   weak_ptr_factory_.GetWeakPtr(),
-                   app_id,
-                   sender_ids,
-                   cert,
-                   callback));
-    return;
-  }
-
-  DoRegister(app_id, sender_ids, cert, callback);
-}
-
-void GCMProfileService::DoRegister(const std::string& app_id,
-                                   const std::vector<std::string>& sender_ids,
-                                   const std::string& cert,
-                                   RegisterCallback callback) {
-  // Normalize the sender IDs by making them sorted.
-  std::vector<std::string> normalized_sender_ids = sender_ids;
-  std::sort(normalized_sender_ids.begin(), normalized_sender_ids.end());
-
-  // If the same sender ids is provided, return the cached registration ID
-  // directly.
-  RegistrationInfoMap::const_iterator registration_info_iter =
-      registration_info_map_.find(app_id);
-  if (registration_info_iter != registration_info_map_.end() &&
-      registration_info_iter->second.sender_ids == normalized_sender_ids) {
-    callback.Run(registration_info_iter->second.registration_id,
-                 GCMClient::SUCCESS);
-    return;
-  }
-
-  // Cache the sender IDs. The registration ID will be filled when the
-  // registration completes.
-  RegistrationInfo registration_info;
-  registration_info.sender_ids = normalized_sender_ids;
-  registration_info_map_[app_id] = registration_info;
-
-  register_callbacks_[app_id] = callback;
-
-  content::BrowserThread::PostTask(
-      content::BrowserThread::IO,
-      FROM_HERE,
-      base::Bind(&GCMProfileService::IOWorker::Register,
-                 io_worker_,
-                 app_id,
-                 normalized_sender_ids,
-                 cert));
-}
-
-void GCMProfileService::Send(const std::string& app_id,
-                             const std::string& receiver_id,
-                             const GCMClient::OutgoingMessage& message,
-                             SendCallback callback) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
-  DCHECK(!app_id.empty() && !receiver_id.empty() && !callback.is_null());
-
-  // If the profile was not signed in, bail out.
-  if (username_.empty()) {
-    callback.Run(std::string(), GCMClient::NOT_SIGNED_IN);
-    return;
-  }
-
-  // If the message with send ID is still in progress, bail out.
-  std::pair<std::string, std::string> key(app_id, message.id);
-  if (send_callbacks_.find(key) != send_callbacks_.end()) {
-    callback.Run(message.id, GCMClient::INVALID_PARAMETER);
-    return;
-  }
-  send_callbacks_[key] = callback;
-
-  // Delay the send operation until all the loadings are done.
-  if (!delayed_task_controller_->CanRunTaskWithoutDelay(app_id)) {
-    delayed_task_controller_->AddTask(
-        app_id,
-        base::Bind(&GCMProfileService::DoSend,
-                   weak_ptr_factory_.GetWeakPtr(),
-                   app_id,
-                   receiver_id,
-                   message));
-    return;
-  }
-
-  DoSend(app_id, receiver_id, message);
-}
-
-void GCMProfileService::DoSend(const std::string& app_id,
-                               const std::string& receiver_id,
-                               const GCMClient::OutgoingMessage& message) {
-  content::BrowserThread::PostTask(
-      content::BrowserThread::IO,
-      FROM_HERE,
-      base::Bind(&GCMProfileService::IOWorker::Send,
-                 io_worker_,
-                 app_id,
-                 receiver_id,
-                 message));
-}
-
-void GCMProfileService::Observe(int type,
-                                const content::NotificationSource& source,
-                                const content::NotificationDetails& details) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
-
-  switch (type) {
-    case chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL: {
-      const GoogleServiceSigninSuccessDetails* signin_details =
-          content::Details<GoogleServiceSigninSuccessDetails>(details).ptr();
-      AddUser(signin_details->username);
-      break;
-    }
-    case chrome::NOTIFICATION_GOOGLE_SIGNED_OUT:
-      username_.clear();
-      RemoveUser();
-      break;
-    case chrome::NOTIFICATION_EXTENSION_LOADED: {
-      extensions::Extension* extension =
-          content::Details<extensions::Extension>(details).ptr();
-      // No need to load the persisted registration info if the extension does
-      // not have the GCM permission.
-      if (extension->HasAPIPermission(extensions::APIPermission::kGcm))
-        ReadRegistrationInfo(extension->id());
-      break;
-    }
-    case chrome:: NOTIFICATION_EXTENSION_UNINSTALLED: {
-      extensions::Extension* extension =
-          content::Details<extensions::Extension>(details).ptr();
-      Unregister(extension->id());
-      break;
-    }
-    default:
-      NOTREACHED();
-  }
-}
-
-void GCMProfileService::AddUser(const std::string& username) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
-
-  // If re-signin occurs due to password change, there is no need to do
-  // check-in again.
-  if (username_ == username || username.empty())
-    return;
-  username_ = username;
-
-  content::BrowserThread::PostTask(
-      content::BrowserThread::IO,
-      FROM_HERE,
-      base::Bind(&GCMProfileService::IOWorker::SetUser,
-                 io_worker_,
-                 username_));
-
-  // Try to read persisted check-in info from the profile's prefs store.
-  PrefService* pref_service = profile_->GetPrefs();
-  uint64 android_id = pref_service->GetUint64(prefs::kGCMUserAccountID);
-  std::string base64_token = pref_service->GetString(prefs::kGCMUserToken);
-  std::string encrypted_secret;
-  base::Base64Decode(base::StringPiece(base64_token), &encrypted_secret);
-  if (android_id && !encrypted_secret.empty()) {
-    std::string decrypted_secret;
-    Encryptor::DecryptString(encrypted_secret, &decrypted_secret);
-    uint64 secret = 0;
-    if (base::StringToUint64(decrypted_secret, &secret) && secret) {
-      GCMClient::CheckinInfo checkin_info;
-      checkin_info.android_id = android_id;
-      checkin_info.secret = secret;
-      content::BrowserThread::PostTask(
-          content::BrowserThread::IO,
-          FROM_HERE,
-          base::Bind(&GCMProfileService::IOWorker::SetCheckinInfo,
-                     io_worker_,
-                     checkin_info));
-
-      if (testing_delegate_)
-        testing_delegate_->CheckInFinished(checkin_info, GCMClient::SUCCESS);
-
-      return;
-    }
-  }
-
-  content::BrowserThread::PostTask(
-      content::BrowserThread::IO,
-      FROM_HERE,
-      base::Bind(&GCMProfileService::IOWorker::CheckIn, io_worker_));
-}
-
-void GCMProfileService::RemoveUser() {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
-
-  PrefService* pref_service = profile_->GetPrefs();
-  pref_service->ClearPref(prefs::kGCMUserAccountID);
-  pref_service->ClearPref(prefs::kGCMUserToken);
-
-  content::BrowserThread::PostTask(
-      content::BrowserThread::IO,
-      FROM_HERE,
-      base::Bind(&GCMProfileService::IOWorker::CheckOut, io_worker_));
-}
-
-void GCMProfileService::Unregister(const std::string& app_id) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
-
-  // This is unlikely to happen because the app will not be uninstalled before
-  // the asynchronous extension function completes.
-  DCHECK(register_callbacks_.find(app_id) == register_callbacks_.end());
-
-  // Remove the cached registration info. If not found, there is no need to
-  // ask the server to unregister it.
-  RegistrationInfoMap::iterator registration_info_iter =
-      registration_info_map_.find(app_id);
-  if (registration_info_iter == registration_info_map_.end())
-    return;
-  registration_info_map_.erase(registration_info_iter);
-
-  // Remove the persisted registration info.
-  DeleteRegistrationInfo(app_id);
-
-  // No need to track the app any more.
-  delayed_task_controller_->RemoveApp(app_id);
-
-  // Ask the server to unregister it. There could be a small chance that the
-  // unregister request fails. If this occurs, it does not bring any harm since
-  // we simply reject the messages/events received from the server.
-  content::BrowserThread::PostTask(
-      content::BrowserThread::IO,
-      FROM_HERE,
-      base::Bind(&GCMProfileService::IOWorker::Unregister,
-                 io_worker_,
-                 app_id));
-}
-
-void GCMProfileService::CheckInFinished(
-    const GCMClient::CheckinInfo& checkin_info, GCMClient::Result result) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
-
-  // Save the check-in info into the profile's prefs store.
-  PrefService* pref_service = profile_->GetPrefs();
-  pref_service->SetUint64(prefs::kGCMUserAccountID, checkin_info.android_id);
-
-  // Encrypt the secret for persisting purpose.
-  std::string encrypted_secret;
-  Encryptor::EncryptString(base::Uint64ToString(checkin_info.secret),
-                           &encrypted_secret);
-
-  // |encrypted_secret| might contain binary data and our prefs store only
-  // works for the text.
-  std::string base64_token;
-  base::Base64Encode(encrypted_secret, &base64_token);
-  pref_service->SetString(prefs::kGCMUserToken, base64_token);
-
-  if (testing_delegate_)
-    testing_delegate_->CheckInFinished(checkin_info, result);
-}
-
-void GCMProfileService::RegisterFinished(const std::string& app_id,
-                                         const std::string& registration_id,
-                                         GCMClient::Result result) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
-
-  std::map<std::string, RegisterCallback>::iterator callback_iter =
-      register_callbacks_.find(app_id);
-  if (callback_iter == register_callbacks_.end()) {
-    // The callback could have been removed when the app is uninstalled.
-    return;
-  }
-
-  // Cache the registration ID if the registration succeeds. Otherwise,
-  // removed the cached info.
-  RegistrationInfoMap::iterator registration_info_iter =
-      registration_info_map_.find(app_id);
-  // This is unlikely to happen because the app will not be uninstalled before
-  // the asynchronous extension function completes.
-  DCHECK(registration_info_iter != registration_info_map_.end());
-  if (result == GCMClient::SUCCESS) {
-    registration_info_iter->second.registration_id = registration_id;
-    WriteRegistrationInfo(app_id);
-  } else {
-    registration_info_map_.erase(registration_info_iter);
-  }
-
-  RegisterCallback callback = callback_iter->second;
-  register_callbacks_.erase(callback_iter);
-  callback.Run(registration_id, result);
 }
 
-void GCMProfileService::SendFinished(const std::string& app_id,
-                                     const std::string& message_id,
-                                     GCMClient::Result result) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
-
-  std::map<std::pair<std::string, std::string>, SendCallback>::iterator
-      callback_iter = send_callbacks_.find(
-          std::pair<std::string, std::string>(app_id, message_id));
-  if (callback_iter == send_callbacks_.end()) {
-    // The callback could have been removed when the app is uninstalled.
-    return;
-  }
-
-  SendCallback callback = callback_iter->second;
-  send_callbacks_.erase(callback_iter);
-  callback.Run(message_id, result);
+void GCMProfileService::Shutdown() {
+  ShutdownService();
 }
 
-void GCMProfileService::MessageReceived(const std::string& app_id,
-                                        GCMClient::IncomingMessage message) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
-
-  // Drop the event if signed out.
-  if (username_.empty())
-    return;
-
-  GetEventRouter(app_id)->OnMessage(app_id, message);
+std::string GCMProfileService::SignedInUserName() const {
+  if (IsStarted())
+    return identity_provider_->GetActiveUsername();
+  return std::string();
 }
 
-void GCMProfileService::MessagesDeleted(const std::string& app_id) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
-
-  // Drop the event if signed out.
-  if (username_.empty())
-    return;
-
-  GetEventRouter(app_id)->OnMessagesDeleted(app_id);
+bool GCMProfileService::ShouldStartAutomatically() const {
+  return GetGCMEnabledState(profile_) == ALWAYS_ENABLED;
 }
 
-void GCMProfileService::MessageSendError(const std::string& app_id,
-                                         const std::string& message_id,
-                                         GCMClient::Result result) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
-
-  // Drop the event if signed out.
-  if (username_.empty())
-    return;
-
-  GetEventRouter(app_id)->OnSendError(app_id, message_id, result);
+base::FilePath GCMProfileService::GetStorePath() const {
+  return profile_->GetPath().Append(chrome::kGCMStoreDirname);
 }
 
-void GCMProfileService::CheckGCMClientLoadingFinished(bool is_loading) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
-
-  if (!is_loading)
-    delayed_task_controller_->SetGCMClientReady();
-}
-
-void GCMProfileService::GCMClientLoadingFinished() {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
-
-  delayed_task_controller_->SetGCMClientReady();
-}
-
-GCMEventRouter* GCMProfileService::GetEventRouter(const std::string& app_id) {
-  if (testing_delegate_ && testing_delegate_->GetEventRouter())
-    return testing_delegate_->GetEventRouter();
-  // TODO(fgorski): check and create the event router for JS routing.
-  return js_event_router_.get();
-}
-
-void GCMProfileService::DeleteRegistrationInfo(const std::string& app_id) {
-  extensions::StateStore* storage =
-      extensions::ExtensionSystem::Get(profile_)->state_store();
-  DCHECK(storage);
-
-  storage->RemoveExtensionValue(app_id, kRegistrationKey);
-}
-
-void GCMProfileService::WriteRegistrationInfo(const std::string& app_id) {
-  extensions::StateStore* storage =
-      extensions::ExtensionSystem::Get(profile_)->state_store();
-  DCHECK(storage);
-
-  RegistrationInfoMap::const_iterator registration_info_iter =
-      registration_info_map_.find(app_id);
-  if (registration_info_iter == registration_info_map_.end())
-    return;
-  const RegistrationInfo& registration_info = registration_info_iter->second;
-
-  scoped_ptr<base::ListValue> senders_list(new base::ListValue());
-  for (std::vector<std::string>::const_iterator senders_iter =
-           registration_info.sender_ids.begin();
-       senders_iter != registration_info.sender_ids.end();
-       ++senders_iter) {
-    senders_list->AppendString(*senders_iter);
-  }
-
-  scoped_ptr<base::DictionaryValue> registration_info_dict(
-      new base::DictionaryValue());
-  registration_info_dict->Set(kSendersKey, senders_list.release());
-  registration_info_dict->SetString(kRegistrationIDKey,
-                                    registration_info.registration_id);
-
-  storage->SetExtensionValue(
-      app_id, kRegistrationKey, registration_info_dict.PassAs<base::Value>());
-}
-
-void GCMProfileService::ReadRegistrationInfo(const std::string& app_id) {
-  // This function can be called more than once when the app is allowed in
-  // incognito and the extension service reloads the app.
-  if (delayed_task_controller_->IsAppTracked(app_id))
-    return;
-
-  delayed_task_controller_->AddApp(app_id);
-
-  extensions::StateStore* storage =
-      extensions::ExtensionSystem::Get(profile_)->state_store();
-  DCHECK(storage);
-  storage->GetExtensionValue(
-      app_id,
-      kRegistrationKey,
-      base::Bind(
-          &GCMProfileService::ReadRegistrationInfoFinished,
-          weak_ptr_factory_.GetWeakPtr(),
-          app_id));
-}
-
-void GCMProfileService::ReadRegistrationInfoFinished(
-    const std::string& app_id,
-    scoped_ptr<base::Value> value) {
-  RegistrationInfo registration_info;
-  if (value &&
-     !ParsePersistedRegistrationInfo(value.Pass(), &registration_info)) {
-    // Delete the persisted data if it is corrupted.
-    DeleteRegistrationInfo(app_id);
-  }
-
-  if (registration_info.IsValid())
-    registration_info_map_[app_id] = registration_info;
-
-  delayed_task_controller_->SetAppReady(app_id);
-}
-
-bool GCMProfileService::ParsePersistedRegistrationInfo(
-    scoped_ptr<base::Value> value,
-    RegistrationInfo* registration_info) {
-  base::DictionaryValue* dict = NULL;
-  if (!value.get() || !value->GetAsDictionary(&dict))
-    return false;
-
-  if (!dict->GetString(kRegistrationIDKey, &registration_info->registration_id))
-    return false;
-
-  const base::ListValue* senders_list = NULL;
-  if (!dict->GetList(kSendersKey, &senders_list) || !senders_list->GetSize())
-    return false;
-  for (size_t i = 0; i < senders_list->GetSize(); ++i) {
-    std::string sender;
-    if (!senders_list->GetString(i, &sender))
-      return false;
-    registration_info->sender_ids.push_back(sender);
-  }
-
-  return true;
-}
-
-// static
-const char* GCMProfileService::GetPersistentRegisterKeyForTesting() {
-  return kRegistrationKey;
+scoped_refptr<net::URLRequestContextGetter>
+GCMProfileService::GetURLRequestContextGetter() const {
+  return profile_->GetRequestContext();
 }
 
 }  // namespace gcm