Add CefResourceManager class for mapping requests to data providers (issue #1640).

This commit is contained in:
Marshall Greenblatt
2015-05-22 21:57:31 -04:00
parent d02f03a71a
commit b6e5310bce
13 changed files with 3037 additions and 78 deletions

View File

@@ -121,6 +121,9 @@ ClientHandler::ClientHandler(Delegate* delegate,
dialog_handler_ = new ClientDialogHandlerGtk();
#endif
resource_manager_ = new CefResourceManager();
test_runner::SetupResourceManager(resource_manager_);
// Read command line settings.
CefRefPtr<CefCommandLine> command_line =
CefCommandLine::GetGlobalCommandLine();
@@ -461,13 +464,24 @@ bool ClientHandler::OnOpenURLFromTab(
return false;
}
cef_return_value_t ClientHandler::OnBeforeResourceLoad(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
CefRefPtr<CefRequestCallback> callback) {
CEF_REQUIRE_IO_THREAD();
return resource_manager_->OnBeforeResourceLoad(browser, frame, request,
callback);
}
CefRefPtr<CefResourceHandler> ClientHandler::GetResourceHandler(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request) {
CEF_REQUIRE_IO_THREAD();
return test_runner::GetResourceHandler(browser, frame, request);
return resource_manager_->GetResourceHandler(browser, frame, request);
}
bool ClientHandler::OnQuotaRequest(CefRefPtr<CefBrowser> browser,

View File

@@ -12,6 +12,7 @@
#include "include/cef_client.h"
#include "include/wrapper/cef_helpers.h"
#include "include/wrapper/cef_message_router.h"
#include "include/wrapper/cef_resource_manager.h"
#include "cefclient/browser/client_types.h"
#if defined(OS_LINUX)
@@ -212,6 +213,11 @@ class ClientHandler : public CefClient,
const CefString& target_url,
CefRequestHandler::WindowOpenDisposition target_disposition,
bool user_gesture) OVERRIDE;
cef_return_value_t OnBeforeResourceLoad(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
CefRefPtr<CefRequestCallback> callback) OVERRIDE;
CefRefPtr<CefResourceHandler> GetResourceHandler(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
@@ -299,6 +305,9 @@ class ClientHandler : public CefClient,
// in client_renderer.cc.
CefRefPtr<CefMessageRouterBrowserSide> message_router_;
// Manages the registration and delivery of resources.
CefRefPtr<CefResourceManager> resource_manager_;
// MAIN THREAD MEMBERS
// The following members will only be accessed on the main thread. This will
// be the same as the CEF UI thread except when using multi-threaded message

View File

@@ -9,6 +9,10 @@
#include <string>
#include "include/cef_stream.h"
#if defined(OS_WIN)
#include "include/wrapper/cef_resource_manager.h"
#endif
namespace client {
#if defined(OS_POSIX)
@@ -22,6 +26,12 @@ bool LoadBinaryResource(const char* resource_name, std::string& resource_data);
// Retrieve a resource as a steam reader.
CefRefPtr<CefStreamReader> GetBinaryResourceReader(const char* resource_name);
#if defined(OS_WIN)
// Create a new provider for loading binary resources.
CefResourceManager::Provider* CreateBinaryResourceProvider(
const std::string& url_path);
#endif
} // namespace client
#endif // CEF_TESTS_CEFCLIENT_BROWSER_RESOURCE_UTIL_H_

View File

@@ -7,6 +7,7 @@
#include "include/base/cef_logging.h"
#include "include/cef_stream.h"
#include "include/wrapper/cef_byte_read_handler.h"
#include "include/wrapper/cef_stream_resource_handler.h"
#include "cefclient/browser/resource.h"
namespace client {
@@ -58,6 +59,46 @@ int GetResourceId(const char* resource_name) {
return 0;
}
// Provider of binary resources.
class BinaryResourceProvider : public CefResourceManager::Provider {
public:
explicit BinaryResourceProvider(const std::string& url_path)
: url_path_(url_path) {
DCHECK(!url_path.empty());
}
bool OnRequest(scoped_refptr<CefResourceManager::Request> request) OVERRIDE {
CEF_REQUIRE_IO_THREAD();
const std::string& url = request->url();
if (url.find(url_path_) != 0L) {
// Not handled by this provider.
return false;
}
CefRefPtr<CefResourceHandler> handler;
const std::string& relative_path = url.substr(url_path_.length());
if (!relative_path.empty()) {
CefRefPtr<CefStreamReader> stream =
GetBinaryResourceReader(relative_path.data());
if (stream.get()) {
handler = new CefStreamResourceHandler(
request->mime_type_resolver().Run(url),
stream);
}
}
request->Continue(handler);
return true;
}
private:
std::string url_path_;
DISALLOW_COPY_AND_ASSIGN(BinaryResourceProvider);
};
} // namespace
bool LoadBinaryResource(const char* resource_name, std::string& resource_data) {
@@ -94,4 +135,9 @@ CefRefPtr<CefStreamReader> GetBinaryResourceReader(const char* resource_name) {
return NULL;
}
CefResourceManager::Provider* CreateBinaryResourceProvider(
const std::string& url_path) {
return new BinaryResourceProvider(url_path);
}
} // namespace client

View File

@@ -266,45 +266,75 @@ void RunOtherTests(CefRefPtr<CefBrowser> browser) {
browser->GetMainFrame()->LoadURL("http://tests/other_tests");
}
// Retrieve the file name and mime type based on the specified url.
bool ParseTestUrl(const std::string& url,
std::string* file_name,
std::string* mime_type) {
// Retrieve the path component.
CefURLParts parts;
CefParseURL(url, parts);
std::string file = CefString(&parts.path);
if (file.size() < 2)
return false;
// Remove the leading slash.
file = file.substr(1);
// Verify that the file name is valid.
for(size_t i = 0; i < file.size(); ++i) {
const char c = file[i];
if (!isalpha(c) && !isdigit(c) && c != '_' && c != '.')
return false;
// Provider that dumps the request contents.
class RequestDumpResourceProvider : public CefResourceManager::Provider {
public:
explicit RequestDumpResourceProvider(const std::string& url)
: url_(url) {
DCHECK(!url.empty());
}
// Determine the mime type based on the file extension, if any.
size_t pos = file.rfind(".");
if (pos != std::string::npos) {
std::string ext = file.substr(pos + 1);
if (ext == "html")
*mime_type = "text/html";
else if (ext == "png")
*mime_type = "image/png";
else
bool OnRequest(scoped_refptr<CefResourceManager::Request> request) OVERRIDE {
CEF_REQUIRE_IO_THREAD();
const std::string& url = request->url();
if (url != url_) {
// Not handled by this provider.
return false;
}
const std::string& dump = DumpRequestContents(request->request());
std::string str = "<html><body bgcolor=\"white\"><pre>" + dump +
"</pre></body></html>";
CefRefPtr<CefStreamReader> stream =
CefStreamReader::CreateForData(
static_cast<void*>(const_cast<char*>(str.c_str())),
str.size());
DCHECK(stream.get());
request->Continue(new CefStreamResourceHandler("text/html", stream));
return true;
}
private:
std::string url_;
DISALLOW_COPY_AND_ASSIGN(RequestDumpResourceProvider);
};
// Add a file extension to |url| if none is currently specified.
std::string RequestUrlFilter(const std::string& url) {
if (url.find(kTestOrigin) != 0U) {
// Don't filter anything outside of the test origin.
return url;
}
// Identify where the query or fragment component, if any, begins.
size_t suffix_pos = url.find('?');
if (suffix_pos == std::string::npos)
suffix_pos = url.find('#');
std::string url_base, url_suffix;
if (suffix_pos == std::string::npos) {
url_base = url;
} else {
// Default to an html extension if none is specified.
*mime_type = "text/html";
file += ".html";
url_base = url.substr(0, suffix_pos);
url_suffix = url.substr(suffix_pos);
}
*file_name = file;
return true;
// Identify the last path component.
size_t path_pos = url_base.rfind('/');
if (path_pos == std::string::npos)
return url;
const std::string& path_component = url_base.substr(path_pos);
// Identify if a file extension is currently specified.
size_t ext_pos = path_component.rfind(".");
if (ext_pos != std::string::npos)
return url;
// Rebuild the URL with a file extension.
return url_base + ".html" + url_suffix;
}
} // namespace
@@ -480,37 +510,30 @@ std::string GetErrorString(cef_errorcode_t code) {
}
}
CefRefPtr<CefResourceHandler> GetResourceHandler(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request) {
std::string url = request->GetURL();
if (url.find(kTestOrigin) == 0) {
// Handle URLs in the test origin.
std::string file_name, mime_type;
if (ParseTestUrl(url, &file_name, &mime_type)) {
if (file_name == "request.html") {
// Show the request contents.
const std::string& dump = DumpRequestContents(request);
std::string str = "<html><body bgcolor=\"white\"><pre>" + dump +
"</pre></body></html>";
CefRefPtr<CefStreamReader> stream =
CefStreamReader::CreateForData(
static_cast<void*>(const_cast<char*>(str.c_str())),
str.size());
DCHECK(stream.get());
return new CefStreamResourceHandler("text/html", stream);
} else {
// Load the resource from file.
CefRefPtr<CefStreamReader> stream =
GetBinaryResourceReader(file_name.c_str());
if (stream.get())
return new CefStreamResourceHandler(mime_type, stream);
}
}
}
void SetupResourceManager(CefRefPtr<CefResourceManager> resource_manager) {
const std::string& test_origin = kTestOrigin;
return NULL;
// Add the URL filter.
resource_manager->SetUrlFilter(base::Bind(RequestUrlFilter));
// Add provider for resource dumps.
resource_manager->AddProvider(
new RequestDumpResourceProvider(test_origin + "request.html"),
0, std::string());
// Add provider for bundled resource files.
#if defined(OS_WIN)
// Read resources from the binary.
resource_manager->AddProvider(CreateBinaryResourceProvider(test_origin),
100, std::string());
#elif defined(OS_POSIX)
// Read resources from a directory on disk.
std::string resource_dir;
if (GetResourceDir(resource_dir)) {
resource_manager->AddDirectoryProvider(test_origin, resource_dir,
100, std::string());
}
#endif
}
void Alert(CefRefPtr<CefBrowser> browser, const std::string& message) {

View File

@@ -10,9 +10,9 @@
#include <string>
#include "include/cef_browser.h"
#include "include/cef_resource_handler.h"
#include "include/cef_request.h"
#include "include/wrapper/cef_message_router.h"
#include "include/wrapper/cef_resource_manager.h"
namespace client {
namespace test_runner {
@@ -30,11 +30,8 @@ std::string GetDataURI(const std::string& data,
// Returns the string representation of the specified error code.
std::string GetErrorString(cef_errorcode_t code);
// Get test resources.
CefRefPtr<CefResourceHandler> GetResourceHandler(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request);
// Set up the resource manager for tests.
void SetupResourceManager(CefRefPtr<CefResourceManager> resource_manager);
// Show a JS alert message.
void Alert(CefRefPtr<CefBrowser> browser, const std::string& message);