File: mahi_ui_controller.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 (227 lines) | stat: -rw-r--r-- 8,243 bytes parent folder | download | duplicates (6)
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
// Copyright 2024 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_MAHI_MAHI_UI_CONTROLLER_H_
#define ASH_SYSTEM_MAHI_MAHI_UI_CONTROLLER_H_

#include <cstdint>
#include <memory>
#include <optional>
#include <string>
#include <vector>

#include "ash/ash_export.h"
#include "ash/public/cpp/session/session_observer.h"
#include "ash/system/mahi/mahi_ui_update.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/scoped_observation.h"
#include "base/scoped_observation_traits.h"
#include "chromeos/components/mahi/public/cpp/mahi_manager.h"
#include "ui/views/widget/unique_widget_ptr.h"

namespace views {
class View;
}  // namespace views

class AccountId;

namespace ash {

// Communicates with `chromeos::MahiManager` and notifies delegates of updates.
class ASH_EXPORT MahiUiController : public SessionObserver {
 public:
  // Establishes the connection between `MahiUiController` and dependent views.
  class Delegate : public base::CheckedObserver {
   public:
    explicit Delegate(MahiUiController* ui_controller);
    Delegate(const Delegate&) = delete;
    Delegate& operator=(const Delegate&) = delete;
    ~Delegate() override;

    // Returns the view that associates with the delegate.
    virtual views::View* GetView() = 0;

    // Returns the visibility of the delegate's associated view for `state`.
    virtual bool GetViewVisibility(VisibilityState state) const = 0;

    // Notifies of a Mahi UI update.
    virtual void OnUpdated(const MahiUiUpdate& update) {}

   private:
    base::ScopedObservation<MahiUiController, Delegate> observation_{this};
  };

  // Lists question sources.
  // Note: this should be kept in sync with `MahiQuestionSource` enum in
  // tools/metrics/histograms/metadata/ash/enums.xml
  enum class QuestionSource {
    // From the Mahi menu view.
    kMenuView,

    // From the Mahi panel view.
    kPanel,

    // From the retry button.
    kRetry,

    kMaxValue = kRetry,
  };

  MahiUiController();
  MahiUiController(const MahiUiController&) = delete;
  MahiUiController& operator=(const MahiUiController&) = delete;
  ~MahiUiController() override;

  void AddDelegate(Delegate* delegate);
  void RemoveDelegate(Delegate* delegate);

  // Opens/closes the mahi panel on the display associated with `display_id`.
  // The panel is positioned on top of the provided `mahi_menu_bounds`.
  // `elucidation_in_use` indicates this panel is to present simplified text
  // (instead of summary).
  void OpenMahiPanel(int64_t display_id,
                     const gfx::Rect& mahi_menu_bounds,
                     bool elucidation_in_use);
  void CloseMahiPanel();

  bool IsMahiPanelOpen();

  // Navigates to the Q&A view and notifies delegates.
  void NavigateToQuestionAnswerView();

  // Navigates to the summary & outlines section and notifies delegates.
  void NavigateToSummaryOutlinesSection();

  // Notifies delegates that there is a content refresh availability change.
  void NotifyRefreshAvailabilityChanged(bool available);

  // Notifies delegates that the panel bounds have changed.
  // Some delegates (like the summary and Q&A views) have a maximum width on
  // their child view based on the panel bounds. Because of this, we cannot rely
  // on OnBoundsChanged in those views and must notify them directly.
  void NotifyPanelBoundsChanged(const gfx::Rect& panel_bounds);

  // Updates the content icon and title, calls `UpdateSummaryAndOutlines` and
  // navigates to the summary view.
  void RefreshContents();

  // Retries the operation associated with `origin_state`.
  // If `origin_state` is `VisibilityState::kQuestionAndAnswer`, re-asks the
  // question.
  // If `origin_state` is `VisibilityState::kSummaryAndOutlines`, regenerates
  // the summary & outlines.
  // NOTE: `origin_state` should not be `VisibilityState::kError`.
  void Retry(VisibilityState origin_state);

