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 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290
|
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_ASH_API_TASKS_TASKS_CLIENT_IMPL_H_
#define CHROME_BROWSER_ASH_API_TASKS_TASKS_CLIENT_IMPL_H_
#include <map>
#include <memory>
#include <string>
#include <vector>
#include "ash/api/tasks/tasks_client.h"
#include "base/functional/callback_forward.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/types/expected.h"
#include "google_apis/tasks/tasks_api_requests.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "ui/base/models/list_model.h"
class Profile;
namespace base {
class Time;
} // namespace base
namespace google_apis {
class RequestSender;
namespace tasks {
class TaskLists;
class Tasks;
} // namespace tasks
} // namespace google_apis
namespace ash::api {
struct Task;
struct TaskList;
// Provides implementation for `TasksClient`. Responsible for communication with
// Google Tasks API.
class TasksClientImpl : public TasksClient {
public:
// Provides an instance of `google_apis::RequestSender` for the client.
using CreateRequestSenderCallback =
base::RepeatingCallback<std::unique_ptr<google_apis::RequestSender>(
const std::vector<std::string>& scopes,
const net::NetworkTrafficAnnotationTag& traffic_annotation_tag)>;
TasksClientImpl(
Profile* profile,
const CreateRequestSenderCallback& create_request_sender_callback,
net::NetworkTrafficAnnotationTag traffic_annotation_tag);
TasksClientImpl(const TasksClientImpl&) = delete;
TasksClientImpl& operator=(const TasksClientImpl&) = delete;
~TasksClientImpl() override;
// TasksClient:
bool IsDisabledByAdmin() const override;
const ui::ListModel<api::TaskList>* GetCachedTaskLists() override;
void GetTaskLists(bool force_fetch,
TasksClient::GetTaskListsCallback callback) override;
const ui::ListModel<api::Task>* GetCachedTasksInTaskList(
const std::string& task_list_id) override;
void GetTasks(const std::string& task_list_id,
bool force_fetch,
TasksClient::GetTasksCallback callback) override;
void MarkAsCompleted(const std::string& task_list_id,
const std::string& task_id,
bool completed) override;
void AddTask(const std::string& task_list_id,
const std::string& title,
TasksClient::OnTaskSavedCallback callback) override;
void UpdateTask(const std::string& task_list_id,
const std::string& task_id,
const std::string& title,
bool completed,
TasksClient::OnTaskSavedCallback callback) override;
void InvalidateCache() override;
std::optional<base::Time> GetTasksLastUpdateTime(
const std::string& task_list_id) const override;
void OnGlanceablesBubbleClosed(base::OnceClosure callback) override;
using TaskListsRequestCallback =
base::RepeatingCallback<void(const std::string& page_token)>;
void set_task_lists_request_callback_for_testing(
const TaskListsRequestCallback& callback) {
task_lists_request_callback_ = callback;
}
using TasksRequestCallback =
base::RepeatingCallback<void(const std::string& task_list_id,
const std::string& page_token)>;
void set_tasks_request_callback_for_testing(
const TasksRequestCallback& callback) {
tasks_request_callback_ = callback;
}
private:
enum class FetchStatus { kNotFresh, kRefreshing, kFresh };
// A structure that keeps track of fetch status and list of pending
// callbacks for a task lists fetch request.
struct TaskListsFetchState {
TaskListsFetchState();
~TaskListsFetchState();
FetchStatus status = FetchStatus::kNotFresh;
// Callbacks to be called when all task lists get fetched using tasks API.
// Should be non-empty if a task lists fetch is in progress.
std::vector<TasksClient::GetTaskListsCallback> callbacks;
};
// A structure that keeps track of fetch status and list of pending callbacks
// for a single tasks in a task list fetch request.
struct TasksFetchState {
TasksFetchState();
~TasksFetchState();
FetchStatus status = FetchStatus::kNotFresh;
// The last time that the tasks were fetched and the status became kFresh.
std::optional<base::Time> last_updated_time = std::nullopt;
// Callbacks to be called when all tasks in a task list get fetched using
// tasks API.
// Should be non-empty if a tasks fetch for the target task list is in
// progress.
std::vector<TasksClient::GetTasksCallback> callbacks;
};
// Fetches one page of task lists data.
// `page_token` - token specifying the result page to return, comes from the
// previous fetch request. Use an empty string to fetch the
// first page.
// `page_number` - 1-based page number of this fetch request. Used for UMA
// to track the total number of pages needed to fetch.
// `accumulated_raw_task_lists` - The list of task lists accumulated from
// different task lists pages.
void FetchTaskListsPage(
const std::string& page_token,
int page_number,
std::vector<std::unique_ptr<google_apis::tasks::TaskList>>
accumulated_raw_task_lists);
// Callback for `FetchTaskListsPage()`. Transforms fetched items to
// ash-friendly types. If `next_page_token()` in the `result` is not empty -
// calls another `FetchTaskListsPage()`, otherwise runs
// `RunGetTaskListsCallbacks()`.
void OnTaskListsPageFetched(
const base::Time& request_start_time,
int page_number,
std::vector<std::unique_ptr<google_apis::tasks::TaskList>>
accumulated_raw_task_lists,
base::expected<std::unique_ptr<google_apis::tasks::TaskLists>,
google_apis::ApiErrorCode> result);
// Fetches one page of tasks data.
// `task_list_id` - task list identifier.
// `page_token` - token specifying the result page to return, comes
// from the previous fetch request. Use an empty
// string to fetch the first page.
// `page_number` - 1-based page number of this fetch request. Used
// for UMA to track the total number of pages needed
// to fetch.
// `accumulated_raw_tasks` - in contrast to the task lists conversion logic,
// tasks can't be converted independently on every
// single page response (subtasks could go first,
// but their parent tasks will be on the next page).
// This parameter helps to accumulate all of them
// first and then do the conversion once the last
// page is fetched.
void FetchTasksPage(const std::string& task_list_id,
const std::string& page_token,
int page_number,
std::vector<std::unique_ptr<google_apis::tasks::Task>>
accumulated_raw_tasks);
// Callback for `FetchTasksPage()`. Transforms fetched items to ash-friendly
// types. If `next_page_token()` in the `result` is not empty - calls another
// `FetchTasksPage()`, otherwise runs `RunGetTasksCallbacks()`.
void OnTasksPageFetched(
const std::string& task_list_id,
std::vector<std::unique_ptr<google_apis::tasks::Task>>
accumulated_raw_tasks,
const base::Time& request_start_time,
int page_number,
base::expected<std::unique_ptr<google_apis::tasks::Tasks>,
google_apis::ApiErrorCode> result);
// Callback for `MarkAsCompleted()` request. Does not removes the task from
// `tasks_in_task_lists_` as it will be cleared by
// `OnGlanceablesBubbleClosed`.
void OnMarkedAsCompleted(
const base::Time& request_start_time,
base::RepeatingClosure on_done,
base::expected<std::unique_ptr<google_apis::tasks::Task>,
google_apis::ApiErrorCode> result);
// Done callback for `AddTask()` request.
// `task_list_id` - id of the task list used in the request.
// `request_start_time` - start time of the request to measure latency.
// `callback` - done callback passed from `AddTask`.
// `result` - newly created task or HTTP error.
void OnTaskAdded(const std::string& task_list_id,
const base::Time& request_start_time,
TasksClient::OnTaskSavedCallback callback,
base::expected<std::unique_ptr<google_apis::tasks::Task>,
google_apis::ApiErrorCode> result);
// Done callback for `UpdateTask()` request.
// `task_list_id` - id of the task list used in the request.
// `request_start_time` - start time of the request to measure latency.
// `callback` - done callback passed from `UpdateTask`.
// `result` - updated task or HTTP error.
void OnTaskUpdated(const std::string& task_list_id,
const base::Time& request_start_time,
TasksClient::OnTaskSavedCallback callback,
base::expected<std::unique_ptr<google_apis::tasks::Task>,
google_apis::ApiErrorCode> result);
// To be called when requests to get user's task lists complete.
// It sets the task lists fetch status to `final_fetch_status`, and runs all
// pending callbacks in `task_lists_fetch_state_`. `http_error` will have a
// value from the Google Tasks API request.
void RunGetTaskListsCallbacks(
FetchStatus final_fetch_status,
std::optional<google_apis::ApiErrorCode> http_error,
std::vector<std::unique_ptr<google_apis::tasks::TaskList>>
accumulated_raw_task_lists);
// To be called when requests to get tasks in the task list identified by
// `task_list_id` complete. It sets fetch status for the task list fetch to
// `final_fetch_status`, and runs all pending callbacks for the task list
// (kept in `tasks_fetch_state_` map). The callbacks are run with `tasks`.
void RunGetTasksCallbacks(
const std::string& task_list_id,
FetchStatus final_fetch_status,
std::optional<google_apis::ApiErrorCode> http_error,
std::vector<std::unique_ptr<google_apis::tasks::Task>>
accumulated_raw_tasks);
// A map of `task_list_id` to a set of `task_id` that are pending to be
// completed.
std::map<std::string, std::set<std::string>> pending_completed_tasks_;
// Returns lazily initialized `request_sender_`.
google_apis::RequestSender* GetRequestSender();
// The profile for which this instance was created.
const raw_ptr<Profile> profile_;
// Callback passed from `GlanceablesKeyedService` that creates
// `request_sender_`.
const CreateRequestSenderCallback create_request_sender_callback_;
// Helper class that sends requests, handles retries and authentication.
std::unique_ptr<google_apis::RequestSender> request_sender_;
// The current fetch state for the users task lists.
TaskListsFetchState task_lists_fetch_state_;
// All available task lists.
ui::ListModel<TaskList> task_lists_;
// All available tasks grouped by task list id.
std::map<std::string, ui::ListModel<Task>> tasks_in_task_lists_;
// Map that contains fetch states for tasks requests from different task
// lists. Mapped by the task list id.
std::map<std::string, std::unique_ptr<TasksFetchState>> tasks_fetch_state_;
// Stub tasks list model that can be used to return an empty task list to
// `GetTasks()` requests.
ui::ListModel<Task> stub_task_list_;
// Callbacks invoked whenever a tasks API request is made. Used primarily
// in tests.
TaskListsRequestCallback task_lists_request_callback_;
TasksRequestCallback tasks_request_callback_;
const net::NetworkTrafficAnnotationTag traffic_annotation_tag_;
base::WeakPtrFactory<TasksClientImpl> weak_factory_{this};
};
} // namespace ash::api
#endif // CHROME_BROWSER_ASH_API_TASKS_TASKS_CLIENT_IMPL_H_
|