1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim:expandtab:shiftwidth=2:tabstop=2: 3 */ 4 /* This Source Code Form is subject to the terms of the Mozilla Public 5 * License, v. 2.0. If a copy of the MPL was not distributed with this 6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 7 8 #ifndef nsUserIdleService_h__ 9 #define nsUserIdleService_h__ 10 11 #include "nsIUserIdleServiceInternal.h" 12 #include "nsCOMPtr.h" 13 #include "nsITimer.h" 14 #include "nsTArray.h" 15 #include "nsIObserver.h" 16 #include "nsIUserIdleService.h" 17 #include "nsCategoryCache.h" 18 #include "nsWeakReference.h" 19 #include "mozilla/TimeStamp.h" 20 21 /** 22 * Class we can use to store an observer with its associated idle time 23 * requirement and whether or not the observer thinks it's "idle". 24 */ 25 class IdleListener { 26 public: 27 nsCOMPtr<nsIObserver> observer; 28 uint32_t reqIdleTime; 29 bool isIdle; 30 31 IdleListener(nsIObserver* obs, uint32_t reqIT, bool aIsIdle = false) observer(obs)32 : observer(obs), reqIdleTime(reqIT), isIdle(aIsIdle) {} 33 ~IdleListener() = default; 34 }; 35 36 // This one will be declared later. 37 class nsUserIdleService; 38 39 /** 40 * Class to handle the daily idle timer. 41 */ 42 class nsUserIdleServiceDaily : public nsIObserver, 43 public nsSupportsWeakReference { 44 public: 45 NS_DECL_ISUPPORTS 46 NS_DECL_NSIOBSERVER 47 48 explicit nsUserIdleServiceDaily(nsIUserIdleService* aIdleService); 49 50 /** 51 * Initializes the daily idle observer. 52 * Keep this separated from the constructor, since it could cause pointer 53 * corruption due to AddRef/Release of "this". 54 */ 55 void Init(); 56 57 private: 58 virtual ~nsUserIdleServiceDaily(); 59 60 /** 61 * StageIdleDaily is the interim call made when an idle-daily event is due. 62 * However we don't want to fire idle-daily until the user is idle for this 63 * session, so this sets up a short wait for an idle event which triggers 64 * the actual idle-daily event. 65 * 66 * @param aHasBeenLongWait Pass true indicating nsUserIdleServiceDaily is 67 * having trouble getting the idle-daily event fired. If true StageIdleDaily 68 * will use a shorter idle wait time before firing idle-daily. 69 */ 70 void StageIdleDaily(bool aHasBeenLongWait); 71 72 /** 73 * @note This is a normal pointer, part to avoid creating a cycle with the 74 * idle service, part to avoid potential pointer corruption due to this class 75 * being instantiated in the constructor of the service itself. 76 */ 77 nsIUserIdleService* mIdleService; 78 79 /** 80 * Place to hold the timer used by this class to determine when a day has 81 * passed, after that it will wait for idle time to be detected. 82 */ 83 nsCOMPtr<nsITimer> mTimer; 84 85 /** 86 * Function that is called back once a day. 87 */ 88 static void DailyCallback(nsITimer* aTimer, void* aClosure); 89 90 /** 91 * Cache of observers for the "idle-daily" category. 92 */ 93 nsCategoryCache<nsIObserver> mCategoryObservers; 94 95 /** 96 * Boolean set to true when daily idle notifications should be disabled. 97 */ 98 bool mShutdownInProgress; 99 100 /** 101 * Next time we expect an idle-daily timer to fire, in case timers aren't 102 * very reliable on the platform. Value is in PR_Now microsecond units. 103 */ 104 PRTime mExpectedTriggerTime; 105 106 /** 107 * Tracks which idle daily observer callback we ask for. There are two: a 108 * regular long idle wait and a shorter wait if we've been waiting to fire 109 * idle daily for an extended period. Set by StageIdleDaily. 110 */ 111 int32_t mIdleDailyTriggerWait; 112 }; 113 114 class nsUserIdleService : public nsIUserIdleServiceInternal { 115 public: 116 NS_DECL_ISUPPORTS 117 NS_DECL_NSIUSERIDLESERVICE NS_DECL_NSIUSERIDLESERVICEINTERNAL 118 119 protected : static already_AddRefed<nsUserIdleService> 120 GetInstance(); 121 122 nsUserIdleService(); 123 virtual ~nsUserIdleService(); 124 125 /** 126 * If there is a platform specific function to poll the system idel time 127 * then that must be returned in this function, and the function MUST return 128 * true, otherwise then the function should be left unimplemented or made 129 * to return false (this can also be used for systems where it depends on 130 * the configuration of the system if the idle time can be determined) 131 * 132 * @param aIdleTime 133 * The idle time in ms. 134 * 135 * @return true if the idle time could be polled, false otherwise. 136 * 137 * @note The time returned by this function can be different than the one 138 * returned by GetIdleTime, as that is corrected by any calls to 139 * ResetIdleTimeOut(), unless you overwrite that function too... 140 */ 141 virtual bool PollIdleTime(uint32_t* aIdleTime); 142 143 /** 144 * Function that determines if we are in poll mode or not. 145 * 146 * @return true if polling is supported, false otherwise. 147 */ 148 virtual bool UsePollMode(); 149 150 private: 151 /** 152 * Ensure that the timer is expiring at least at the given time 153 * 154 * The function might not restart the timer if there is one running currently 155 * 156 * @param aNextTimeout 157 * The last absolute time the timer should expire 158 */ 159 void SetTimerExpiryIfBefore(mozilla::TimeStamp aNextTimeout); 160 161 /** 162 * Stores the next timeout time, 0 means timer not running 163 */ 164 mozilla::TimeStamp mCurrentlySetToTimeoutAt; 165 166 /** 167 * mTimer holds the internal timer used by this class to detect when to poll 168 * for idle time, when to check if idle timers should expire etc. 169 */ 170 nsCOMPtr<nsITimer> mTimer; 171 172 /** 173 * Array of listeners that wants to be notified about idle time. 174 */ 175 nsTArray<IdleListener> mArrayListeners; 176 177 /** 178 * Object keeping track of the daily idle thingy. 179 */ 180 RefPtr<nsUserIdleServiceDaily> mDailyIdle; 181 182 /** 183 * Number of observers currently in idle mode. 184 */ 185 uint32_t mIdleObserverCount; 186 187 /** 188 * Delta time from last non idle time to when the next observer should switch 189 * to idle mode 190 * 191 * Time in seconds 192 * 193 * If this value is 0 it means there are no active observers 194 */ 195 uint32_t mDeltaToNextIdleSwitchInS; 196 197 /** 198 * If true, the idle service is temporarily disabled, and all idle events 199 * will be ignored. 200 */ 201 bool mDisabled = false; 202 203 /** 204 * Absolute value for when the last user interaction took place. 205 */ 206 mozilla::TimeStamp mLastUserInteraction; 207 208 /** 209 * Function that ensures the timer is running with at least the minimum time 210 * needed. It will kill the timer if there are no active observers. 211 */ 212 void ReconfigureTimer(void); 213 214 /** 215 * Callback function that is called when the internal timer expires. 216 * 217 * This in turn calls the IdleTimerCallback that does the real processing 218 */ 219 static void StaticIdleTimerCallback(nsITimer* aTimer, void* aClosure); 220 221 /** 222 * Function that handles when a timer has expired 223 */ 224 void IdleTimerCallback(void); 225 }; 226 227 #endif // nsUserIdleService_h__ 228