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 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_
|