Chromium Code Reviews| Index: chrome/browser/services/gcm/push_messaging_service_impl.cc |
| diff --git a/chrome/browser/services/gcm/push_messaging_service_impl.cc b/chrome/browser/services/gcm/push_messaging_service_impl.cc |
| index f6043b495bd9650c7b37f2ebd8947aa640847c15..0822ce192de12320f820ee5c780f30b2bd7caf8a 100644 |
| --- a/chrome/browser/services/gcm/push_messaging_service_impl.cc |
| +++ b/chrome/browser/services/gcm/push_messaging_service_impl.cc |
| @@ -7,40 +7,163 @@ |
| #include <vector> |
| #include "base/bind.h" |
| +#include "base/command_line.h" |
| +#include "base/prefs/pref_service.h" |
| +#include "base/strings/string_util.h" |
| +#include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/services/gcm/gcm_profile_service.h" |
| +#include "chrome/browser/services/gcm/gcm_profile_service_factory.h" |
| +#include "chrome/common/chrome_switches.h" |
| +#include "chrome/common/pref_names.h" |
| #include "components/gcm_driver/gcm_driver.h" |
| +#include "components/pref_registry/pref_registry_syncable.h" |
| namespace gcm { |
| +namespace { |
| +static const char kAppIdPrefix[] = "push:"; |
|
jochen (gone - plz use gerrit)
2014/06/18 03:58:40
no static
Michael van Ouwerkerk
2014/06/18 11:17:51
Done.
|
| +} // namespace |
| + |
| +// static |
| +void PushMessagingServiceImpl::RegisterProfilePrefs( |
| + user_prefs::PrefRegistrySyncable* registry) { |
| + registry->RegisterIntegerPref( |
| + prefs::kPushMessagingRegistrationCount, |
| + 0, |
| + user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); |
| +} |
| + |
| +// static |
| +void PushMessagingServiceImpl::InitializeForProfile(Profile* profile) { |
| + // TODO(mvanouwerkerk): Make sure to remove this check at the same time as |
| + // push graduates from experimental in Blink. |
| + if (!CommandLine::ForCurrentProcess()->HasSwitch( |
| + switches::kEnableExperimentalWebPlatformFeatures)) { |
| + return; |
| + } |
| + // TODO(johnme): Consider whether push should be enabled in incognito. If it |
| + // does get enabled, then be careful that you're reading the pref from the |
| + // right profile, as prefs defined in a regular profile are visible in the |
| + // corresponding incognito profile unless overrriden. |
| + if (!profile || profile->IsOffTheRecord() || profile->GetPrefs()->GetInteger( |
| + prefs::kPushMessagingRegistrationCount) <= 0) |
| + return; |
|
jochen (gone - plz use gerrit)
2014/06/18 03:58:40
nit { }
Michael van Ouwerkerk
2014/06/18 11:17:51
Done.
|
| + // Create the GCMProfileService, and hence instantiate this class. |
| + GCMProfileService* gcm_service = gcm::GCMProfileServiceFactory::GetForProfile( |
|
jochen (gone - plz use gerrit)
2014/06/18 03:58:40
is this clang-formatted?
Michael van Ouwerkerk
2014/06/18 11:17:51
Done.
|
| + profile); |
| + PushMessagingServiceImpl* push_service = |
| + static_cast<PushMessagingServiceImpl*>( |
| + gcm_service->push_messaging_service()); |
| + // Register ourselves as an app handler. |
| + gcm_service->driver()->AddAppHandler(kAppIdPrefix, push_service); |
| +} |
| + |
| PushMessagingServiceImpl::PushMessagingServiceImpl( |
| - GCMProfileService* gcm_profile_service) |
| + GCMProfileService* gcm_profile_service, |
| + Profile* profile) |
| : gcm_profile_service_(gcm_profile_service), |
| - weak_factory_(this) {} |
| + profile_(profile), |
| + weak_factory_(this) { |
| +} |
| + |
| +PushMessagingServiceImpl::~PushMessagingServiceImpl() { |
| + // TODO(johnme): If it's possible for this to be destroyed before GCMDriver, |
| + // then we should call RemoveAppHandler. |
| +} |
| -PushMessagingServiceImpl::~PushMessagingServiceImpl() {} |
| +bool PushMessagingServiceImpl::CanHandle(const std::string& app_id) const { |
| + // TODO(mvanouwerkerk): Finalize and centralize format of Push API app_id. |
| + return StartsWithASCII(app_id, kAppIdPrefix, true); |
| +} |
| + |
| +void PushMessagingServiceImpl::ShutdownHandler() { |
| + // TODO(johnme): Do any necessary cleanup. |
| +} |
| + |
| +void PushMessagingServiceImpl::OnMessage( |
| + const std::string& app_id, |
| + const GCMClient::IncomingMessage& message) { |
| + // The Push API only exposes a single string of data in the push event fired |
| + // on the Service Worker. When developers send messages using GCM to the Push |
| + // API, they must pass a single key-value pair, where the key is "data" and |
| + // the value is the string they want to be passed to their Service Worker. |
| + // For example, they could send the following JSON using the HTTPS GCM API: |
| + // { |
| + // "registration_ids": ["FOO", "BAR"], |
| + // "data": { |
| + // "data": "BAZ", |
| + // }, |
| + // "delay_while_idle": true, |
| + // } |
| + // TODO(johnme): Make sure this is clearly documented for developers. |
| + GCMClient::MessageData::const_iterator it = message.data.find("data"); |
| + if (it != message.data.end()) { |
| + const std::string& data ALLOW_UNUSED = it->second; |
| + // TODO(mvanouwerkerk): Fire push event with data on the Service Worker |
| + // corresponding to app_id (and remove ALLOW_UNUSED above). |
| + } else { |
| + // Drop the message, as it is invalid. |
| + // TODO(mvanouwerkerk): Show a warning in the developer console of the |
| + // Service Worker corresponding to app_id. |
| + // TODO(johnme): Add diagnostic observers (e.g. UMA and an internals page) |
| + // to know when bad things happen. |
| + } |
| +} |
| + |
| +void PushMessagingServiceImpl::OnMessagesDeleted(const std::string& app_id) { |
| + // TODO(mvanouwerkerk): Fire push error event on the Service Worker |
| + // corresponding to app_id. |
| +} |
| + |
| +void PushMessagingServiceImpl::OnSendError( |
| + const std::string& app_id, |
| + const GCMClient::SendErrorDetails& send_error_details) { |
| + NOTREACHED() << "The Push API shouldn't have sent messages upstream"; |
| +} |
| void PushMessagingServiceImpl::Register( |
| const std::string& app_id, |
| const std::string& sender_id, |
| const content::PushMessagingService::RegisterCallback& callback) { |
| // The GCMDriver could be NULL if GCMProfileService has been shut down. |
| - if (!gcm_profile_service_->driver()) |
| + if (!gcm_profile_service_->driver()) { |
| + DidRegister(app_id, callback, "", GCMClient::GCM_DISABLED); |
|
jianli
2014/06/17 22:05:17
It is not about a different error code we return.
Michael van Ouwerkerk
2014/06/18 11:17:51
Done.
|
| return; |
| + } |
| + |
| + // If this is registering for the first time then the driver does not have |
| + // this as an app handler and registration would fail. |
| + if (gcm_profile_service_->driver()->GetAppHandler(kAppIdPrefix) != this) |
| + gcm_profile_service_->driver()->AddAppHandler(kAppIdPrefix, this); |
| + |
| std::vector<std::string> sender_ids(1, sender_id); |
| gcm_profile_service_->driver()->Register( |
| app_id, |
| sender_ids, |
| base::Bind(&PushMessagingServiceImpl::DidRegister, |
| weak_factory_.GetWeakPtr(), |
| + app_id, |
| callback)); |
| } |
| void PushMessagingServiceImpl::DidRegister( |
| + const std::string& app_id, |
| const content::PushMessagingService::RegisterCallback& callback, |
| const std::string& registration_id, |
| GCMClient::Result result) { |
| GURL endpoint = GURL("https://android.googleapis.com/gcm/send"); |
| - callback.Run(endpoint, registration_id, result == GCMClient::SUCCESS); |
| + bool success = (result == GCMClient::SUCCESS); |
| + callback.Run(endpoint, registration_id, success); |
| + if (success) { |
| + // TODO(johnme): Make sure the pref doesn't get out of sync after crashes. |
| + int registration_count = profile_->GetPrefs()->GetInteger( |
| + prefs::kPushMessagingRegistrationCount); |
| + profile_->GetPrefs()->SetInteger(prefs::kPushMessagingRegistrationCount, |
| + registration_count + 1); |
|
jochen (gone - plz use gerrit)
2014/06/18 03:58:40
what do you do on overflow?
Michael van Ouwerkerk
2014/06/18 11:17:51
While I don't expect anyone will get that far, let
|
| + } |
| } |
| +// TODO(johnme): Unregister should decrement the pref, and call |
| +// RemoveAppHandler if the count drops to zero. |
| + |
| } // namespace gcm |