  // Sends `question` to the backend. `current_panel_content` determines if the
  // `question` is regarding the current content displayed on the panel.
  // `source` indicates where `question` is posted.
  // If `update_summary_after_answer_question` is true, a request to update the
  // summary view will be made when the answer is loaded.
  void SendQuestion(const std::u16string& question,
                    bool current_panel_content,
                    QuestionSource source,
                    bool update_summary_after_answer_question = false);

  // Sends requests to the backend to update summary and outlines.
  // `delegates_` will be notified of the updated summary and outlines when
  // requests are fulfilled.
  void UpdateSummaryAndOutlines();

  // Sends requests to the backend to update elucidation.
  // `delegates_` will be notified of the updated elucidation when requests are
  // fulfilled.
  void UpdateElucidation();

  // Records histogram that tracks the amount of times the panel was opened
  // during an active session.
  void RecordTimesPanelOpenedMetric();

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

  views::Widget* mahi_panel_widget() { return mahi_panel_widget_.get(); }

  void set_elucidation_in_use_for_testing(bool elucidation_in_use) {
    elucidation_in_use_ = elucidation_in_use;
  }

 private:
  void HandleError(const MahiUiError& error);

  // Notifies `delegates_` of `update`.
  void NotifyUiUpdate(const MahiUiUpdate& update);

  // Sets the visibility state and notifies `delegates_` of `update`.
  void SetVisibilityStateAndNotifyUiUpdate(VisibilityState state,
                                           const MahiUiUpdate& update);

  // Callbacks of `chromeos::MahiManager` APIs ---------------------------------

  void OnAnswerLoaded(std::optional<std::u16string> answer,
                      chromeos::MahiResponseStatus status);

  void OnOutlinesLoaded(std::vector<chromeos::MahiOutline> outlines,
                        chromeos::MahiResponseStatus status);

  // TODO(crbug.com/375944360): avoid u16string copy
  void OnSummaryLoaded(std::u16string summary_text,
                       chromeos::MahiResponseStatus status);

  void OnElucidationLoaded(std::u16string elucidation_text,
                           chromeos::MahiResponseStatus status);
  // Invalidates pending summary/outline/QA requests on new request to avoid
  // racing.
  void InvalidatePendingRequests();

  // The current state. Use `VisibilityState::kSummaryAndOutlines` by default.
  VisibilityState visibility_state_ =
      VisibilityState::kSummaryAndOutlinesAndElucidation;

  base::ObserverList<Delegate> delegates_;

  views::UniqueWidgetPtr mahi_panel_widget_;

  // Used to record metrics. The count will be increased by one every time the
  // panel is opened, and reset to zero when the metric is recorded, which
  // happens when the session is no longer active or on shutdown.
  int times_panel_opened_per_session_ = 0;

  // Indicates the params of the most recent question.
  // Set when the controller receives a request to send a question.
  // Reset when the content is refreshed.
  std::optional<MahiQuestionParams> most_recent_question_params_;

  // Indicates that we need to update summary after answer is fully loaded.
  bool update_summary_after_answer_question_ = false;

  // Indicates that the active result panel is for elucidation (simplified
  // text).
  bool elucidation_in_use_ = false;

  base::WeakPtrFactory<MahiUiController> weak_ptr_factory_{this};
};

}  // namespace ash

namespace base {

template <>
struct ScopedObservationTraits<ash::MahiUiController,
                               ash::MahiUiController::Delegate> {
  static void AddObserver(ash::MahiUiController* controller,
                          ash::MahiUiController::Delegate* delegate) {
    controller->AddDelegate(delegate);
  }
  static void RemoveObserver(ash::MahiUiController* controller,
                             ash::MahiUiController::Delegate* delegate) {
    controller->RemoveDelegate(delegate);
  }
};

}  // namespace base

#endif  // ASH_SYSTEM_MAHI_MAHI_UI_CONTROLLER_H_