2013-10-18 18:33:56 +02:00
|
|
|
// Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights
|
|
|
|
// reserved. Use of this source code is governed by a BSD-style license that
|
|
|
|
// can be found in the LICENSE file.
|
|
|
|
|
2021-06-20 18:08:10 +02:00
|
|
|
#include <algorithm>
|
2021-06-19 21:54:45 +02:00
|
|
|
#include <memory>
|
|
|
|
|
|
|
|
#include "include/base/cef_callback.h"
|
|
|
|
#include "include/base/cef_callback_helpers.h"
|
2014-07-15 00:18:51 +02:00
|
|
|
#include "include/cef_scheme.h"
|
2016-02-12 23:31:22 +01:00
|
|
|
#include "include/wrapper/cef_closure_task.h"
|
2016-11-15 18:56:02 +01:00
|
|
|
#include "include/wrapper/cef_scoped_temp_dir.h"
|
2016-11-18 18:31:21 +01:00
|
|
|
#include "tests/ceftests/test_handler.h"
|
2017-12-22 22:05:32 +01:00
|
|
|
#include "tests/ceftests/test_util.h"
|
2016-11-18 00:52:42 +01:00
|
|
|
#include "tests/gtest/include/gtest/gtest.h"
|
2017-08-04 00:55:19 +02:00
|
|
|
#include "tests/shared/browser/file_util.h"
|
2013-10-18 18:33:56 +02:00
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
2016-02-12 23:31:22 +01:00
|
|
|
const char kTestDomain[] = "test-download.com";
|
2023-04-29 00:17:03 +02:00
|
|
|
const char kTestStartUrl[] = "https://test-download.com/test.html";
|
|
|
|
const char kTestDownloadUrl[] = "https://test-download.com/download.txt";
|
|
|
|
const char kTestNavUrl[] = "https://test-download-nav.com/nav.html";
|
2013-10-18 18:33:56 +02:00
|
|
|
const char kTestFileName[] = "download_test.txt";
|
|
|
|
const char kTestContentDisposition[] =
|
|
|
|
"attachment; filename=\"download_test.txt\"";
|
|
|
|
const char kTestMimeType[] = "text/plain";
|
|
|
|
const char kTestContent[] = "Download test text";
|
|
|
|
|
2021-06-19 21:54:45 +02:00
|
|
|
using DelayCallback = base::OnceCallback<void(base::OnceClosure /*callback*/)>;
|
2016-02-12 23:31:22 +01:00
|
|
|
|
2013-10-18 18:33:56 +02:00
|
|
|
class DownloadSchemeHandler : public CefResourceHandler {
|
|
|
|
public:
|
2021-06-19 21:54:45 +02:00
|
|
|
DownloadSchemeHandler(DelayCallback delay_callback,
|
2016-02-12 23:31:22 +01:00
|
|
|
TrackCallback* got_download_request)
|
2021-06-19 21:54:45 +02:00
|
|
|
: delay_callback_(std::move(delay_callback)),
|
2024-01-20 18:00:09 +01:00
|
|
|
got_download_request_(got_download_request) {}
|
2013-10-18 18:33:56 +02:00
|
|
|
|
2019-12-31 13:24:10 +01:00
|
|
|
bool Open(CefRefPtr<CefRequest> request,
|
|
|
|
bool& handle_request,
|
|
|
|
CefRefPtr<CefCallback> callback) override {
|
|
|
|
EXPECT_FALSE(CefCurrentlyOn(TID_UI) || CefCurrentlyOn(TID_IO));
|
|
|
|
|
2013-10-18 18:33:56 +02:00
|
|
|
std::string url = request->GetURL();
|
2017-12-22 22:05:32 +01:00
|
|
|
if (url == kTestDownloadUrl) {
|
2013-10-18 18:33:56 +02:00
|
|
|
got_download_request_->yes();
|
|
|
|
content_ = kTestContent;
|
|
|
|
mime_type_ = kTestMimeType;
|
|
|
|
content_disposition_ = kTestContentDisposition;
|
2016-02-12 23:31:22 +01:00
|
|
|
should_delay_ = true;
|
2013-10-18 18:33:56 +02:00
|
|
|
} else {
|
2024-04-26 21:21:33 +02:00
|
|
|
EXPECT_TRUE(IgnoreURL(url)) << url;
|
2019-12-31 13:24:10 +01:00
|
|
|
|
|
|
|
// Cancel immediately.
|
|
|
|
handle_request = true;
|
2013-10-18 18:33:56 +02:00
|
|
|
return false;
|
|
|
|
}
|
2017-05-17 11:29:28 +02:00
|
|
|
|
2019-12-31 13:24:10 +01:00
|
|
|
// Continue immediately.
|
|
|
|
handle_request = true;
|
2013-10-18 18:33:56 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-11-12 20:25:15 +01:00
|
|
|
void GetResponseHeaders(CefRefPtr<CefResponse> response,
|
2023-06-01 16:06:15 +02:00
|
|
|
int64_t& response_length,
|
2014-11-12 20:25:15 +01:00
|
|
|
CefString& redirectUrl) override {
|
2013-10-18 18:33:56 +02:00
|
|
|
response_length = content_.size();
|
|
|
|
|
|
|
|
response->SetStatus(200);
|
|
|
|
response->SetMimeType(mime_type_);
|
|
|
|
|
|
|
|
if (!content_disposition_.empty()) {
|
|
|
|
CefResponse::HeaderMap headerMap;
|
|
|
|
response->GetHeaderMap(headerMap);
|
|
|
|
headerMap.insert(
|
|
|
|
std::make_pair("Content-Disposition", content_disposition_));
|
|
|
|
response->SetHeaderMap(headerMap);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-31 13:24:10 +01:00
|
|
|
bool Read(void* data_out,
|
|
|
|
int bytes_to_read,
|
|
|
|
int& bytes_read,
|
|
|
|
CefRefPtr<CefResourceReadCallback> callback) override {
|
|
|
|
EXPECT_FALSE(CefCurrentlyOn(TID_UI) || CefCurrentlyOn(TID_IO));
|
|
|
|
|
2013-10-18 18:33:56 +02:00
|
|
|
bytes_read = 0;
|
|
|
|
|
2016-02-12 23:31:22 +01:00
|
|
|
if (should_delay_ && !delay_callback_.is_null()) {
|
|
|
|
// Delay the download response a single time.
|
2021-06-19 21:54:45 +02:00
|
|
|
std::move(delay_callback_)
|
|
|
|
.Run(base::BindOnce(&DownloadSchemeHandler::ContinueRead, this,
|
|
|
|
data_out, bytes_to_read, callback));
|
2016-02-12 23:31:22 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-12-31 13:24:10 +01:00
|
|
|
return DoRead(data_out, bytes_to_read, bytes_read);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Cancel() override {}
|
|
|
|
|
|
|
|
private:
|
|
|
|
void ContinueRead(void* data_out,
|
|
|
|
int bytes_to_read,
|
|
|
|
CefRefPtr<CefResourceReadCallback> callback) {
|
|
|
|
int bytes_read = 0;
|
|
|
|
DoRead(data_out, bytes_to_read, bytes_read);
|
|
|
|
callback->Continue(bytes_read);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DoRead(void* data_out, int bytes_to_read, int& bytes_read) {
|
2016-02-12 23:31:22 +01:00
|
|
|
bool has_data = false;
|
2013-10-18 18:33:56 +02:00
|
|
|
size_t size = content_.size();
|
|
|
|
if (offset_ < size) {
|
|
|
|
int transfer_size =
|
|
|
|
std::min(bytes_to_read, static_cast<int>(size - offset_));
|
|
|
|
memcpy(data_out, content_.c_str() + offset_, transfer_size);
|
|
|
|
offset_ += transfer_size;
|
|
|
|
|
|
|
|
bytes_read = transfer_size;
|
|
|
|
has_data = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return has_data;
|
|
|
|
}
|
|
|
|
|
2016-02-12 23:31:22 +01:00
|
|
|
DelayCallback delay_callback_;
|
2013-10-18 18:33:56 +02:00
|
|
|
TrackCallback* got_download_request_;
|
2024-01-20 18:00:09 +01:00
|
|
|
bool should_delay_ = false;
|
2013-10-18 18:33:56 +02:00
|
|
|
std::string content_;
|
|
|
|
std::string mime_type_;
|
|
|
|
std::string content_disposition_;
|
2024-01-20 18:00:09 +01:00
|
|
|
size_t offset_ = 0;
|
2019-12-31 13:24:10 +01:00
|
|
|
CefRefPtr<CefResourceReadCallback> read_callback_;
|
2013-10-18 18:33:56 +02:00
|
|
|
|
2014-07-15 00:18:51 +02:00
|
|
|
IMPLEMENT_REFCOUNTING(DownloadSchemeHandler);
|
2019-12-31 13:24:10 +01:00
|
|
|
DISALLOW_COPY_AND_ASSIGN(DownloadSchemeHandler);
|
2013-10-18 18:33:56 +02:00
|
|
|
};
|
|
|
|
|
2021-06-19 21:54:45 +02:00
|
|
|
using DelayCallbackVendor = base::RepeatingCallback<DelayCallback(void)>;
|
|
|
|
|
2013-10-18 18:33:56 +02:00
|
|
|
class DownloadSchemeHandlerFactory : public CefSchemeHandlerFactory {
|
|
|
|
public:
|
2021-06-19 21:54:45 +02:00
|
|
|
DownloadSchemeHandlerFactory(const DelayCallbackVendor& delay_callback_vendor,
|
2016-02-12 23:31:22 +01:00
|
|
|
TrackCallback* got_download_request)
|
2021-06-19 21:54:45 +02:00
|
|
|
: delay_callback_vendor_(delay_callback_vendor),
|
2017-05-17 11:29:28 +02:00
|
|
|
got_download_request_(got_download_request) {}
|
2013-10-18 18:33:56 +02:00
|
|
|
|
2017-05-17 11:29:28 +02:00
|
|
|
CefRefPtr<CefResourceHandler> Create(CefRefPtr<CefBrowser> browser,
|
|
|
|
CefRefPtr<CefFrame> frame,
|
|
|
|
const CefString& scheme_name,
|
|
|
|
CefRefPtr<CefRequest> request) override {
|
2021-06-19 21:54:45 +02:00
|
|
|
return new DownloadSchemeHandler(delay_callback_vendor_.is_null()
|
|
|
|
? base::NullCallback()
|
|
|
|
: delay_callback_vendor_.Run(),
|
|
|
|
got_download_request_);
|
2013-10-18 18:33:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2021-06-19 21:54:45 +02:00
|
|
|
DelayCallbackVendor delay_callback_vendor_;
|
2013-10-18 18:33:56 +02:00
|
|
|
TrackCallback* got_download_request_;
|
|
|
|
|
2014-07-15 00:18:51 +02:00
|
|
|
IMPLEMENT_REFCOUNTING(DownloadSchemeHandlerFactory);
|
2019-12-31 13:24:10 +01:00
|
|
|
DISALLOW_COPY_AND_ASSIGN(DownloadSchemeHandlerFactory);
|
2013-10-18 18:33:56 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
class DownloadTestHandler : public TestHandler {
|
|
|
|
public:
|
2016-02-12 23:31:22 +01:00
|
|
|
enum TestMode {
|
2022-03-22 22:40:28 +01:00
|
|
|
PROGRAMMATIC,
|
2016-02-12 23:31:22 +01:00
|
|
|
NAVIGATED,
|
|
|
|
PENDING,
|
2017-12-22 22:05:32 +01:00
|
|
|
CLICKED,
|
2022-03-22 22:40:28 +01:00
|
|
|
CLICKED_INVALID,
|
|
|
|
CLICKED_BLOCKED,
|
2016-02-12 23:31:22 +01:00
|
|
|
};
|
|
|
|
|
2017-12-22 22:05:32 +01:00
|
|
|
DownloadTestHandler(TestMode test_mode,
|
|
|
|
TestRequestContextMode rc_mode,
|
|
|
|
const std::string& rc_cache_path)
|
|
|
|
: test_mode_(test_mode),
|
|
|
|
rc_mode_(rc_mode),
|
2024-01-20 18:00:09 +01:00
|
|
|
rc_cache_path_(rc_cache_path) {}
|
2017-12-22 22:05:32 +01:00
|
|
|
|
|
|
|
bool is_clicked() const {
|
2022-03-22 22:40:28 +01:00
|
|
|
return test_mode_ == CLICKED || test_mode_ == CLICKED_INVALID ||
|
|
|
|
test_mode_ == CLICKED_BLOCKED;
|
|
|
|
}
|
|
|
|
|
2024-04-26 21:21:33 +02:00
|
|
|
bool is_clicked_invalid() const { return test_mode_ == CLICKED_INVALID; }
|
|
|
|
|
2022-03-22 22:40:28 +01:00
|
|
|
bool is_clicked_and_downloaded() const { return test_mode_ == CLICKED; }
|
|
|
|
|
|
|
|
bool is_downloaded() const {
|
|
|
|
return test_mode_ == PROGRAMMATIC || test_mode_ == NAVIGATED ||
|
|
|
|
is_clicked_and_downloaded();
|
2017-12-22 22:05:32 +01:00
|
|
|
}
|
2013-10-18 18:33:56 +02:00
|
|
|
|
2014-11-12 20:25:15 +01:00
|
|
|
void RunTest() override {
|
2023-10-11 21:18:35 +02:00
|
|
|
if (!is_clicked() || is_clicked_and_downloaded()) {
|
|
|
|
// Create a new temporary directory.
|
|
|
|
EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
|
|
|
|
test_path_ =
|
|
|
|
client::file_util::JoinPath(temp_dir_.GetPath(), kTestFileName);
|
|
|
|
}
|
|
|
|
|
|
|
|
CreateTestRequestContext(
|
|
|
|
rc_mode_, rc_cache_path_,
|
|
|
|
base::BindOnce(&DownloadTestHandler::RunTestContinue, this));
|
|
|
|
|
|
|
|
// Time out the test after a reasonable period of time.
|
|
|
|
SetTestTimeout();
|
|
|
|
}
|
|
|
|
|
|
|
|
void RunTestContinue(CefRefPtr<CefRequestContext> request_context) {
|
|
|
|
EXPECT_UI_THREAD();
|
|
|
|
|
2021-06-19 21:54:45 +02:00
|
|
|
DelayCallbackVendor delay_callback_vendor;
|
|
|
|
if (test_mode_ == NAVIGATED || test_mode_ == PENDING) {
|
|
|
|
delay_callback_vendor = base::BindRepeating(
|
|
|
|
[](CefRefPtr<DownloadTestHandler> self) {
|
|
|
|
return base::BindOnce(&DownloadTestHandler::OnDelayCallback, self);
|
|
|
|
},
|
|
|
|
CefRefPtr<DownloadTestHandler>(this));
|
|
|
|
}
|
2016-02-12 23:31:22 +01:00
|
|
|
|
2017-12-22 22:05:32 +01:00
|
|
|
CefRefPtr<CefSchemeHandlerFactory> scheme_factory =
|
2021-06-19 21:54:45 +02:00
|
|
|
new DownloadSchemeHandlerFactory(delay_callback_vendor,
|
2017-12-22 22:05:32 +01:00
|
|
|
&got_download_request_);
|
2013-10-18 18:33:56 +02:00
|
|
|
|
2017-12-22 22:05:32 +01:00
|
|
|
if (request_context) {
|
2023-04-29 00:17:03 +02:00
|
|
|
request_context->RegisterSchemeHandlerFactory("https", kTestDomain,
|
2017-12-22 22:05:32 +01:00
|
|
|
scheme_factory);
|
|
|
|
} else {
|
2023-04-29 00:17:03 +02:00
|
|
|
CefRegisterSchemeHandlerFactory("https", kTestDomain, scheme_factory);
|
2017-12-22 22:05:32 +01:00
|
|
|
}
|
|
|
|
|
2016-02-12 23:31:22 +01:00
|
|
|
if (test_mode_ == NAVIGATED) {
|
|
|
|
// Add the resource that we'll navigate to.
|
|
|
|
AddResource(kTestNavUrl, "<html><body>Navigated</body></html>",
|
|
|
|
"text/html");
|
|
|
|
}
|
|
|
|
|
2017-12-22 22:05:32 +01:00
|
|
|
if (is_clicked()) {
|
2022-03-22 22:40:28 +01:00
|
|
|
if (test_mode_ == CLICKED || test_mode_ == CLICKED_BLOCKED) {
|
|
|
|
download_url_ = kTestDownloadUrl;
|
|
|
|
} else if (test_mode_ == CLICKED_INVALID) {
|
|
|
|
download_url_ = "invalid:foo@example.com";
|
2017-12-22 22:05:32 +01:00
|
|
|
} else {
|
|
|
|
EXPECT_TRUE(false); // Not reached.
|
|
|
|
}
|
2022-03-22 22:40:28 +01:00
|
|
|
AddResource(kTestStartUrl,
|
|
|
|
"<html><body><a href=\"" + download_url_ +
|
|
|
|
"\">CLICK ME</a></body></html>",
|
|
|
|
"text/html");
|
2017-12-22 22:05:32 +01:00
|
|
|
} else {
|
2022-03-22 22:40:28 +01:00
|
|
|
download_url_ = kTestStartUrl;
|
2017-12-22 22:05:32 +01:00
|
|
|
AddResource(kTestStartUrl, "<html><body>Download Test</body></html>",
|
|
|
|
"text/html");
|
|
|
|
}
|
|
|
|
|
2013-10-18 18:33:56 +02:00
|
|
|
// Create the browser
|
2017-12-22 22:05:32 +01:00
|
|
|
CreateBrowser(kTestStartUrl, request_context);
|
2013-10-18 18:33:56 +02:00
|
|
|
}
|
|
|
|
|
2014-11-12 20:25:15 +01:00
|
|
|
void OnLoadEnd(CefRefPtr<CefBrowser> browser,
|
|
|
|
CefRefPtr<CefFrame> frame,
|
|
|
|
int httpStatusCode) override {
|
2016-02-12 23:31:22 +01:00
|
|
|
const std::string& url = frame->GetURL().ToString();
|
2017-12-22 22:05:32 +01:00
|
|
|
if (url == kTestNavUrl) {
|
2016-02-12 23:31:22 +01:00
|
|
|
got_nav_load_.yes();
|
|
|
|
ContinueNavigatedIfReady();
|
2017-12-22 22:05:32 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (is_clicked()) {
|
|
|
|
// Begin the download by clicking a link.
|
|
|
|
// ALT key will trigger download of custom protocol links.
|
|
|
|
SendClick(browser,
|
2022-03-22 22:40:28 +01:00
|
|
|
test_mode_ == CLICKED_INVALID ? EVENTFLAG_ALT_DOWN : 0);
|
2024-04-26 21:21:33 +02:00
|
|
|
|
2024-06-26 02:12:37 +02:00
|
|
|
if (is_clicked_invalid()) {
|
2024-04-26 21:21:33 +02:00
|
|
|
// Destroy the test after a bit because there will be no further
|
|
|
|
// callbacks.
|
|
|
|
CefPostDelayedTask(
|
|
|
|
TID_UI, base::BindOnce(&DownloadTestHandler::DestroyTest, this),
|
|
|
|
200);
|
|
|
|
}
|
2017-12-22 22:05:32 +01:00
|
|
|
} else {
|
|
|
|
// Begin the download progammatically.
|
|
|
|
browser->GetHost()->StartDownload(kTestDownloadUrl);
|
2016-02-12 23:31:22 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Callback from the scheme handler when the download request is delayed.
|
2021-06-19 21:54:45 +02:00
|
|
|
void OnDelayCallback(base::OnceClosure callback) {
|
2016-02-12 23:31:22 +01:00
|
|
|
if (!CefCurrentlyOn(TID_UI)) {
|
2021-06-19 21:54:45 +02:00
|
|
|
CefPostTask(TID_UI, base::BindOnce(&DownloadTestHandler::OnDelayCallback,
|
|
|
|
this, std::move(callback)));
|
2016-02-12 23:31:22 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
got_delay_callback_.yes();
|
|
|
|
|
|
|
|
if (test_mode_ == NAVIGATED) {
|
2021-06-19 21:54:45 +02:00
|
|
|
delay_callback_ = std::move(callback);
|
2016-02-12 23:31:22 +01:00
|
|
|
ContinueNavigatedIfReady();
|
|
|
|
} else if (test_mode_ == PENDING) {
|
|
|
|
ContinuePendingIfReady();
|
|
|
|
} else {
|
|
|
|
EXPECT_TRUE(false); // Not reached.
|
|
|
|
}
|
|
|
|
}
|
2013-10-18 18:33:56 +02:00
|
|
|
|
2016-02-12 23:31:22 +01:00
|
|
|
void ContinueNavigatedIfReady() {
|
2017-12-22 22:05:32 +01:00
|
|
|
EXPECT_EQ(test_mode_, NAVIGATED);
|
2016-02-12 23:31:22 +01:00
|
|
|
if (got_delay_callback_ && got_nav_load_) {
|
2019-12-31 13:24:10 +01:00
|
|
|
EXPECT_FALSE(delay_callback_.is_null());
|
2021-06-19 21:54:45 +02:00
|
|
|
std::move(delay_callback_).Run();
|
2016-02-12 23:31:22 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ContinuePendingIfReady() {
|
2017-12-22 22:05:32 +01:00
|
|
|
EXPECT_EQ(test_mode_, PENDING);
|
2016-02-12 23:31:22 +01:00
|
|
|
if (got_delay_callback_ && got_on_before_download_ &&
|
|
|
|
got_on_download_updated_) {
|
|
|
|
// Destroy the test without waiting for the download to complete.
|
|
|
|
DestroyTest();
|
|
|
|
}
|
2013-10-18 18:33:56 +02:00
|
|
|
}
|
|
|
|
|
2022-03-22 22:40:28 +01:00
|
|
|
bool CanDownload(CefRefPtr<CefBrowser> browser,
|
|
|
|
const CefString& url,
|
|
|
|
const CefString& request_method) override {
|
|
|
|
EXPECT_TRUE(CefCurrentlyOn(TID_UI));
|
|
|
|
EXPECT_FALSE(got_can_download_);
|
|
|
|
EXPECT_FALSE(got_on_before_download_);
|
|
|
|
EXPECT_TRUE(is_clicked());
|
|
|
|
|
|
|
|
got_can_download_.yes();
|
|
|
|
|
|
|
|
EXPECT_TRUE(browser->IsSame(GetBrowser()));
|
|
|
|
EXPECT_STREQ(download_url_.c_str(), url.ToString().c_str());
|
|
|
|
EXPECT_STREQ("GET", request_method.ToString().c_str());
|
|
|
|
|
2023-06-26 12:48:34 +02:00
|
|
|
if (is_clicked() && !is_clicked_and_downloaded()) {
|
|
|
|
// Destroy the test after a bit because there will be no further
|
|
|
|
// callbacks.
|
|
|
|
CefPostDelayedTask(
|
|
|
|
TID_UI, base::BindOnce(&DownloadTestHandler::DestroyTest, this), 200);
|
|
|
|
}
|
|
|
|
|
2022-03-22 22:40:28 +01:00
|
|
|
return test_mode_ != CLICKED_BLOCKED;
|
|
|
|
}
|
|
|
|
|
2024-04-26 21:21:33 +02:00
|
|
|
bool OnBeforeDownload(
|
2013-10-18 18:33:56 +02:00
|
|
|
CefRefPtr<CefBrowser> browser,
|
|
|
|
CefRefPtr<CefDownloadItem> download_item,
|
|
|
|
const CefString& suggested_name,
|
2014-11-12 20:25:15 +01:00
|
|
|
CefRefPtr<CefBeforeDownloadCallback> callback) override {
|
2013-10-18 18:33:56 +02:00
|
|
|
EXPECT_TRUE(CefCurrentlyOn(TID_UI));
|
|
|
|
EXPECT_FALSE(got_on_before_download_);
|
|
|
|
|
2022-03-22 22:40:28 +01:00
|
|
|
if (is_clicked()) {
|
|
|
|
EXPECT_TRUE(got_can_download_);
|
|
|
|
} else {
|
|
|
|
EXPECT_FALSE(got_can_download_);
|
|
|
|
}
|
|
|
|
|
2013-10-18 18:33:56 +02:00
|
|
|
got_on_before_download_.yes();
|
|
|
|
|
|
|
|
EXPECT_TRUE(browser->IsSame(GetBrowser()));
|
|
|
|
EXPECT_STREQ(kTestFileName, suggested_name.ToString().c_str());
|
|
|
|
EXPECT_TRUE(download_item.get());
|
|
|
|
EXPECT_TRUE(callback.get());
|
|
|
|
|
|
|
|
download_id_ = download_item->GetId();
|
|
|
|
EXPECT_LT(0U, download_id_);
|
2017-05-17 11:29:28 +02:00
|
|
|
|
2013-10-18 18:33:56 +02:00
|
|
|
EXPECT_TRUE(download_item->IsValid());
|
|
|
|
EXPECT_TRUE(download_item->IsInProgress());
|
|
|
|
EXPECT_FALSE(download_item->IsComplete());
|
|
|
|
EXPECT_FALSE(download_item->IsCanceled());
|
2023-04-21 06:15:08 +02:00
|
|
|
EXPECT_FALSE(download_item->IsInterrupted());
|
|
|
|
EXPECT_EQ(CEF_DOWNLOAD_INTERRUPT_REASON_NONE,
|
|
|
|
download_item->GetInterruptReason());
|
2023-06-01 16:06:15 +02:00
|
|
|
EXPECT_EQ(static_cast<int64_t>(sizeof(kTestContent) - 1),
|
2017-05-17 11:29:28 +02:00
|
|
|
download_item->GetTotalBytes());
|
2013-10-18 18:33:56 +02:00
|
|
|
EXPECT_EQ(0UL, download_item->GetFullPath().length());
|
|
|
|
EXPECT_STREQ(kTestDownloadUrl, download_item->GetURL().ToString().c_str());
|
|
|
|
EXPECT_EQ(0UL, download_item->GetSuggestedFileName().length());
|
|
|
|
EXPECT_STREQ(kTestContentDisposition,
|
2017-05-17 11:29:28 +02:00
|
|
|
download_item->GetContentDisposition().ToString().c_str());
|
|
|
|
EXPECT_STREQ(kTestMimeType,
|
|
|
|
download_item->GetMimeType().ToString().c_str());
|
2013-10-18 18:33:56 +02:00
|
|
|
|
2016-11-15 18:56:02 +01:00
|
|
|
callback->Continue(test_path_, false);
|
2016-02-12 23:31:22 +01:00
|
|
|
|
2018-02-15 01:12:09 +01:00
|
|
|
if (test_mode_ == NAVIGATED) {
|
|
|
|
CefRefPtr<CefFrame> main_frame = browser->GetMainFrame();
|
|
|
|
EXPECT_TRUE(main_frame->IsMain());
|
|
|
|
main_frame->LoadURL(kTestNavUrl);
|
|
|
|
} else if (test_mode_ == PENDING) {
|
2016-02-12 23:31:22 +01:00
|
|
|
ContinuePendingIfReady();
|
2018-02-15 01:12:09 +01:00
|
|
|
}
|
2024-04-26 21:21:33 +02:00
|
|
|
|
|
|
|
return true;
|
2013-10-18 18:33:56 +02:00
|
|
|
}
|
|
|
|
|
2017-05-17 11:29:28 +02:00
|
|
|
void OnDownloadUpdated(CefRefPtr<CefBrowser> browser,
|
|
|
|
CefRefPtr<CefDownloadItem> download_item,
|
|
|
|
CefRefPtr<CefDownloadItemCallback> callback) override {
|
2013-10-18 18:33:56 +02:00
|
|
|
EXPECT_TRUE(CefCurrentlyOn(TID_UI));
|
|
|
|
|
2023-01-02 23:59:03 +01:00
|
|
|
if (destroyed_) {
|
2019-01-23 14:47:52 +01:00
|
|
|
return;
|
2023-01-02 23:59:03 +01:00
|
|
|
}
|
2019-01-23 14:47:52 +01:00
|
|
|
|
2013-10-18 18:33:56 +02:00
|
|
|
got_on_download_updated_.yes();
|
|
|
|
|
|
|
|
EXPECT_TRUE(browser->IsSame(GetBrowser()));
|
|
|
|
EXPECT_TRUE(download_item.get());
|
|
|
|
EXPECT_TRUE(callback.get());
|
|
|
|
|
2017-08-11 18:56:52 +02:00
|
|
|
if (got_on_before_download_) {
|
2013-10-18 18:33:56 +02:00
|
|
|
EXPECT_EQ(download_id_, download_item->GetId());
|
2017-08-11 18:56:52 +02:00
|
|
|
}
|
2013-10-18 18:33:56 +02:00
|
|
|
|
|
|
|
EXPECT_LE(0LL, download_item->GetCurrentSpeed());
|
|
|
|
EXPECT_LE(0, download_item->GetPercentComplete());
|
|
|
|
|
|
|
|
EXPECT_TRUE(download_item->IsValid());
|
|
|
|
EXPECT_FALSE(download_item->IsCanceled());
|
2023-04-21 06:15:08 +02:00
|
|
|
EXPECT_FALSE(download_item->IsInterrupted());
|
|
|
|
EXPECT_EQ(CEF_DOWNLOAD_INTERRUPT_REASON_NONE,
|
|
|
|
download_item->GetInterruptReason());
|
2013-10-18 18:33:56 +02:00
|
|
|
EXPECT_STREQ(kTestDownloadUrl, download_item->GetURL().ToString().c_str());
|
|
|
|
EXPECT_STREQ(kTestContentDisposition,
|
2017-05-17 11:29:28 +02:00
|
|
|
download_item->GetContentDisposition().ToString().c_str());
|
2013-10-18 18:33:56 +02:00
|
|
|
EXPECT_STREQ(kTestMimeType,
|
2017-05-17 11:29:28 +02:00
|
|
|
download_item->GetMimeType().ToString().c_str());
|
2013-10-18 18:33:56 +02:00
|
|
|
|
|
|
|
std::string full_path = download_item->GetFullPath();
|
|
|
|
if (!full_path.empty()) {
|
|
|
|
got_full_path_.yes();
|
2016-11-15 18:56:02 +01:00
|
|
|
EXPECT_STREQ(test_path_.c_str(), full_path.c_str());
|
2013-10-18 18:33:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (download_item->IsComplete()) {
|
2016-02-12 23:31:22 +01:00
|
|
|
got_download_complete_.yes();
|
|
|
|
|
2013-10-18 18:33:56 +02:00
|
|
|
EXPECT_FALSE(download_item->IsInProgress());
|
|
|
|
EXPECT_EQ(100, download_item->GetPercentComplete());
|
2023-06-01 16:06:15 +02:00
|
|
|
EXPECT_EQ(static_cast<int64_t>(sizeof(kTestContent) - 1),
|
2017-05-17 11:29:28 +02:00
|
|
|
download_item->GetReceivedBytes());
|
2023-06-01 16:06:15 +02:00
|
|
|
EXPECT_EQ(static_cast<int64_t>(sizeof(kTestContent) - 1),
|
2017-05-17 11:29:28 +02:00
|
|
|
download_item->GetTotalBytes());
|
2013-10-18 18:33:56 +02:00
|
|
|
|
|
|
|
DestroyTest();
|
|
|
|
} else {
|
|
|
|
EXPECT_TRUE(download_item->IsInProgress());
|
|
|
|
EXPECT_LE(0LL, download_item->GetReceivedBytes());
|
|
|
|
}
|
2016-02-12 23:31:22 +01:00
|
|
|
|
2019-01-23 14:47:52 +01:00
|
|
|
if (test_mode_ == PENDING) {
|
|
|
|
download_item_callback_ = callback;
|
2016-02-12 23:31:22 +01:00
|
|
|
ContinuePendingIfReady();
|
2019-01-23 14:47:52 +01:00
|
|
|
}
|
2013-10-18 18:33:56 +02:00
|
|
|
}
|
|
|
|
|
2016-11-15 18:56:02 +01:00
|
|
|
void VerifyResultsOnFileThread() {
|
2020-09-25 03:40:47 +02:00
|
|
|
EXPECT_TRUE(CefCurrentlyOn(TID_FILE_USER_VISIBLE));
|
2016-11-15 18:56:02 +01:00
|
|
|
|
|
|
|
if (test_mode_ != PENDING) {
|
|
|
|
// Verify the file contents.
|
|
|
|
std::string contents;
|
2017-08-04 00:55:19 +02:00
|
|
|
EXPECT_TRUE(client::file_util::ReadFileToString(test_path_, &contents));
|
2016-11-15 18:56:02 +01:00
|
|
|
EXPECT_STREQ(kTestContent, contents.c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
EXPECT_TRUE(temp_dir_.Delete());
|
|
|
|
EXPECT_TRUE(temp_dir_.IsEmpty());
|
|
|
|
|
2021-06-19 21:54:45 +02:00
|
|
|
CefPostTask(TID_UI,
|
|
|
|
base::BindOnce(&DownloadTestHandler::DestroyTest, this));
|
2016-11-15 18:56:02 +01:00
|
|
|
}
|
|
|
|
|
2014-11-12 20:25:15 +01:00
|
|
|
void DestroyTest() override {
|
2018-02-15 01:12:09 +01:00
|
|
|
if (!verified_results_ && !temp_dir_.IsEmpty()) {
|
|
|
|
// Avoid an endless failure loop.
|
|
|
|
verified_results_ = true;
|
2016-11-15 18:56:02 +01:00
|
|
|
// Clean up temp_dir_ on the FILE thread before destroying the test.
|
2021-06-19 21:54:45 +02:00
|
|
|
CefPostTask(TID_FILE_USER_VISIBLE,
|
|
|
|
base::BindOnce(
|
|
|
|
&DownloadTestHandler::VerifyResultsOnFileThread, this));
|
2016-11-15 18:56:02 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-01-23 14:47:52 +01:00
|
|
|
destroyed_ = true;
|
|
|
|
|
|
|
|
if (download_item_callback_) {
|
|
|
|
// Cancel the pending download to avoid leaking request objects.
|
|
|
|
download_item_callback_->Cancel();
|
|
|
|
download_item_callback_ = nullptr;
|
|
|
|
}
|
|
|
|
|
2017-12-22 22:05:32 +01:00
|
|
|
if (request_context_) {
|
2023-04-29 00:17:03 +02:00
|
|
|
request_context_->RegisterSchemeHandlerFactory("https", kTestDomain,
|
2017-12-22 22:05:32 +01:00
|
|
|
nullptr);
|
|
|
|
request_context_ = nullptr;
|
|
|
|
} else {
|
2023-04-29 00:17:03 +02:00
|
|
|
CefRegisterSchemeHandlerFactory("https", kTestDomain, nullptr);
|
2017-12-22 22:05:32 +01:00
|
|
|
}
|
2013-10-18 18:33:56 +02:00
|
|
|
|
2024-04-26 21:21:33 +02:00
|
|
|
if (is_clicked_invalid()) {
|
2024-06-26 02:12:37 +02:00
|
|
|
// No CanDownload for invalid protocol links.
|
|
|
|
EXPECT_FALSE(got_can_download_);
|
2024-04-26 21:21:33 +02:00
|
|
|
} else if (is_clicked()) {
|
2022-03-22 22:40:28 +01:00
|
|
|
EXPECT_TRUE(got_can_download_);
|
|
|
|
} else {
|
|
|
|
EXPECT_FALSE(got_can_download_);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (test_mode_ == CLICKED_INVALID) {
|
|
|
|
// The invalid protocol request is not handled.
|
2017-12-22 22:05:32 +01:00
|
|
|
EXPECT_FALSE(got_download_request_);
|
2022-03-22 22:40:28 +01:00
|
|
|
} else {
|
|
|
|
EXPECT_TRUE(got_download_request_);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (is_clicked() && !is_clicked_and_downloaded()) {
|
|
|
|
// The download never proceeds.
|
2017-12-22 22:05:32 +01:00
|
|
|
EXPECT_FALSE(got_on_before_download_);
|
|
|
|
EXPECT_FALSE(got_on_download_updated_);
|
|
|
|
} else {
|
|
|
|
EXPECT_TRUE(got_on_before_download_);
|
|
|
|
EXPECT_TRUE(got_on_download_updated_);
|
|
|
|
}
|
2013-10-18 18:33:56 +02:00
|
|
|
|
2023-01-02 23:59:03 +01:00
|
|
|
if (test_mode_ == NAVIGATED) {
|
2016-02-12 23:31:22 +01:00
|
|
|
EXPECT_TRUE(got_nav_load_);
|
2023-01-02 23:59:03 +01:00
|
|
|
} else {
|
2016-02-12 23:31:22 +01:00
|
|
|
EXPECT_FALSE(got_nav_load_);
|
2023-01-02 23:59:03 +01:00
|
|
|
}
|
2016-02-12 23:31:22 +01:00
|
|
|
|
2022-03-22 22:40:28 +01:00
|
|
|
if (!is_downloaded()) {
|
|
|
|
// The download never completes.
|
2016-02-12 23:31:22 +01:00
|
|
|
EXPECT_FALSE(got_download_complete_);
|
|
|
|
EXPECT_FALSE(got_full_path_);
|
|
|
|
} else {
|
|
|
|
EXPECT_TRUE(got_download_complete_);
|
|
|
|
EXPECT_TRUE(got_full_path_);
|
|
|
|
}
|
2013-10-18 18:33:56 +02:00
|
|
|
|
|
|
|
TestHandler::DestroyTest();
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2017-12-22 22:05:32 +01:00
|
|
|
void SendClick(CefRefPtr<CefBrowser> browser, uint32_t modifiers) {
|
|
|
|
EXPECT_TRUE(is_clicked());
|
|
|
|
CefMouseEvent mouse_event;
|
|
|
|
mouse_event.x = 20;
|
|
|
|
mouse_event.y = 20;
|
|
|
|
mouse_event.modifiers = modifiers;
|
2023-02-06 22:26:20 +01:00
|
|
|
SendMouseClickEvent(browser, mouse_event);
|
2017-12-22 22:05:32 +01:00
|
|
|
}
|
|
|
|
|
2016-02-12 23:31:22 +01:00
|
|
|
const TestMode test_mode_;
|
2017-12-22 22:05:32 +01:00
|
|
|
const TestRequestContextMode rc_mode_;
|
|
|
|
const std::string rc_cache_path_;
|
|
|
|
|
|
|
|
CefRefPtr<CefRequestContext> request_context_;
|
2016-02-12 23:31:22 +01:00
|
|
|
|
2019-01-23 14:47:52 +01:00
|
|
|
// Used with NAVIGATED and PENDING test modes.
|
2021-06-19 21:54:45 +02:00
|
|
|
base::OnceClosure delay_callback_;
|
2016-02-12 23:31:22 +01:00
|
|
|
|
2019-01-23 14:47:52 +01:00
|
|
|
// Used with PENDING test mode.
|
|
|
|
CefRefPtr<CefDownloadItemCallback> download_item_callback_;
|
|
|
|
|
2022-03-22 22:40:28 +01:00
|
|
|
std::string download_url_;
|
2016-11-15 18:56:02 +01:00
|
|
|
CefScopedTempDir temp_dir_;
|
|
|
|
std::string test_path_;
|
2024-01-20 18:00:09 +01:00
|
|
|
uint32_t download_id_ = 0;
|
|
|
|
bool verified_results_ = false;
|
2019-01-23 14:47:52 +01:00
|
|
|
bool destroyed_ = false;
|
2013-10-18 18:33:56 +02:00
|
|
|
|
|
|
|
TrackCallback got_download_request_;
|
2022-03-22 22:40:28 +01:00
|
|
|
TrackCallback got_can_download_;
|
2013-10-18 18:33:56 +02:00
|
|
|
TrackCallback got_on_before_download_;
|
|
|
|
TrackCallback got_on_download_updated_;
|
|
|
|
TrackCallback got_full_path_;
|
2016-02-12 23:31:22 +01:00
|
|
|
TrackCallback got_download_complete_;
|
|
|
|
TrackCallback got_delay_callback_;
|
|
|
|
TrackCallback got_nav_load_;
|
2015-09-09 16:05:39 +02:00
|
|
|
|
|
|
|
IMPLEMENT_REFCOUNTING(DownloadTestHandler);
|
2013-10-18 18:33:56 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
2017-12-22 22:05:32 +01:00
|
|
|
#define DOWNLOAD_TEST_GROUP(test_name, test_mode) \
|
|
|
|
RC_TEST_GROUP_ALL(DownloadTest, test_name, DownloadTestHandler, test_mode)
|
|
|
|
|
|
|
|
// Test a programmatic download.
|
2022-03-22 22:40:28 +01:00
|
|
|
DOWNLOAD_TEST_GROUP(Programmatic, PROGRAMMATIC)
|
2017-12-22 22:05:32 +01:00
|
|
|
|
|
|
|
// Test a clicked download.
|
2019-03-13 22:27:37 +01:00
|
|
|
DOWNLOAD_TEST_GROUP(Clicked, CLICKED)
|
2017-12-22 22:05:32 +01:00
|
|
|
|
|
|
|
// Test a clicked download where the protocol is invalid and therefore rejected.
|
|
|
|
// There will be no resulting CefDownloadHandler callbacks.
|
2022-03-22 22:40:28 +01:00
|
|
|
DOWNLOAD_TEST_GROUP(ClickedInvalid, CLICKED_INVALID)
|
|
|
|
|
|
|
|
// Test a clicked download where CanDownload returns false.
|
|
|
|
// There will be no resulting CefDownloadHandler callbacks.
|
|
|
|
DOWNLOAD_TEST_GROUP(ClickedBlocked, CLICKED_BLOCKED)
|
2016-02-12 23:31:22 +01:00
|
|
|
|
|
|
|
// Test where the download completes after cross-origin navigation.
|
2019-03-13 22:27:37 +01:00
|
|
|
DOWNLOAD_TEST_GROUP(Navigated, NAVIGATED)
|
2016-02-12 23:31:22 +01:00
|
|
|
|
|
|
|
// Test where the download is still pending when the browser is destroyed.
|
2019-03-13 22:27:37 +01:00
|
|
|
DOWNLOAD_TEST_GROUP(Pending, PENDING)
|