Home | History | Annotate | Download | only in alarms
      1 // Copyright (c) 2012 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 #ifndef CHROME_BROWSER_EXTENSIONS_API_ALARMS_ALARM_MANAGER_H__
      6 #define CHROME_BROWSER_EXTENSIONS_API_ALARMS_ALARM_MANAGER_H__
      7 
      8 #include <map>
      9 #include <string>
     10 #include <vector>
     11 
     12 #include "base/memory/weak_ptr.h"
     13 #include "base/timer/timer.h"
     14 #include "chrome/browser/extensions/api/profile_keyed_api_factory.h"
     15 #include "chrome/browser/extensions/extension_function.h"
     16 #include "chrome/common/extensions/api/alarms.h"
     17 #include "content/public/browser/notification_observer.h"
     18 #include "content/public/browser/notification_registrar.h"
     19 
     20 class Profile;
     21 
     22 namespace base {
     23 class Clock;
     24 }  // namespace base
     25 
     26 namespace extensions {
     27 
     28 class ExtensionAlarmsSchedulingTest;
     29 
     30 struct Alarm {
     31   Alarm();
     32   Alarm(const std::string& name,
     33         const api::alarms::AlarmCreateInfo& create_info,
     34         base::TimeDelta min_granularity,
     35         base::Time now);
     36   ~Alarm();
     37 
     38   linked_ptr<api::alarms::Alarm> js_alarm;
     39   // The granularity isn't exposed to the extension's javascript, but we poll at
     40   // least as often as the shortest alarm's granularity.  It's initialized as
     41   // the relative delay requested in creation, even if creation uses an absolute
     42   // time.  This will always be at least as large as the min_granularity
     43   // constructor argument.
     44   base::TimeDelta granularity;
     45 };
     46 
     47 // Manages the currently pending alarms for every extension in a profile.
     48 // There is one manager per virtual Profile.
     49 class AlarmManager
     50     : public ProfileKeyedAPI,
     51       public content::NotificationObserver,
     52       public base::SupportsWeakPtr<AlarmManager> {
     53  public:
     54   typedef std::vector<Alarm> AlarmList;
     55 
     56   class Delegate {
     57    public:
     58     virtual ~Delegate() {}
     59     // Called when an alarm fires.
     60     virtual void OnAlarm(const std::string& extension_id,
     61                          const Alarm& alarm) = 0;
     62   };
     63 
     64   explicit AlarmManager(Profile* profile);
     65   virtual ~AlarmManager();
     66 
     67   // Override the default delegate. Callee assumes onwership. Used for testing.
     68   void set_delegate(Delegate* delegate) { delegate_.reset(delegate); }
     69 
     70   // Adds |alarm| for the given extension, and starts the timer.
     71   void AddAlarm(const std::string& extension_id,
     72                 const Alarm& alarm);
     73 
     74   // Returns the alarm with the given name, or NULL if none exists.
     75   const Alarm* GetAlarm(const std::string& extension_id,
     76                         const std::string& name);
     77 
     78   // Returns the list of pending alarms for the given extension, or NULL
     79   // if none exist.
     80   const AlarmList* GetAllAlarms(const std::string& extension_id);
     81 
     82   // Cancels and removes the alarm with the given name.
     83   bool RemoveAlarm(const std::string& extension_id,
     84                    const std::string& name);
     85 
     86   // Cancels and removes all alarms for the given extension.
     87   void RemoveAllAlarms(const std::string& extension_id);
     88 
     89   // Replaces AlarmManager's owned clock with |clock| and takes ownership of it.
     90   void SetClockForTesting(base::Clock* clock);
     91 
     92   // ProfileKeyedAPI implementation.
     93   static ProfileKeyedAPIFactory<AlarmManager>* GetFactoryInstance();
     94 
     95   // Convenience method to get the AlarmManager for a profile.
     96   static AlarmManager* Get(Profile* profile);
     97 
     98  private:
     99   FRIEND_TEST_ALL_PREFIXES(ExtensionAlarmsTest, CreateRepeating);
    100   FRIEND_TEST_ALL_PREFIXES(ExtensionAlarmsTest, Clear);
    101   friend class ExtensionAlarmsSchedulingTest;
    102   FRIEND_TEST_ALL_PREFIXES(ExtensionAlarmsSchedulingTest, PollScheduling);
    103   FRIEND_TEST_ALL_PREFIXES(ExtensionAlarmsSchedulingTest,
    104                            ReleasedExtensionPollsInfrequently);
    105   FRIEND_TEST_ALL_PREFIXES(ExtensionAlarmsSchedulingTest, TimerRunning);
    106   friend class ProfileKeyedAPIFactory<AlarmManager>;
    107 
    108   typedef std::string ExtensionId;
    109   typedef std::map<ExtensionId, AlarmList> AlarmMap;
    110 
    111   // Iterator used to identify a particular alarm within the Map/List pair.
    112   // "Not found" is represented by <alarms_.end(), invalid_iterator>.
    113   typedef std::pair<AlarmMap::iterator, AlarmList::iterator> AlarmIterator;
    114 
    115   // Helper to return the iterators within the AlarmMap and AlarmList for the
    116   // matching alarm, or an iterator to the end of the AlarmMap if none were
    117   // found.
    118   AlarmIterator GetAlarmIterator(const std::string& extension_id,
    119                                  const std::string& name);
    120 
    121   // Helper to cancel and remove the alarm at the given iterator. The iterator
    122   // must be valid.
    123   void RemoveAlarmIterator(const AlarmIterator& iter);
    124 
    125   // Callback for when an alarm fires.
    126   void OnAlarm(AlarmIterator iter);
    127 
    128   // Internal helper to add an alarm and start the timer with the given delay.
    129   void AddAlarmImpl(const std::string& extension_id,
    130                     const Alarm& alarm);
    131 
    132   // Syncs our alarm data for the given extension to/from the state storage.
    133   void WriteToStorage(const std::string& extension_id);
    134   void ReadFromStorage(const std::string& extension_id,
    135                        scoped_ptr<base::Value> value);
    136 
    137   // Schedules the next poll of alarms for when the next soonest alarm runs,
    138   // but not more often than the minimum granularity of all alarms.
    139   void ScheduleNextPoll();
    140 
    141   // Polls the alarms, running any that have elapsed. After running them and
    142   // rescheduling repeating alarms, schedule the next poll.
    143   void PollAlarms();
    144 
    145   // NotificationObserver:
    146   virtual void Observe(int type,
    147                        const content::NotificationSource& source,
    148                        const content::NotificationDetails& details) OVERRIDE;
    149 
    150   // ProfileKeyedAPI implementation.
    151   static const char* service_name() {
    152     return "AlarmManager";
    153   }
    154   static const bool kServiceHasOwnInstanceInIncognito = true;
    155 
    156   Profile* const profile_;
    157   scoped_ptr<base::Clock> clock_;
    158   content::NotificationRegistrar registrar_;
    159   scoped_ptr<Delegate> delegate_;
    160 
    161   // The timer for this alarm manager.
    162   base::OneShotTimer<AlarmManager> timer_;
    163 
    164   // A map of our pending alarms, per extension.
    165   // Invariant: None of the AlarmLists are empty.
    166   AlarmMap alarms_;
    167 
    168   // The previous and next time that alarms were and will be run.
    169   base::Time last_poll_time_;
    170   base::Time next_poll_time_;
    171 
    172   DISALLOW_COPY_AND_ASSIGN(AlarmManager);
    173 };
    174 
    175 }  //  namespace extensions
    176 
    177 #endif  // CHROME_BROWSER_EXTENSIONS_API_ALARMS_ALARM_MANAGER_H__
    178