File: calendar_model.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (233 lines) | stat: -rw-r--r-- 9,339 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef ASH_SYSTEM_TIME_CALENDAR_MODEL_H_
#define ASH_SYSTEM_TIME_CALENDAR_MODEL_H_

#include <deque>
#include <list>
#include <map>
#include <memory>
#include <set>

#include "ash/ash_export.h"
#include "ash/public/cpp/session/session_observer.h"
#include "ash/system/time/calendar_event_fetch.h"
#include "ash/system/time/calendar_event_fetch_types.h"
#include "base/observer_list.h"
#include "base/time/time.h"
#include "google_apis/calendar/calendar_api_response_types.h"
#include "google_apis/common/api_error_codes.h"

namespace ash {

class CalendarEventFetch;

// A simple std::list of calendar events, used to store a single day's events
// in EventMap. Not to be confused with google_apis::calendar::EventList,
// which represents the return value of a query from the GoogleCalendar API.
using SingleDayEventList = std::list<google_apis::calendar::CalendarEvent>;

// Controller of the `CalendarView`.
class ASH_EXPORT CalendarModel : public SessionObserver {
 public:
  // `kNa` is used to represent the fetching status when on the non-logged-in
  // screens. If `kNa` is returned, the loading bar won't be shown since events
  // are not being fetched.
  // `kRefetching` is used to represent the fetching status when there're cached
  // events for a month but another fetching request has been sent. In this
  // case, the event indicator dots and the tooltip will show the cached events.
  // `kNever` is used as the default state when we experience an error or
  // timeout or haven't fetched anything.
  enum FetchingStatus { kNever, kFetching, kRefetching, kSuccess, kError, kNa };

  CalendarModel();
  CalendarModel(const CalendarModel& other) = delete;
  CalendarModel& operator=(const CalendarModel& other) = delete;
  ~CalendarModel() override;

  // SessionObserver:
  void OnSessionStateChanged(session_manager::SessionState state) override;
  void OnActiveUserSessionChanged(const AccountId& account_id) override;

  // Maps a day, i.e. midnight on the day of the event's start_time, to a
  // SingleDayEventList.
  using SingleMonthEventMap = std::map<base::Time, SingleDayEventList>;

  // Maps a month, i.e. midnight on the first day of the month, to a
  // SingleMonthEventMap.
  using MonthToEventsMap = std::map<base::Time, SingleMonthEventMap>;

  class Observer : public base::CheckedObserver {
   public:
    // Invoked when a month of events has been fetched.
    virtual void OnEventsFetched(const FetchingStatus status,
                                 const base::Time start_time) {}
  };

  void AddObserver(Observer* observer);
  void RemoveObserver(Observer* observer);

  // Completely, unconditionally clears out any cached events. Intended for when
  // we log out or switch users.
  void ClearAllCachedEvents();

  // Clears out all events that start in a non-prunable month.
  void ClearAllPrunableEvents();

  // Returns true if the event storage for a given month is populated with at
  // least one event.
  bool MonthHasEvents(const base::Time start_of_month);

  // Logs to UMA all event fetch metrics recorded over the lifetime of a
  // calendar session.
  void UploadLifetimeMetrics();

  // Adds `month` to the set of non-prunable months.
  void AddNonPrunableMonth(const base::Time& month);

  // Adds every month in `months` to the set of non-prunable months.
  void AddNonPrunableMonths(const std::set<base::Time>& months);

  // Requests events for the month starting at `start_of_month` if there is not
  // currently a calendar list fetch in progress.
  void MaybeFetchEvents(base::Time start_of_month);

  // Requests events for the month starting at `start_of_month`. If there is no
  // calendar list, or Multi-Calendar is disabled, only primary calendar events
  // are fetched.
  void FetchEvents(base::Time start_of_month);

  // Requests events for the month starting at `start_of_month` for the primary
  // calendar.
  void FetchPrimaryCalendarEvents(const base::Time start_of_month);

  // Cancels any pending event fetch for `start_of_month`.
  void CancelFetch(const base::Time& start_of_month);

  // Gets the number of events of the passed in day.
  int EventsNumberOfDay(base::Time day, SingleDayEventList* events);

  // Finds the event list of the given day, with no impact on our MRU list.  Use
  // this if you don't care about making the month in which `day` resides less
  // likely to be pruned if we need to trim down to stay within storage limits.
  SingleDayEventList FindEvents(base::Time day) const;

