File: download_browsertest_utils.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 (291 lines) | stat: -rw-r--r-- 11,977 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
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
// 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_DOWNLOAD_DOWNLOAD_BROWSERTEST_UTILS_H_
#define CHROME_BROWSER_DOWNLOAD_DOWNLOAD_BROWSERTEST_UTILS_H_

#include <stddef.h>

#include "base/files/file_path.h"
#include "base/memory/raw_ptr.h"
#include "chrome/browser/download/download_test_file_activity_observer.h"
#include "chrome/browser/extensions/install_verifier.h"
#include "chrome/browser/web_applications/test/os_integration_test_override_impl.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "content/public/test/download_test_observer.h"
#include "content/public/test/slow_download_http_response.h"
#include "content/public/test/test_download_http_response.h"
#include "content/public/test/test_file_error_injector.h"
#include "extensions/browser/scoped_ignore_content_verifier_for_test.h"
#include "ui/base/window_open_disposition.h"

class DownloadPrefs;

// Gets the download manager for a browser.
content::DownloadManager* DownloadManagerForBrowser(Browser* browser);

// Sets the kPromptForDownload pref on `browser`. Generally this should be used
// with `prompt_for_download` false, as prompting for download location in a
// browser test will make the download time out.
void SetPromptForDownload(Browser* browser, bool prompt_for_download);

// DownloadTestObserver subclass that observes one download until it transitions
// from a non-resumable state to a resumable state a specified number of
// times. Note that this observer can only observe a single download.
class DownloadTestObserverResumable : public content::DownloadTestObserver {
 public:
  // Construct a new observer. |transition_count| is the number of times the
  // download should transition from a non-resumable state to a resumable state.
  DownloadTestObserverResumable(content::DownloadManager* download_manager,
                                size_t transition_count);

  DownloadTestObserverResumable(const DownloadTestObserverResumable&) = delete;
  DownloadTestObserverResumable& operator=(
      const DownloadTestObserverResumable&) = delete;

  ~DownloadTestObserverResumable() override;

 private:
  bool IsDownloadInFinalState(download::DownloadItem* download) override;

  bool was_previously_resumable_ = false;
  size_t transitions_left_;
};

// DownloadTestObserver subclass that observes a download until it transitions
// from IN_PROGRESS to another state, but only after StartObserving() is called.
class DownloadTestObserverNotInProgress : public content::DownloadTestObserver {
 public:
  DownloadTestObserverNotInProgress(content::DownloadManager* download_manager,
                                    size_t count);

  DownloadTestObserverNotInProgress(const DownloadTestObserverNotInProgress&) =
      delete;
  DownloadTestObserverNotInProgress& operator=(
      const DownloadTestObserverNotInProgress&) = delete;

  ~DownloadTestObserverNotInProgress() override;

  void StartObserving();

 private:
  bool IsDownloadInFinalState(download::DownloadItem* download) override;

  bool started_observing_;
};

class DownloadTestBase : public InProcessBrowserTest {
 public:
  // Choice of navigation or direct fetch.  Used by |DownloadFileCheckErrors()|.
  enum DownloadMethod { DOWNLOAD_NAVIGATE, DOWNLOAD_DIRECT };

  // Information passed in to |DownloadFileCheckErrors()|.
  struct DownloadInfo {
    const char* starting_url;           // URL for initiating the download.
    const char* expected_download_url;  // Expected value of DI::GetURL(). Can
                                        // be different if |starting_url|
                                        // initiates a download from another
                                        // URL.
    DownloadMethod download_method;     // Navigation or Direct.
    // Download interrupt reason (NONE is OK).
    download::DownloadInterruptReason reason;
    bool show_download_item;  // True if the download item appears on the shelf.
    bool should_redirect_to_documents;  // True if we save it in "My Documents".
  };

  struct FileErrorInjectInfo {
    DownloadInfo download_info;
    content::TestFileErrorInjector::FileErrorInfo error_info;
  };

  static constexpr char kDownloadTest1Path[] = "download-test1.lib";
#if BUILDFLAG(IS_WIN)
  static constexpr char kDangerousMockFilePath[] =
      "/downloads/dangerous/dangerous.exe";
#elif BUILDFLAG(IS_POSIX)
  // TODO(crbug.com/40800578): Find an actually "dangerous" extension for
  // Fuchsia.
  static constexpr char kDangerousMockFilePath[] =
      "/downloads/dangerous/dangerous.sh";
#endif

  DownloadTestBase();
  ~DownloadTestBase() override;

  void SetUpOnMainThread() override;
  void SetUpCommandLine(base::CommandLine* command_line) override;
  void TearDownOnMainThread() override;

  bool CheckTestDir();

  // Returning false indicates a failure of the setup, and should be asserted
  // in the caller.
  bool InitialSetup();

 protected:
  enum SizeTestType {
    SIZE_TEST_TYPE_KNOWN,
    SIZE_TEST_TYPE_UNKNOWN,
  };

  base::FilePath GetTestDataDirectory();

  // Location of the file source (the place from which it is downloaded).
  base::FilePath OriginFile(const base::FilePath& file);

  // Location of the file destination (place to which it is downloaded).
  base::FilePath DestinationFile(Browser* browser, const base::FilePath& file);

  content::TestDownloadResponseHandler* test_response_handler();

  DownloadPrefs* GetDownloadPrefs(Browser* browser);

  base::FilePath GetDownloadDirectory(Browser* browser);

  // Create a DownloadTestObserverTerminal that will wait for the
  // specified number of downloads to finish.
  content::DownloadTestObserver* CreateWaiter(Browser* browser,
                                              int num_downloads);

