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:
Oliver Hamlet
2016-11-02 22:07:29 +00:00
parent e07baeebf0
commit fedf4e0530
11 changed files with 59 additions and 59 deletions
+3 -3
View File
@@ -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() {
+1 -1
View File
@@ -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();
-19
View File
@@ -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
-3
View File
@@ -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);
+1 -1
View 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
View File
@@ -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);
-1
View File
@@ -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;
+3 -2
View File
@@ -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;
}
+40 -17
View File
@@ -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;
}
}
+4
View File
@@ -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);
};
+2 -2
View File
@@ -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) {