File: clipboard_image_model_request.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 (223 lines) | stat: -rw-r--r-- 8,099 bytes parent folder | download | duplicates (3)
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
// Copyright 2020 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_CLIPBOARD_CLIPBOARD_IMAGE_MODEL_REQUEST_H_
#define CHROME_BROWSER_UI_ASH_CLIPBOARD_CLIPBOARD_IMAGE_MODEL_REQUEST_H_

#include <memory>
#include <optional>
#include <string>

#include "base/memory/raw_ptr.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "base/unguessable_token.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/browser/web_contents_observer.h"
#include "ui/base/models/image_model.h"

class AccountId;

namespace ash {
class ScopedClipboardHistoryPause;
}  // namespace ash

namespace ui {
class ClipboardData;
}  // namespace ui

namespace views {
class WebView;
class Widget;
}  // namespace views

// Renders html in an off-screen WebView, copies the rendered surface, and
// passes the copy through |deliver_image_model_callback_|. If the request takes
// takes more than 5s to load, timeout is declared and the callback is not
// called. If the request is Stop()-ed, the callback is not called.
class ClipboardImageModelRequest : public content::WebContentsDelegate,
                                   public content::WebContentsObserver {
 public:
  using ImageModelCallback = base::OnceCallback<void(ui::ImageModel)>;

  struct Params {
    Params() = delete;
    Params(const base::UnguessableToken& id,
           const std::string& html_markup,
           const gfx::Size& bounding_box_size,
           ImageModelCallback request_finished_callback);
    Params(Params&&);
    Params& operator=(Params&&);
    ~Params();

    // A unique identifier, used to cancel running requests.
    base::UnguessableToken id;
    // Markup being rendered.
    std::string html_markup;

    // The size of the rectangle which encloses the selection region on the
    // original page. It is used to calculate the size of the HTML preview image
    // shown on the clipboard history menu.
    gfx::Size bounding_box_size;

    // The callback to return the results of the request. Not called if the
    // request is stopped via Stop(), or if timeout occurs.
    ImageModelCallback callback;
  };

  using RequestStopCallback = base::RepeatingCallback<void(bool)>;

  struct TestParams {
    TestParams() = delete;
    explicit TestParams(
        RequestStopCallback callback,
        const std::optional<bool>& enforce_auto_resize = std::nullopt);
    TestParams(const TestParams&) = delete;
    TestParams& operator=(const TestParams&) = delete;
    ~TestParams();

    // The callback running when the image model request stops. The boolean
    // value indicates whether the image model request renders web contents
    // in auto resize mode.
    RequestStopCallback callback;

    // When set, `enforce_auto_resize` specifies whether the image model request
    // should be rendered in auto resize mode. If `enforce_auto_resize` is
    // true (or false), auto resize mode is always enabled (or disabled).
    std::optional<bool> enforce_auto_resize;
  };

  // Places `html_markup` on the clipboard and restores the original clipboard
  // contents when destructed.
  class ScopedClipboardModifier {
   public:
    explicit ScopedClipboardModifier(const std::string& html_markup);
    ScopedClipboardModifier(const ScopedClipboardModifier&) = delete;
    ScopedClipboardModifier& operator=(const ScopedClipboardModifier&) = delete;
    ~ScopedClipboardModifier();

   private:
    // Pauses ash::ClipboardHistory for its lifetime.
    std::unique_ptr<ash::ScopedClipboardHistoryPause>
        scoped_clipboard_history_pause_;
    std::unique_ptr<ui::ClipboardData> replaced_clipboard_data_;
  };

  ClipboardImageModelRequest(
      const AccountId& account_id,
      base::RepeatingClosure on_request_finished_callback);
  ClipboardImageModelRequest(const ClipboardImageModelRequest&) = delete;
  ClipboardImageModelRequest operator=(const ClipboardImageModelRequest&) =
      delete;
  ~ClipboardImageModelRequest() override;

  // Renders the HTML in a WebView and attempts to copy the surface. If this
  // fails to load after 5 seconds, OnTimeout is called.
  void Start(Params&& params);

  // The different reasons a request can `Stop()`. These values are logged to
  // UMA. Entries should not be renumbered and numeric values should never be
  // reused. Please keep in sync with "RequestStopReason" in
  // src/tools/metrics/histograms/enums.xml.
  enum class RequestStopReason {
    kFulfilled = 0,
    kTimeout = 1,
    kEmptyResult = 2,
    kMultipleCopyCompletion = 3,
    kRequestCanceled = 4,
    kMaxValue = kRequestCanceled,
  };
  // Stops the request and resets state. `stop_reason` is the reason the request
  // was `Stop()`-ed. |web_view_| is kept alive to enable fast restarting of the
  // request.
  void Stop(RequestStopReason stop_reason);

  // `Stop()`s the request and gets the params of the running request.
  Params StopAndGetParams();

  // Whether the clipboard is being modified by this request.
  bool IsModifyingClipboard() const;

  // Returns whether a request with |request_id| is running, or if any request
  // is running if no |request_id| is supplied.
  bool IsRunningRequest(
      std::optional<base::UnguessableToken> request_id = std::nullopt) const;

  // content::WebContentsDelegate:
  void ResizeDueToAutoResize(content::WebContents* web_contents,
                             const gfx::Size& new_size) override;

  // content::WebContentsObserver:
  void DidStopLoading() override;

  // Configures test parameter.
  static void SetTestParams(TestParams* test_params);

 private:
  // Called when the results of the paste are painted.
  void OnVisualStateChangeFinished(bool done);

  // Posts `CopySurface()` to the task sequence.
  void PostCopySurfaceTask();

  // Copies the rendered HTML.
  void CopySurface();

  // Callback called when the rendered surface is done being copied.
  void OnCopyComplete(float device_scale_factor, const SkBitmap& bitmap);

  // Called when the running request takes too long to complete.
  void OnTimeout();

  // Returns whether the auto-resize mode should be enabled. If auto-resize mode
  // is enabled, Blink decides the preview image's size which may be different
  // from that of the original selection region.
  bool ShouldEnableAutoResizeMode() const;

  // A Widget that is not shown, but forces |web_view_| to render.
  std::unique_ptr<views::Widget> const widget_;

  // Contents view of |widget_|. Owned by |widget_|.
  const raw_ptr<views::WebView> web_view_;

  // Unique identifier for this request run. Empty when there are no running
  // requests.
  base::UnguessableToken request_id_;

  // The HTML being rendered.
  std::string html_markup_;

  // The size of the rectangle enclosing the copied HTML on the original page.
  gfx::Size bounding_box_size_;

  // Whether `DidStopLoading()` was called. Used to prevent the request from
  // responding to load events that happen after the initial load.
  bool did_stop_loading_ = false;

  // Responsible for temporarily replacing contents of the clipboard.
  std::optional<ScopedClipboardModifier> scoped_clipboard_modifier_;

  // Callback used to deliver the rendered ImageModel.
  ImageModelCallback deliver_image_model_callback_;

  // Callback called when this request finishes (via timeout or completion).
  base::RepeatingClosure on_request_finished_callback_;

  // Timer used to abort requests which take longer than 5s to load.
  base::RepeatingTimer timeout_timer_;

  // Time this object was created. Used to log object lifetime.
  const base::TimeTicks request_creation_time_;

  // Time this object started its most recent request.
  base::TimeTicks request_start_time_;

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

  // Used to debounce calls to `CopySurface()`.
  base::WeakPtrFactory<ClipboardImageModelRequest>
      copy_surface_weak_ptr_factory_{this};
};

#endif  // CHROME_BROWSER_UI_ASH_CLIPBOARD_CLIPBOARD_IMAGE_MODEL_REQUEST_H_