  // Create a DownloadTestObserverInProgress that will wait for the
  // specified number of downloads to start.
  content::DownloadTestObserver* CreateInProgressWaiter(Browser* browser,
                                                        int num_downloads);

  // Create a DownloadTestObserverTerminal that will wait for the
  // specified number of downloads to finish, or for
  // a dangerous download warning to be shown.
  content::DownloadTestObserver* DangerousDownloadWaiter(
      Browser* browser,
      int num_downloads,
      content::DownloadTestObserver::DangerousDownloadAction
          dangerous_download_action);

  void CheckDownloadStatesForBrowser(
      Browser* browser,
      size_t num,
      download::DownloadItem::DownloadState state);

  void CheckDownloadStates(size_t num,
                           download::DownloadItem::DownloadState state);

  bool VerifyNoDownloads() const;

  // Download |url|, then wait for the download to finish.
  // |disposition| indicates where the navigation occurs (current tab, new
  // foreground tab, etc).
  // |browser_test_flags| indicate what to wait for, and is an OR of 0 or more
  // values in the ui_test_utils::BrowserTestWaitFlags enum.
  // |prompt_for_download| indicates whether to prompt for the download location
  // and should generally be false, since the download location prompt can
  // cause the browser test to time out.
  void DownloadAndWaitWithDisposition(Browser* browser,
                                      const GURL& url,
                                      WindowOpenDisposition disposition,
                                      int browser_test_flags,
                                      bool prompt_for_download = false);

  // Download a file in the current tab, then wait for the download to finish.
  void DownloadAndWait(Browser* browser,
                       const GURL& url,
                       bool prompt_for_download = false);

  // Should only be called when the download is known to have finished
  // (in error or not).
  // Returning false indicates a failure of the function, and should be asserted
  // in the caller.
  bool CheckDownload(Browser* browser,
                     const base::FilePath& downloaded_filename,
                     const base::FilePath& origin_filename);

  // A version of CheckDownload that allows complete path specification.
  bool CheckDownloadFullPaths(Browser* browser,
                              const base::FilePath& downloaded_file,
                              const base::FilePath& origin_file);

  // Creates an in-progress download and returns a pointer to its DownloadItem.
  // Either supply a `browser` or the `browser()` in the test fixture will be
  // used.
  download::DownloadItem* CreateSlowTestDownload(Browser* browser = nullptr);

  bool RunSizeTest(Browser* browser,
                   SizeTestType type,
                   const std::string& partial_indication,
                   const std::string& total_indication);

  void GetDownloads(
      Browser* browser,
      std::vector<raw_ptr<download::DownloadItem, VectorExperimental>>*
          downloads) const;

  static void ExpectWindowCountAfterDownload(size_t expected);

  void EnableFileChooser(bool enable);
  bool DidShowFileChooser();

  // Allows the ChromeDownloadManagerDelegate to open downloads.
  void SetAllowOpenDownload(bool allow);

  // Checks that |path| is has |file_size| bytes, and matches the |value|
  // string.
  bool VerifyFile(const base::FilePath& path,
                  const std::string& value,
                  const int64_t file_size);

  // Attempts to download a file, based on information in |download_info|.
  // If a Select File dialog opens, will automatically choose the default.
  void DownloadFilesCheckErrorsSetup();

  // Attempts to download a set of files, based on information in the
  // |download_info| array.  |count| is the number of files.
  // If a Select File dialog appears, it will choose the default and return
  // immediately.
  void DownloadFilesCheckErrors(size_t count, DownloadInfo* download_info);
  void DownloadFilesCheckErrorsLoopBody(const DownloadInfo& download_info,
                                        size_t i);

  void DownloadInsertFilesErrorCheckErrors(size_t count,
                                           FileErrorInjectInfo* info);
  void DownloadInsertFilesErrorCheckErrorsLoopBody(
      scoped_refptr<content::TestFileErrorInjector> injector,
      const FileErrorInjectInfo& info,
      size_t i);

  // Attempts to download a file to a read-only folder, based on information
  // in |download_info|.
  void DownloadFilesToReadonlyFolder(size_t count, DownloadInfo* download_info);

  // This method:
  // * Starts a mock download by navigating to embedded test server URL.
  // * Injects |error| on the first write using |error_injector|.
  // * Waits for the download to be interrupted.
  // * Clears the errors on |error_injector|.
  // * Returns the resulting interrupted download.
  download::DownloadItem* StartMockDownloadAndInjectError(
      content::TestFileErrorInjector* error_injector,
      download::DownloadInterruptReason error);

  // Provide equivalent to embedded_test_server() with a variant that uses HTTPS
  // to avoid insecure download warnings.
  net::EmbeddedTestServer* https_test_server() {
    return https_test_server_.get();
  }

 private:
  web_app::OsIntegrationTestOverrideBlockingRegistration faked_os_integration_;

  // Location of the test data.
  base::FilePath test_dir_;

  content::TestDownloadResponseHandler test_response_handler_;
  std::unique_ptr<DownloadTestFileActivityObserver> file_activity_observer_;
  extensions::ScopedIgnoreContentVerifierForTest ignore_content_verifier_;
  extensions::ScopedInstallVerifierBypassForTest ignore_install_verification_;

  // By default, the embedded test server uses HTTP. Keep an HTTPS server
  // as well so that we can avoid unexpected insecure download warnings.
  std::unique_ptr<net::EmbeddedTestServer> https_test_server_;
};

#endif  // CHROME_BROWSER_DOWNLOAD_DOWNLOAD_BROWSERTEST_UTILS_H_