  // Uses the `FindEvents` method to get events for that day and then filters
  // the result into two lists of multi-day and same day events.
  std::tuple<SingleDayEventList, SingleDayEventList>
  FindEventsSplitByMultiDayAndSameDay(base::Time day) const;

  // Uses the `FindEvents` method to get events for that day and then filters
  // the result into events that start or end in the next two hours.
  std::list<google_apis::calendar::CalendarEvent> FindUpcomingEvents(
      base::Time now_local) const;

  // Checks the `FetchingStatus` of a given start time.
  FetchingStatus FindFetchingStatus(base::Time start_time);

  // Redistributes all the fetched events to the date map with the
  // time difference. This method is only called when there's a timezone change.
  void RedistributeEvents();

 private:
  // For unit tests.
  friend class CalendarModelTest;
  friend class CalendarMonthViewFetchTest;
  friend class CalendarMonthViewTest;
  friend class CalendarUpNextViewAnimationTest;
  friend class CalendarUpNextViewPixelTest;
  friend class CalendarUpNextViewTest;
  friend class CalendarViewPixelTest;
  friend class CalendarViewAnimationTest;
  friend class CalendarViewEventListViewFetchTest;
  friend class CalendarViewEventListViewTest;
  friend class CalendarViewTest;
  friend class CalendarViewWithUpNextViewAnimationTest;
  friend class CalendarViewWithUpNextViewTest;

  // Checks if the event has allowed statuses and is eligible for insertion.
  bool ShouldInsertEvent(
      const google_apis::calendar::CalendarEvent* event) const;

  // Inserts a single `event` that spans more than one day in the EventCache.
  void InsertMultiDayEvent(const google_apis::calendar::CalendarEvent* event,
                           const base::Time start_of_month);

  // Finds or creates a new SingleMonthEventMap to then insert the `event` into
  // an event list of that month.
  void InsertEventInMonth(const google_apis::calendar::CalendarEvent* event,
                          const base::Time start_of_month,
                          const base::Time start_time_midnight);

  // Inserts a single `event` in a SingleDayEventList of a SingleMonthEventMap.
  void InsertEventInMonthEventList(
      SingleMonthEventMap& month,
      const google_apis::calendar::CalendarEvent* event,
      const base::Time start_time_midnight);

  // Frees up months of events as needed to keep us within storage limits.
  void PruneEventCache();

  // Moves this month to the top of our queue that's ordered from
  // most-recently-used to least-recently-used.
  void PromoteMonth(base::Time start_of_month);

  // Based on error(s) received during a month's fetch(es), notify observers.
  void NotifyObservers(base::Time start_of_month);

  // Actual callback invoked when an event fetch is complete.
  void OnEventsFetched(base::Time start_of_month,
                       std::string calendar_id,
                       google_apis::ApiErrorCode error,
                       const google_apis::calendar::EventList* events);

  // Callback invoked when an event fetch failed with an internal error.
  void OnEventFetchFailedInternalError(
      base::Time start_of_month,
      std::string calendar_id,
      CalendarEventFetchInternalErrorCode error);

  // Internal storage for fetched events, with each fetched month having a
  // map of days to events.
  MonthToEventsMap event_months_;

  // Months whose events we've fetched, in most-recently-used (MRU) order.
  std::deque<base::Time> mru_months_;

  // Set of months that are not prunable.
  std::set<base::Time> non_prunable_months_;

  // Set of months we've already fetched.
  std::set<base::Time> months_fetched_;

  // All fetch requests that are still in-progress. Maps each start of month
  // timestamp to a map linking each calendar ID to a CalendarEventFetch
  // object.
  std::map<base::Time,
           std::map<std::string, std::unique_ptr<CalendarEventFetch>>>
      pending_fetches_;

  // Maps a month to a set of error codes returned by the month's event
  // fetches.
  std::map<base::Time, std::set<google_apis::ApiErrorCode>> fetch_error_codes_;

  // Timestamp of the start of the first event fetch created, for use in
  // duration metrics when Multi-Calendar is enabled.
  base::TimeTicks fetches_start_time_;

  // Maps a non-prunable month to an indicator that equals true if new event
  // fetches for the month have completed successfully.
  std::map<base::Time, bool> events_have_fetched_;

  ScopedSessionObserver session_observer_;

  base::ObserverList<Observer> observers_;

  base::WeakPtrFactory<CalendarModel> weak_factory_{this};
};

}  // namespace ash

#endif  // ASH_SYSTEM_TIME_CALENDAR_MODEL_H_