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
ash / quick_insert / quick_insert_controller.h [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 ASH_QUICK_INSERT_QUICK_INSERT_CONTROLLER_H_
#define ASH_QUICK_INSERT_QUICK_INSERT_CONTROLLER_H_
#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include <vector>
#include "ash/ash_export.h"
#include "ash/quick_insert/metrics/quick_insert_feature_usage_metrics.h"
#include "ash/quick_insert/metrics/quick_insert_session_metrics.h"
#include "ash/quick_insert/model/quick_insert_emoji_history_model.h"
#include "ash/quick_insert/model/quick_insert_emoji_suggester.h"
#include "ash/quick_insert/model/quick_insert_model.h"
#include "ash/quick_insert/quick_insert_asset_fetcher_impl_delegate.h"
#include "ash/quick_insert/quick_insert_caps_lock_bubble_controller.h"
#include "ash/quick_insert/quick_insert_insert_media_request.h"
#include "ash/quick_insert/quick_insert_search_result.h"
#include "ash/quick_insert/quick_insert_suggestions_controller.h"
#include "ash/quick_insert/quick_insert_web_paste_target.h"
#include "ash/quick_insert/search/quick_insert_search_controller.h"
#include "ash/quick_insert/views/quick_insert_feature_tour.h"
#include "ash/quick_insert/views/quick_insert_view_delegate.h"
#include "base/functional/callback_forward.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/scoped_observation.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "ui/base/emoji/emoji_panel_helper.h"
#include "ui/events/devices/device_data_manager.h"
#include "ui/events/devices/input_device_event_observer.h"
#include "ui/views/view_observer.h"
#include "ui/views/widget/unique_widget_ptr.h"
class PrefRegistrySimple;
class PrefService;
namespace input_method {
class ImeKeyboard;
}
namespace ui {
class TextInputClient;
}
namespace network {
class SharedURLLoaderFactory;
} // namespace network
namespace ash {
class QuickInsertAssetFetcher;
class QuickInsertClient;
class QuickInsertModel;
class QuickInsertPasteRequest;
class QuickInsertActionOnNextFocusRequest;
// Controls a Quick Insert widget.
class ASH_EXPORT QuickInsertController
: public QuickInsertViewDelegate,
public views::ViewObserver,
public QuickInsertAssetFetcherImplDelegate {
public:
QuickInsertController();
QuickInsertController(const QuickInsertController&) = delete;
QuickInsertController& operator=(const QuickInsertController&) = delete;
~QuickInsertController() override;
// Maximum time to wait for focus to be regained after completing the feature
// tour. If this timeout is reached, we stop waiting for focus and show the
// Quick Insert widget regardless of the focus state.
static constexpr base::TimeDelta kShowWidgetPostFeatureTourTimeout =
base::Seconds(2);
// Time from when the insert is issued and when we give up inserting.
static constexpr base::TimeDelta kInsertMediaTimeout = base::Seconds(2);
// Time from when a search starts to when the first set of results are
// published.
static constexpr base::TimeDelta kBurnInPeriod = base::Milliseconds(200);
// Registers Quick Insert prefs to the provided `registry`.
static void RegisterProfilePrefs(PrefRegistrySimple* registry);
// Sets the `client` used by this class and the widget to communicate with the
// browser. `client` may be set to null, which will close the Widget if it's
// open, and may call "stop search" methods on the PREVIOUS client.
// If `client` is not null, then it must remain valid for the lifetime of this
// class, or until AFTER `SetClient` is called with a different client.
// Caution: If `client` outlives this class, the client should avoid calling
// this method on a destructed class instance to avoid a use after free.
void SetClient(QuickInsertClient* client);
// This should be run when the Prefs from the client is ready.
void OnClientPrefsSet(PrefService* prefs);
// Toggles the visibility of the Quick Insert widget.
// This must only be called after `SetClient` is called with a valid client.
// `trigger_event_timestamp` is the timestamp of the event that triggered the
// Widget to be toggled. For example, if the feature was triggered by a mouse
// click, then it should be the timestamp of the click. By default, the
// timestamp is the time this function is called.
void ToggleWidget(
base::TimeTicks trigger_event_timestamp = base::TimeTicks::Now());
// Returns the Quick Insert widget for tests.
views::Widget* widget_for_testing() { return widget_.get(); }
QuickInsertFeatureTour& feature_tour_for_testing() { return feature_tour_; }
QuickInsertCapsLockBubbleController&
caps_lock_bubble_controller_for_testing() {
return caps_lock_bubble_controller_;
}
// QuickInsertViewDelegate:
std::vector<QuickInsertCategory> GetAvailableCategories() override;
void GetZeroStateSuggestedResults(SuggestedResultsCallback callback) override;
void GetResultsForCategory(QuickInsertCategory category,
SearchResultsCallback callback) override;
void StartSearch(std::u16string_view query,
std::optional<QuickInsertCategory> category,
SearchResultsCallback callback) override;
void StopSearch() override;
void StartEmojiSearch(std::u16string_view,
EmojiSearchResultsCallback callback) override;
void CloseWidgetThenInsertResultOnNextFocus(
const QuickInsertSearchResult& result) override;
void OpenResult(const QuickInsertSearchResult& result) override;
void ShowEmojiPicker(ui::EmojiPickerCategory category,
std::u16string_view query) override;
void ShowEditor(std::optional<std::string> preset_query_id,
std::optional<std::string> freeform_text) override;
void ShowLobster(std::optional<std::string> freeform_text) override;
QuickInsertAssetFetcher* GetAssetFetcher() override;
QuickInsertSessionMetrics& GetSessionMetrics() override;
QuickInsertActionType GetActionForResult(
const QuickInsertSearchResult& result) override;
std::vector<QuickInsertEmojiResult> GetSuggestedEmoji() override;
bool IsGifsEnabled() override;
QuickInsertModeType GetMode() override;
QuickInsertCapsLockPosition GetCapsLockPosition() override;
// views:ViewObserver:
void OnViewIsDeleting(views::View* view) override;
// QuickInsertAssetFetcherImplDelegate:
scoped_refptr<network::SharedURLLoaderFactory> GetSharedURLLoaderFactory()
override;
void FetchFileThumbnail(const base::FilePath& path,
const gfx::Size& size,
FetchFileThumbnailCallback callback) override;
// Disables the feature tour. Only works in tests.
static void DisableFeatureTourForTesting();
private:
// Trigger source for showing the Quick Insert widget. This is used to
// determine how the widget should be shown on the screen.
enum class WidgetTriggerSource {
// The user triggered Quick Insert as part of their usual user flow, e.g.
// toggled Quick Insert with a key press.
kDefault,
// The user triggered Quick Insert by completing the feature tour.
kFeatureTour,
};
// Active Quick Insert session tied to the lifetime of the QuickInsertWidget.
struct Session {
QuickInsertModel model;
QuickInsertEmojiHistoryModel emoji_history_model;
QuickInsertEmojiSuggester emoji_suggester;
QuickInsertSessionMetrics session_metrics;
// Periodically records usage metrics based on the Standard Feature Usage
// Logging (SFUL) framework.
QuickInsertFeatureUsageMetrics feature_usage_metrics;
Session(PrefService* prefs,
ui::TextInputClient* focused_client,
input_method::ImeKeyboard* ime_keyboard,
QuickInsertModel::EditorStatus editor_status,
QuickInsertModel::LobsterStatus lobster_status,
QuickInsertEmojiSuggester::GetNameCallback get_name);
~Session();
};
void ShowWidget(base::TimeTicks trigger_event_timestamp,
WidgetTriggerSource trigger_source);
void CloseWidget();
void ShowWidgetPostFeatureTour();
void InsertResultOnNextFocus(const QuickInsertSearchResult& result);
void OnInsertCompleted(const QuickInsertRichMedia& media,
QuickInsertInsertMediaRequest::Result result);
PrefService* GetPrefs();
std::optional<QuickInsertWebPasteTarget> GetWebPasteTarget();
QuickInsertFeatureTour feature_tour_;
QuickInsertCapsLockBubbleController caps_lock_bubble_controller_;
std::unique_ptr<Session> session_;
views::UniqueWidgetPtr widget_;
std::unique_ptr<QuickInsertAssetFetcher> asset_fetcher_;
std::unique_ptr<QuickInsertInsertMediaRequest> insert_media_request_;
std::unique_ptr<QuickInsertPasteRequest> paste_request_;
std::unique_ptr<QuickInsertActionOnNextFocusRequest> caps_lock_request_;
QuickInsertSuggestionsController suggestions_controller_;
QuickInsertSearchController search_controller_;
raw_ptr<QuickInsertClient> client_ = nullptr;
base::OnceCallback<void(std::optional<std::string> preset_query_id,
std::optional<std::string> freeform_text)>
show_editor_callback_;
base::OnceCallback<void(std::optional<std::string> freeform_text)>
show_lobster_callback_;
// Timer used to delay closing the Widget for accessibility.
base::OneShotTimer close_widget_delay_timer_;
base::ScopedObservation<views::View, views::ViewObserver> view_observation_{
this};
base::WeakPtrFactory<QuickInsertController> weak_ptr_factory_{this};
};
} // namespace ash
#endif // ASH_QUICK_INSERT_QUICK_INSERT_CONTROLLER_H_