mirror of
https://github.com/Adamcake/Bolt.git
synced 2026-04-22 09:56:53 -04:00
190 lines
7.0 KiB
C++
190 lines
7.0 KiB
C++
#include "resource_handler.hxx"
|
|
#include "include/cef_urlrequest.h"
|
|
#include "include/internal/cef_types.h"
|
|
|
|
// returns content-length or -1 if it's malformed or nonexistent
|
|
// CEF interprets -1 as "unknown length"
|
|
static int64_t GetContentLength(CefRefPtr<CefResponse> response) {
|
|
std::string content_length = response->GetHeaderByName("Content-Length").ToString();
|
|
if (content_length.size() == 0) {
|
|
return -1;
|
|
}
|
|
int64_t length = 0;
|
|
for (auto it = content_length.begin(); it != content_length.end(); it++) {
|
|
if (*it < '0' || *it > '9') return -1;
|
|
length = (length * 10) + ((int64_t)(*it) - '0');
|
|
}
|
|
return length;
|
|
}
|
|
|
|
bool Browser::ResourceHandler::Open(CefRefPtr<CefRequest>, bool& handle_request, CefRefPtr<CefCallback>) {
|
|
handle_request = true;
|
|
return true;
|
|
}
|
|
|
|
void Browser::ResourceHandler::GetResponseHeaders(CefRefPtr<CefResponse> response, int64_t& response_length, CefString& redirectUrl) {
|
|
response->SetStatus(this->status);
|
|
response->SetMimeType(this->mime);
|
|
#if defined(BOLT_PLUGINS)
|
|
// note: this response header is set for internally-handled requests only,
|
|
// normal web requests aren't affected.
|
|
response->SetHeaderByName("Access-Control-Allow-Origin", "*", true);
|
|
#endif
|
|
if (this->has_location) {
|
|
response->SetHeaderByName("Location", this->location, false);
|
|
}
|
|
response_length = this->data_len;
|
|
}
|
|
|
|
bool Browser::ResourceHandler::Read(void* data_out, int bytes_to_read, int& bytes_read, CefRefPtr<CefResourceReadCallback>) {
|
|
if (this->cursor == this->data_len) {
|
|
// "To indicate response completion set |bytes_read| to 0 and return false."
|
|
bytes_read = 0;
|
|
return false;
|
|
}
|
|
if (this->cursor + bytes_to_read <= this->data_len) {
|
|
// requested read is entirely in bounds
|
|
bytes_read = bytes_to_read;
|
|
memcpy(data_out, this->data + this->cursor, bytes_read);
|
|
this->cursor += bytes_to_read;
|
|
} else {
|
|
// read only to end of string
|
|
bytes_read = this->data_len - this->cursor;
|
|
memcpy(data_out, this->data + this->cursor, bytes_read);
|
|
this->cursor = this->data_len;
|
|
}
|
|
if (this->cursor == this->data_len) this->finish();
|
|
return true;
|
|
}
|
|
|
|
bool Browser::ResourceHandler::Skip(int64_t bytes_to_skip, int64_t& bytes_skipped, CefRefPtr<CefResourceSkipCallback>) {
|
|
if (this->cursor + bytes_to_skip <= this->data_len) {
|
|
// skip in bounds
|
|
bytes_skipped = bytes_to_skip;
|
|
this->cursor += bytes_to_skip;
|
|
} else {
|
|
// skip to end of string
|
|
bytes_skipped = this->data_len - this->cursor;
|
|
this->cursor = this->data_len;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void Browser::ResourceHandler::Cancel() {
|
|
if (this->cursor != this->data_len) {
|
|
this->cursor = this->data_len;
|
|
this->finish();
|
|
}
|
|
}
|
|
|
|
CefRefPtr<CefResourceHandler> Browser::ResourceHandler::GetResourceHandler(CefRefPtr<CefBrowser>, CefRefPtr<CefFrame>, CefRefPtr<CefRequest>) {
|
|
return this;
|
|
}
|
|
|
|
void Browser::ResourceHandler::finish() {
|
|
if (this->file_manager) {
|
|
this->file_manager->free(FileManager::File { .contents = this->data, .size = this->data_len, .mime_type = this->mime });
|
|
this->file_manager = nullptr;
|
|
}
|
|
}
|
|
|
|
Browser::DefaultURLHandler::DefaultURLHandler(CefRefPtr<CefRequest> request): urlrequest_complete(false), headers_checked(false), urlrequest_callback(nullptr), cursor(0) {
|
|
this->url_request = CefURLRequest::Create(request, this, nullptr);
|
|
}
|
|
|
|
CefResourceRequestHandler::ReturnValue Browser::DefaultURLHandler::OnBeforeResourceLoad(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefRequest> request, CefRefPtr<CefCallback> callback) {
|
|
// use CefResourceRequestHandler::OnBeforeResourceLoad to stall asynchronously on the IO thread
|
|
// until the request completes, if it hasn't already
|
|
if (urlrequest_complete) {
|
|
return RV_CONTINUE;
|
|
} else {
|
|
this->urlrequest_callback = callback;
|
|
return RV_CONTINUE_ASYNC;
|
|
}
|
|
}
|
|
|
|
CefRefPtr<CefResourceHandler> Browser::DefaultURLHandler::GetResourceHandler(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefRequest> request) {
|
|
return this;
|
|
}
|
|
|
|
bool Browser::DefaultURLHandler::Open(CefRefPtr<CefRequest> request, bool& handle_request, CefRefPtr<CefCallback> callback) {
|
|
handle_request = true;
|
|
return true;
|
|
}
|
|
|
|
void Browser::DefaultURLHandler::GetResponseHeaders(CefRefPtr<CefResponse> response, int64_t& response_length, CefString& redirectUrl) {
|
|
CefRefPtr<CefResponse> url_response = this->url_request->GetResponse();
|
|
CefResponse::HeaderMap headers;
|
|
url_response->GetHeaderMap(headers);
|
|
response->SetHeaderMap(headers);
|
|
response->SetStatus(url_response->GetStatus());
|
|
response->SetStatusText(url_response->GetStatusText());
|
|
response->SetMimeType(url_response->GetMimeType());
|
|
response->SetCharset(url_response->GetCharset());
|
|
response->SetHeaderByName("Access-Control-Allow-Origin", "*", true);
|
|
response_length = GetContentLength(url_response);
|
|
}
|
|
|
|
bool Browser::DefaultURLHandler::Read(void* data_out, int bytes_to_read, int& bytes_read, CefRefPtr<CefResourceReadCallback> callback) {
|
|
if (this->cursor == this->data.size()) {
|
|
// "To indicate response completion set |bytes_read| to 0 and return false."
|
|
bytes_read = 0;
|
|
return false;
|
|
}
|
|
if (this->cursor + bytes_to_read <= this->data.size()) {
|
|
// requested read is entirely in bounds
|
|
bytes_read = bytes_to_read;
|
|
memcpy(data_out, &this->data[this->cursor], bytes_read);
|
|
this->cursor += bytes_to_read;
|
|
} else {
|
|
// read only to end of string
|
|
bytes_read = this->data.size() - this->cursor;
|
|
memcpy(data_out, &this->data[this->cursor], bytes_read);
|
|
this->cursor = this->data.size();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool Browser::DefaultURLHandler::Skip(int64_t bytes_to_skip, int64_t& bytes_skipped, CefRefPtr<CefResourceSkipCallback> callback) {
|
|
if (this->cursor + bytes_to_skip <= this->data.size()) {
|
|
// skip in bounds
|
|
bytes_skipped = bytes_to_skip;
|
|
this->cursor += bytes_to_skip;
|
|
} else {
|
|
// skip to end of string
|
|
bytes_skipped = this->data.size() - this->cursor;
|
|
this->cursor = this->data.size();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void Browser::DefaultURLHandler::Cancel() {
|
|
this->cursor = this->data.size();
|
|
}
|
|
|
|
void Browser::DefaultURLHandler::OnRequestComplete(CefRefPtr<CefURLRequest> request) {
|
|
this->urlrequest_complete = true;
|
|
if (this->urlrequest_callback) {
|
|
this->urlrequest_callback->Continue();
|
|
}
|
|
}
|
|
|
|
void Browser::DefaultURLHandler::OnUploadProgress(CefRefPtr<CefURLRequest> request, int64_t current, int64_t total) {}
|
|
void Browser::DefaultURLHandler::OnDownloadProgress(CefRefPtr<CefURLRequest> request, int64_t current, int64_t total) {}
|
|
|
|
void Browser::DefaultURLHandler::OnDownloadData(CefRefPtr<CefURLRequest> request, const void* data, size_t data_length) {
|
|
CefRefPtr<CefResponse> response = request->GetResponse();
|
|
if (!this->headers_checked && response) {
|
|
const int64_t content_length = GetContentLength(response);
|
|
if (content_length != -1) this->data.reserve(content_length);
|
|
this->headers_checked = true;
|
|
}
|
|
size_t write_offset = this->data.size();
|
|
this->data.resize(write_offset + data_length);
|
|
memcpy(this->data.data() + write_offset, data, data_length);
|
|
}
|
|
|
|
bool Browser::DefaultURLHandler::GetAuthCredentials(bool isProxy, const CefString& host, int port, const CefString& realm, const CefString& scheme, CefRefPtr<CefAuthCallback> callback) {
|
|
return false;
|
|
}
|