blob: 83cd8b91c073c96473d71a8de00f3519e4f660ed [file] [log] [blame]
// 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_UI_ASH_GLANCEABLES_GLANCEABLES_CLASSROOM_CLIENT_IMPL_H_
#define CHROME_BROWSER_UI_ASH_GLANCEABLES_GLANCEABLES_CLASSROOM_CLIENT_IMPL_H_
#include <memory>
#include <string>
#include <vector>
#include "ash/glanceables/classroom/glanceables_classroom_client.h"
#include "ash/glanceables/classroom/glanceables_classroom_types.h"
#include "base/containers/flat_map.h"
#include "base/functional/callback_forward.h"
#include "base/gtest_prod_util.h"
#include "base/memory/weak_ptr.h"
#include "base/types/expected.h"
#include "google_apis/common/api_error_codes.h"
#include "google_apis/common/request_sender.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
namespace google_apis::classroom {
class Courses;
class CourseWork;
class StudentSubmissions;
} // namespace google_apis::classroom
namespace net {
struct NetworkTrafficAnnotationTag;
} // namespace net
namespace ash {
// Provides implementation for `GlanceablesClassroomClient`. Responsible for
// communication with Google Classroom API.
class GlanceablesClassroomClientImpl : public GlanceablesClassroomClient {
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)>;
explicit GlanceablesClassroomClientImpl(
const CreateRequestSenderCallback& create_request_sender_callback);
GlanceablesClassroomClientImpl(const GlanceablesClassroomClientImpl&) =
delete;
GlanceablesClassroomClientImpl& operator=(
const GlanceablesClassroomClientImpl&) = delete;
~GlanceablesClassroomClientImpl() override;
// GlanceablesClassroomClient:
void IsStudentRoleActive(IsRoleEnabledCallback callback) override;
void GetCompletedStudentAssignments(
GetStudentAssignmentsCallback callback) override;
void GetStudentAssignmentsWithApproachingDueDate(
GetStudentAssignmentsCallback callback) override;
void GetStudentAssignmentsWithMissedDueDate(
GetStudentAssignmentsCallback callback) override;
void GetStudentAssignmentsWithoutDueDate(
GetStudentAssignmentsCallback callback) override;
private:
FRIEND_TEST_ALL_PREFIXES(GlanceablesClassroomClientImplTest, FetchCourses);
FRIEND_TEST_ALL_PREFIXES(GlanceablesClassroomClientImplTest,
FetchCoursesOnHttpError);
FRIEND_TEST_ALL_PREFIXES(GlanceablesClassroomClientImplTest,
FetchCoursesMultiplePages);
FRIEND_TEST_ALL_PREFIXES(GlanceablesClassroomClientImplTest, FetchCourseWork);
FRIEND_TEST_ALL_PREFIXES(GlanceablesClassroomClientImplTest,
FetchCourseWorkOnHttpError);
FRIEND_TEST_ALL_PREFIXES(GlanceablesClassroomClientImplTest,
FetchCourseWorkMultiplePages);
FRIEND_TEST_ALL_PREFIXES(GlanceablesClassroomClientImplTest,
FetchStudentSubmissions);
FRIEND_TEST_ALL_PREFIXES(GlanceablesClassroomClientImplTest,
FetchStudentSubmissionsOnHttpError);
FRIEND_TEST_ALL_PREFIXES(GlanceablesClassroomClientImplTest,
FetchStudentSubmissionsMultiplePages);
// Done callback for fetching all courses for student or teacher roles.
using FetchCoursesCallback = base::OnceCallback<void(
const std::vector<std::unique_ptr<GlanceablesClassroomCourse>>& courses)>;
// Done callback for fetching all course work items in a course.
using FetchCourseWorkCallback = base::OnceCallback<void(
const std::vector<std::unique_ptr<GlanceablesClassroomCourseWorkItem>>&
course_work)>;
// Done callback for fetching all student submissions in a course.
using FetchStudentSubmissionsCallback = base::OnceCallback<void(
const std::vector<std::unique_ptr<GlanceablesClassroomStudentSubmission>>&
student_submissions)>;
enum class FetchStatus { kNotFetched, kFetching, kFetched };
// Fetches all courses for student and teacher roles and invokes `callback`
// when done.
void FetchStudentCourses(FetchCoursesCallback callback);
void FetchTeacherCourses(FetchCoursesCallback callback);
// Fetches all course work items for the specified `course_id` and invokes
// `callback` when done.
void FetchCourseWork(const std::string& course_id,
FetchCourseWorkCallback callback);
// Fetches all student submissions for the specified `course_id` and invokes
// `callback` when done.
void FetchStudentSubmissions(const std::string& course_id,
FetchStudentSubmissionsCallback callback);
// Delays executing `callback` until all student data are fetched.
void InvokeOnceStudentDataFetched(base::OnceClosure callback);
// Fetches one page of courses.
// `student_id` - restricts returned courses to those having a student
// with the specified identifier. Use an empty string
// to avoid filtering by student id.
// `teacher_id` - restricts returned courses to those having a teacher
// with the specified identifier. Use an empty string
// to avoid filtering by teacher id.
// `page_token` - token specifying the result page to return, comes
// from the previous fetch request. Use an empty string
// to fetch the first page.
// `courses_container` - points to the container in which the response items
// are accumulated.
// `callback` - a callback that runs when all courses for the user
// have been fetched. This may require multiple fetch
// requests, in this case `callback` gets called when
// the final request completes.
void FetchCoursesPage(
const std::string& student_id,
const std::string& teacher_id,
const std::string& page_token,
std::vector<std::unique_ptr<GlanceablesClassroomCourse>>&
courses_container,
FetchCoursesCallback callback);
// Callback for `FetchCoursesPage()`. If `next_page_token()` in the `result`
// is not empty - calls another `FetchCoursesPage()`, otherwise runs done
// `callback`.
void OnCoursesPageFetched(
const std::string& student_id,
const std::string& teacher_id,
std::vector<std::unique_ptr<GlanceablesClassroomCourse>>&
courses_container,
FetchCoursesCallback callback,
base::expected<std::unique_ptr<google_apis::classroom::Courses>,
google_apis::ApiErrorCode> result);
// Callback for `FetchStudentCourses()` or `FetchTeacherCourses()`. Triggers
// fetching course work and student submissions for fetched `courses` and
// invokes `on_course_work_and_student_submissions_fetched` when done.
void OnCoursesFetched(
base::OnceClosure on_course_work_and_student_submissions_fetched,
const std::vector<std::unique_ptr<GlanceablesClassroomCourse>>& courses);
// Fetches one page of course work items.
// `course_id` - identifier of the course.
// `page_token` - token specifying the result page to return, comes from the
// previous fetch request. Use an empty string to fetch the
// first page.
// `callback` - a callback that runs when all course work items in a course
// have been fetched. This may require multiple fetch requests,
// in this case `callback` gets called when the final request
// completes.
void FetchCourseWorkPage(const std::string& course_id,
const std::string& page_token,
FetchCourseWorkCallback callback);
// Callback for `FetchCourseWorkPage()`. If `next_page_token()` in the
// `result` is not empty - calls another `FetchCourseWorkPage()`, otherwise
// runs done `callback`.
void OnCourseWorkPageFetched(
const std::string& course_id,
FetchCourseWorkCallback callback,
base::expected<std::unique_ptr<google_apis::classroom::CourseWork>,
google_apis::ApiErrorCode> result);
// Fetches one page of student submissions.
// `course_id` - identifier of the course.
// `page_token` - token specifying the result page to return, comes from the
// previous fetch request. Use an empty string to fetch the
// first page.
// `callback` - a callback that runs when all student submissions in a
// course have been fetched. This may require multiple fetch
// requests, in this case `callback` gets called when the final
// request completes.
void FetchStudentSubmissionsPage(const std::string& course_id,
const std::string& page_token,
FetchStudentSubmissionsCallback callback);
// Callback for `FetchStudentSubmissionsPage()`. If `next_page_token()` in the
// `result` is not empty - calls another `FetchStudentSubmissionsPage()`,
// otherwise runs done `callback`.
void OnStudentSubmissionsPageFetched(
const std::string& course_id,
FetchStudentSubmissionsCallback callback,
base::expected<
std::unique_ptr<google_apis::classroom::StudentSubmissions>,
google_apis::ApiErrorCode> result);
// Invokes all pending callbacks from `callbacks_waiting_for_student_data_`
// once all student data are fetched (courses + course work + student
// submissions).
void OnStudentDataFetched();
// Selects student assignments that satisfy both filtering predicates below.
// `due_predicate` - returns `true` if passed due date/time
// satisfies filtering requirements.
// `submission_state_predicate` - returns `true` if passed submission state
// satisfies filtering requirements.
// `callback` - invoked with filtered results.
void GetFilteredStudentAssignments(
base::RepeatingCallback<bool(const absl::optional<base::Time>&)>
due_predicate,
base::RepeatingCallback<
bool(GlanceablesClassroomStudentSubmission::State)>
submission_state_predicate,
GetStudentAssignmentsCallback callback);
// Returns lazily initialized `request_sender_`.
google_apis::RequestSender* GetRequestSender();
// 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_;
// Available courses for student and teacher roles.
std::vector<std::unique_ptr<GlanceablesClassroomCourse>> student_courses_;
std::vector<std::unique_ptr<GlanceablesClassroomCourse>> teacher_courses_;
// All course work items grouped by course id.
base::flat_map<
std::string,
std::vector<std::unique_ptr<GlanceablesClassroomCourseWorkItem>>>
course_work_;
// All student submissions grouped by course id.
base::flat_map<
std::string,
std::vector<std::unique_ptr<GlanceablesClassroomStudentSubmission>>>
student_submissions_;
// Fetch status of all student data.
FetchStatus student_data_fetch_status_ = FetchStatus::kNotFetched;
// Pending callbacks awaiting all student data.
std::vector<base::OnceClosure> callbacks_waiting_for_student_data_;
base::WeakPtrFactory<GlanceablesClassroomClientImpl> weak_factory_{this};
};
} // namespace ash
#endif // CHROME_BROWSER_UI_ASH_GLANCEABLES_GLANCEABLES_CLASSROOM_CLIENT_IMPL_H_