| OLD | NEW |
| (Empty) |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "chrome/browser/drive/drive_notification_manager.h" | |
| 6 | |
| 7 #include "base/metrics/histogram.h" | |
| 8 #include "chrome/browser/drive/drive_notification_observer.h" | |
| 9 #include "components/invalidation/invalidation_service.h" | |
| 10 #include "components/invalidation/object_id_invalidation_map.h" | |
| 11 #include "google/cacheinvalidation/types.pb.h" | |
| 12 | |
| 13 namespace drive { | |
| 14 | |
| 15 namespace { | |
| 16 | |
| 17 // The polling interval time is used when XMPP is disabled. | |
| 18 const int kFastPollingIntervalInSecs = 60; | |
| 19 | |
| 20 // The polling interval time is used when XMPP is enabled. Theoretically | |
| 21 // polling should be unnecessary if XMPP is enabled, but just in case. | |
| 22 const int kSlowPollingIntervalInSecs = 300; | |
| 23 | |
| 24 // The sync invalidation object ID for Google Drive. | |
| 25 const char kDriveInvalidationObjectId[] = "CHANGELOG"; | |
| 26 | |
| 27 } // namespace | |
| 28 | |
| 29 DriveNotificationManager::DriveNotificationManager( | |
| 30 invalidation::InvalidationService* invalidation_service) | |
| 31 : invalidation_service_(invalidation_service), | |
| 32 push_notification_registered_(false), | |
| 33 push_notification_enabled_(false), | |
| 34 observers_notified_(false), | |
| 35 polling_timer_(true /* retain_user_task */, false /* is_repeating */), | |
| 36 weak_ptr_factory_(this) { | |
| 37 DCHECK(invalidation_service_); | |
| 38 RegisterDriveNotifications(); | |
| 39 RestartPollingTimer(); | |
| 40 } | |
| 41 | |
| 42 DriveNotificationManager::~DriveNotificationManager() {} | |
| 43 | |
| 44 void DriveNotificationManager::Shutdown() { | |
| 45 // Unregister for Drive notifications. | |
| 46 if (!invalidation_service_ || !push_notification_registered_) | |
| 47 return; | |
| 48 | |
| 49 // We unregister the handler without updating unregistering our IDs on | |
| 50 // purpose. See the class comment on the InvalidationService interface for | |
| 51 // more information. | |
| 52 invalidation_service_->UnregisterInvalidationHandler(this); | |
| 53 invalidation_service_ = NULL; | |
| 54 } | |
| 55 | |
| 56 void DriveNotificationManager::OnInvalidatorStateChange( | |
| 57 syncer::InvalidatorState state) { | |
| 58 push_notification_enabled_ = (state == syncer::INVALIDATIONS_ENABLED); | |
| 59 if (push_notification_enabled_) { | |
| 60 DVLOG(1) << "XMPP Notifications enabled"; | |
| 61 } else { | |
| 62 DVLOG(1) << "XMPP Notifications disabled (state=" << state << ")"; | |
| 63 } | |
| 64 FOR_EACH_OBSERVER(DriveNotificationObserver, observers_, | |
| 65 OnPushNotificationEnabled(push_notification_enabled_)); | |
| 66 } | |
| 67 | |
| 68 void DriveNotificationManager::OnIncomingInvalidation( | |
| 69 const syncer::ObjectIdInvalidationMap& invalidation_map) { | |
| 70 DVLOG(2) << "XMPP Drive Notification Received"; | |
| 71 syncer::ObjectIdSet ids = invalidation_map.GetObjectIds(); | |
| 72 DCHECK_EQ(1U, ids.size()); | |
| 73 const invalidation::ObjectId object_id( | |
| 74 ipc::invalidation::ObjectSource::COSMO_CHANGELOG, | |
| 75 kDriveInvalidationObjectId); | |
| 76 DCHECK_EQ(1U, ids.count(object_id)); | |
| 77 | |
| 78 // This effectively disables 'local acks'. It tells the invalidations system | |
| 79 // to not bother saving invalidations across restarts for us. | |
| 80 // See crbug.com/320878. | |
| 81 invalidation_map.AcknowledgeAll(); | |
| 82 NotifyObserversToUpdate(NOTIFICATION_XMPP); | |
| 83 } | |
| 84 | |
| 85 std::string DriveNotificationManager::GetOwnerName() const { return "Drive"; } | |
| 86 | |
| 87 void DriveNotificationManager::AddObserver( | |
| 88 DriveNotificationObserver* observer) { | |
| 89 observers_.AddObserver(observer); | |
| 90 } | |
| 91 | |
| 92 void DriveNotificationManager::RemoveObserver( | |
| 93 DriveNotificationObserver* observer) { | |
| 94 observers_.RemoveObserver(observer); | |
| 95 } | |
| 96 | |
| 97 void DriveNotificationManager::RestartPollingTimer() { | |
| 98 const int interval_secs = (push_notification_enabled_ ? | |
| 99 kSlowPollingIntervalInSecs : | |
| 100 kFastPollingIntervalInSecs); | |
| 101 polling_timer_.Stop(); | |
| 102 polling_timer_.Start( | |
| 103 FROM_HERE, | |
| 104 base::TimeDelta::FromSeconds(interval_secs), | |
| 105 base::Bind(&DriveNotificationManager::NotifyObserversToUpdate, | |
| 106 weak_ptr_factory_.GetWeakPtr(), | |
| 107 NOTIFICATION_POLLING)); | |
| 108 } | |
| 109 | |
| 110 void DriveNotificationManager::NotifyObserversToUpdate( | |
| 111 NotificationSource source) { | |
| 112 DVLOG(1) << "Notifying observers: " << NotificationSourceToString(source); | |
| 113 FOR_EACH_OBSERVER(DriveNotificationObserver, observers_, | |
| 114 OnNotificationReceived()); | |
| 115 if (!observers_notified_) { | |
| 116 UMA_HISTOGRAM_BOOLEAN("Drive.PushNotificationInitiallyEnabled", | |
| 117 push_notification_enabled_); | |
| 118 } | |
| 119 observers_notified_ = true; | |
| 120 | |
| 121 // Note that polling_timer_ is not a repeating timer. Restarting manually | |
| 122 // here is better as XMPP may be received right before the polling timer is | |
| 123 // fired (i.e. we don't notify observers twice in a row). | |
| 124 RestartPollingTimer(); | |
| 125 } | |
| 126 | |
| 127 void DriveNotificationManager::RegisterDriveNotifications() { | |
| 128 DCHECK(!push_notification_enabled_); | |
| 129 | |
| 130 if (!invalidation_service_) | |
| 131 return; | |
| 132 | |
| 133 invalidation_service_->RegisterInvalidationHandler(this); | |
| 134 syncer::ObjectIdSet ids; | |
| 135 ids.insert(invalidation::ObjectId( | |
| 136 ipc::invalidation::ObjectSource::COSMO_CHANGELOG, | |
| 137 kDriveInvalidationObjectId)); | |
| 138 CHECK(invalidation_service_->UpdateRegisteredInvalidationIds(this, ids)); | |
| 139 push_notification_registered_ = true; | |
| 140 OnInvalidatorStateChange(invalidation_service_->GetInvalidatorState()); | |
| 141 | |
| 142 UMA_HISTOGRAM_BOOLEAN("Drive.PushNotificationRegistered", | |
| 143 push_notification_registered_); | |
| 144 } | |
| 145 | |
| 146 // static | |
| 147 std::string DriveNotificationManager::NotificationSourceToString( | |
| 148 NotificationSource source) { | |
| 149 switch (source) { | |
| 150 case NOTIFICATION_XMPP: | |
| 151 return "NOTIFICATION_XMPP"; | |
| 152 case NOTIFICATION_POLLING: | |
| 153 return "NOTIFICATION_POLLING"; | |
| 154 } | |
| 155 | |
| 156 NOTREACHED(); | |
| 157 return ""; | |
| 158 } | |
| 159 | |
| 160 } // namespace drive | |
| OLD | NEW |