mirror of
https://github.com/loot/libloot.git
synced 2026-07-27 14:16:01 -07:00
Improve internal URL handling
Use a custom domain instead of a custom scheme for greater compatibility, and handle it using the same handler as for loading l10n files.
This commit is contained in:
@@ -46,12 +46,12 @@ boost::filesystem::path LootPaths::getReadmePath() {
|
||||
return lootAppPath_ / "docs" / "index.html";
|
||||
}
|
||||
|
||||
boost::filesystem::path LootPaths::getUIIndexPath() {
|
||||
return lootAppPath_ / "resources" / "ui" / "index.html";
|
||||
boost::filesystem::path LootPaths::getResourcesPath() {
|
||||
return lootAppPath_ / "resources";
|
||||
}
|
||||
|
||||
boost::filesystem::path LootPaths::getL10nPath() {
|
||||
return lootAppPath_ / "resources" / "l10n";
|
||||
return getResourcesPath() / "l10n";
|
||||
}
|
||||
|
||||
boost::filesystem::path LootPaths::getLootDataPath() {
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace loot {
|
||||
class LootPaths {
|
||||
public:
|
||||
static boost::filesystem::path getReadmePath();
|
||||
static boost::filesystem::path getUIIndexPath();
|
||||
static boost::filesystem::path getResourcesPath();
|
||||
static boost::filesystem::path getL10nPath();
|
||||
static boost::filesystem::path getLootDataPath();
|
||||
static boost::filesystem::path getSettingsPath();
|
||||
|
||||
@@ -95,25 +95,6 @@ std::string IntToHexString(const uint32_t n) {
|
||||
return out;
|
||||
}
|
||||
|
||||
//Turns an absolute filesystem path into a valid file:// URL.
|
||||
std::string ToFileURL(const boost::filesystem::path& file) {
|
||||
BOOST_LOG_TRIVIAL(trace) << "Converting file path " << file << " to a URL.";
|
||||
string url;
|
||||
|
||||
#ifdef _WIN32
|
||||
wstring wstr(MAX_PATH, 0);
|
||||
DWORD len = MAX_PATH;
|
||||
UrlCreateFromPath(ToWinWide(file.string()).c_str(), &wstr[0], &len, NULL);
|
||||
url = FromWinWide(wstr.c_str()); // Passing c_str() cuts off any unused buffer.
|
||||
BOOST_LOG_TRIVIAL(trace) << "Converted to: " << url;
|
||||
#else
|
||||
// Let's be naive about this.
|
||||
url = "file://" + file.string();
|
||||
#endif
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
//Opens the file in its registered default application.
|
||||
void OpenInDefaultApplication(const boost::filesystem::path& file) {
|
||||
#ifdef _WIN32
|
||||
|
||||
@@ -37,9 +37,6 @@ uint32_t GetCrc32(const boost::filesystem::path& filename);
|
||||
//Converts an unsigned 32-bit integer to a hex string using BOOST's Spirit.Karma. Faster than a stringstream conversion.
|
||||
std::string IntToHexString(const uint32_t n);
|
||||
|
||||
//Turns an absolute filesystem path into a valid file:// URL.
|
||||
std::string ToFileURL(const boost::filesystem::path& file);
|
||||
|
||||
//Opens the file in its registered default application.
|
||||
void OpenInDefaultApplication(const boost::filesystem::path& file);
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
translationDataPromise = Promise.resolve(defaultTranslationData);
|
||||
} else {
|
||||
translationDataPromise = new Promise((resolve, reject) => {
|
||||
const url = `loot://l10n/${this.locale}/LC_MESSAGES/loot.mo`;
|
||||
const url = `http://loot/l10n/${this.locale}/LC_MESSAGES/loot.mo`;
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', url);
|
||||
xhr.responseType = 'arraybuffer';
|
||||
|
||||
+5
-10
@@ -62,11 +62,6 @@ CefRefPtr<CefRenderProcessHandler> LootApp::GetRenderProcessHandler() {
|
||||
return this;
|
||||
}
|
||||
|
||||
void LootApp::OnRegisterCustomSchemes(CefRefPtr<CefSchemeRegistrar> registrar) {
|
||||
// Register "loot" as a standard scheme.
|
||||
registrar->AddCustomScheme("loot", true, false, false);
|
||||
}
|
||||
|
||||
void LootApp::OnContextInitialized() {
|
||||
//Make sure this is running in the UI thread.
|
||||
assert(CefCurrentlyOn(TID_UI));
|
||||
@@ -75,15 +70,15 @@ void LootApp::OnContextInitialized() {
|
||||
CefWindowInfo window_info;
|
||||
|
||||
#ifdef _WIN32
|
||||
// On Windows we need to specify certain flags that will be passed to CreateWindowEx().
|
||||
// On Windows we need to specify certain flags that will be passed to CreateWindowEx().
|
||||
window_info.SetAsPopup(NULL, "LOOT");
|
||||
#endif
|
||||
|
||||
// Set the handler for browser-level callbacks.
|
||||
// Set the handler for browser-level callbacks.
|
||||
CefRefPtr<LootHandler> handler(new LootHandler(lootState_));
|
||||
|
||||
// Register the custom "loot" scheme handlers.
|
||||
CefRegisterSchemeHandlerFactory("loot", "l10n", new LootSchemeHandlerFactory());
|
||||
// Register the custom "loot" domain handler.
|
||||
CefRegisterSchemeHandlerFactory("http", "loot", new LootSchemeHandlerFactory());
|
||||
|
||||
// Specify CEF browser settings here.
|
||||
CefBrowserSettings browser_settings;
|
||||
@@ -102,7 +97,7 @@ void LootApp::OnContextInitialized() {
|
||||
}
|
||||
|
||||
// Set URL to load. Ignore any command line values.
|
||||
std::string url = ToFileURL(LootPaths::getUIIndexPath());
|
||||
const std::string url = "http://loot/ui/index.html";
|
||||
|
||||
// Create the first browser window.
|
||||
CefBrowserHost::CreateBrowser(window_info, handler.get(), url, browser_settings, NULL);
|
||||
|
||||
@@ -44,7 +44,6 @@ public:
|
||||
CefRefPtr<CefCommandLine> command_line);
|
||||
virtual CefRefPtr<CefBrowserProcessHandler> GetBrowserProcessHandler() OVERRIDE;
|
||||
virtual CefRefPtr<CefRenderProcessHandler> GetRenderProcessHandler() OVERRIDE;
|
||||
virtual void OnRegisterCustomSchemes(CefRefPtr<CefSchemeRegistrar> registrar) OVERRIDE;
|
||||
|
||||
// Override CefBrowserProcessHandler methods.
|
||||
virtual void OnContextInitialized() OVERRIDE;
|
||||
|
||||
@@ -32,11 +32,13 @@
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <include/base/cef_bind.h>
|
||||
#include <include/cef_app.h>
|
||||
#include <include/cef_parser.h>
|
||||
#include <include/cef_task.h>
|
||||
#include <include/wrapper/cef_closure_task.h>
|
||||
|
||||
#include "backend/app/loot_paths.h"
|
||||
#include "backend/helpers/helpers.h"
|
||||
#include "gui/loot_scheme_handler_factory.h"
|
||||
#include "gui/query_handler.h"
|
||||
#include "gui/resource.h"
|
||||
|
||||
@@ -221,9 +223,8 @@ bool LootHandler::OnBeforeBrowse(CefRefPtr< CefBrowser > browser,
|
||||
CefRefPtr< CefRequest > request,
|
||||
bool is_redirect) {
|
||||
BOOST_LOG_TRIVIAL(trace) << "Attempting to open link: " << request->GetURL().ToString();
|
||||
BOOST_LOG_TRIVIAL(trace) << "Comparing with URL: " << ToFileURL(LootPaths::getUIIndexPath());
|
||||
|
||||
if (boost::iequals(request->GetURL().ToString(), ToFileURL(LootPaths::getUIIndexPath()))) {
|
||||
if (boost::starts_with(request->GetURL().ToString(), "http://loot/")) {
|
||||
BOOST_LOG_TRIVIAL(trace) << "Link is to LOOT page, allowing CEF's default handling.";
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ along with LOOT. If not, see
|
||||
|
||||
#include "backend/app/loot_paths.h"
|
||||
|
||||
#include <include/cef_parser.h>
|
||||
#include <include/wrapper/cef_stream_resource_handler.h>
|
||||
|
||||
#include <string>
|
||||
@@ -43,27 +44,49 @@ CefRefPtr<CefResourceHandler> LootSchemeHandlerFactory::Create(CefRefPtr<CefBrow
|
||||
CefRefPtr<CefFrame> frame,
|
||||
const CefString& scheme_name,
|
||||
CefRefPtr<CefRequest> request) {
|
||||
BOOST_LOG_TRIVIAL(trace) << "Handling custom scheme: " << string(request->GetURL());
|
||||
BOOST_LOG_TRIVIAL(info) << "Handling request to URL: " << request->GetURL().ToString();
|
||||
const string filePath = GetPath(request->GetURL());
|
||||
|
||||
// Get the path from the custom URL, which is of the form
|
||||
// loot://l10n/<l10n path>
|
||||
string file = (LootPaths::getL10nPath() / request->GetURL().ToString().substr(12)).string();
|
||||
if (boost::filesystem::exists(filePath)) {
|
||||
return new CefStreamResourceHandler(200,
|
||||
"OK",
|
||||
GetMimeType(filePath),
|
||||
GetHeaders(),
|
||||
CefStreamReader::CreateForFile(filePath));
|
||||
}
|
||||
|
||||
BOOST_LOG_TRIVIAL(trace) << "File " << filePath << " not found, sending 404.";
|
||||
const string error404 = "File not found.";
|
||||
CefRefPtr<CefStreamReader> stream = CefStreamReader::CreateForData((void*)error404.c_str(), error404.size());
|
||||
return new CefStreamResourceHandler(404,
|
||||
"Not Found",
|
||||
"text/plain",
|
||||
GetHeaders(),
|
||||
stream);
|
||||
}
|
||||
|
||||
std::string LootSchemeHandlerFactory::GetPath(const CefString& url) const {
|
||||
CefURLParts urlParts;
|
||||
CefParseURL(url, urlParts);
|
||||
|
||||
return (LootPaths::getResourcesPath() / CefString(&urlParts.path).ToString()).string();
|
||||
}
|
||||
|
||||
std::string LootSchemeHandlerFactory::GetMimeType(const std::string& file) const {
|
||||
if (file.substr(file.length() - 5) == ".html")
|
||||
return "text/html";
|
||||
else if (file.substr(file.length() - 3) == ".js")
|
||||
return "application/javascript";
|
||||
else if (file.substr(file.length() - 4) == ".css")
|
||||
return "text/css";
|
||||
else
|
||||
return "application/octet-stream";
|
||||
}
|
||||
|
||||
CefResponse::HeaderMap LootSchemeHandlerFactory::GetHeaders() const {
|
||||
CefResponse::HeaderMap headers;
|
||||
headers.emplace("Access-Control-Allow-Origin", "*");
|
||||
|
||||
if (boost::filesystem::exists(file)) {
|
||||
// Load the file into a CEF stream.
|
||||
CefRefPtr<CefStreamReader> stream = CefStreamReader::CreateForFile(file);
|
||||
BOOST_LOG_TRIVIAL(trace) << "Loaded file: " << file;
|
||||
|
||||
return new CefStreamResourceHandler(200, "OK", "application/octet-stream", headers, stream);
|
||||
} else {
|
||||
BOOST_LOG_TRIVIAL(trace) << "File " << file << " not found, sending 404.";
|
||||
|
||||
const string error404 = "File not found.";
|
||||
CefRefPtr<CefStreamReader> stream = CefStreamReader::CreateForData((void*)error404.c_str(), error404.size());
|
||||
return new CefStreamResourceHandler(404, "Not Found", "application/octet-stream", headers, stream);
|
||||
}
|
||||
return headers;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,10 @@ public:
|
||||
const CefString& scheme_name,
|
||||
CefRefPtr<CefRequest> request)
|
||||
OVERRIDE;
|
||||
private:
|
||||
std::string GetPath(const CefString& url) const;
|
||||
std::string GetMimeType(const std::string& file) const;
|
||||
CefResponse::HeaderMap GetHeaders() const;
|
||||
|
||||
IMPLEMENT_REFCOUNTING(LootSchemeHandlerFactory);
|
||||
};
|
||||
|
||||
@@ -37,10 +37,10 @@ TEST(LootPaths, getReadmePathShouldUseLootAppPath) {
|
||||
EXPECT_EQ(boost::filesystem::current_path() / "docs" / "index.html", LootPaths::getReadmePath());
|
||||
}
|
||||
|
||||
TEST(LootPaths, getUIIndexPathShouldUseLootAppPath) {
|
||||
TEST(LootPaths, getResourcesPathShouldUseLootAppPath) {
|
||||
LootPaths::initialise();
|
||||
|
||||
EXPECT_EQ(boost::filesystem::current_path() / "resources" / "ui" / "index.html", LootPaths::getUIIndexPath());
|
||||
EXPECT_EQ(boost::filesystem::current_path() / "resources", LootPaths::getResourcesPath());
|
||||
}
|
||||
|
||||
TEST(LootPaths, getL10nPathShouldUseLootAppPath) {
|
||||
|
||||
Reference in New Issue
Block a user