diff --git a/src/backend/app/loot_paths.cpp b/src/backend/app/loot_paths.cpp index c8881cfe..599ee3db 100644 --- a/src/backend/app/loot_paths.cpp +++ b/src/backend/app/loot_paths.cpp @@ -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() { diff --git a/src/backend/app/loot_paths.h b/src/backend/app/loot_paths.h index 61d3b5f6..83ae33fc 100644 --- a/src/backend/app/loot_paths.h +++ b/src/backend/app/loot_paths.h @@ -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(); diff --git a/src/backend/helpers/helpers.cpp b/src/backend/helpers/helpers.cpp index 764ff5e8..d07330e1 100644 --- a/src/backend/helpers/helpers.cpp +++ b/src/backend/helpers/helpers.cpp @@ -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 diff --git a/src/backend/helpers/helpers.h b/src/backend/helpers/helpers.h index 75664edd..e522accc 100644 --- a/src/backend/helpers/helpers.h +++ b/src/backend/helpers/helpers.h @@ -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); diff --git a/src/gui/html/js/translator.js b/src/gui/html/js/translator.js index 44021996..f48509c2 100644 --- a/src/gui/html/js/translator.js +++ b/src/gui/html/js/translator.js @@ -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'; diff --git a/src/gui/loot_app.cpp b/src/gui/loot_app.cpp index 431e3f10..56cc79eb 100644 --- a/src/gui/loot_app.cpp +++ b/src/gui/loot_app.cpp @@ -62,11 +62,6 @@ CefRefPtr LootApp::GetRenderProcessHandler() { return this; } -void LootApp::OnRegisterCustomSchemes(CefRefPtr 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 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); diff --git a/src/gui/loot_app.h b/src/gui/loot_app.h index 15144278..053988cb 100644 --- a/src/gui/loot_app.h +++ b/src/gui/loot_app.h @@ -44,7 +44,6 @@ public: CefRefPtr command_line); virtual CefRefPtr GetBrowserProcessHandler() OVERRIDE; virtual CefRefPtr GetRenderProcessHandler() OVERRIDE; - virtual void OnRegisterCustomSchemes(CefRefPtr registrar) OVERRIDE; // Override CefBrowserProcessHandler methods. virtual void OnContextInitialized() OVERRIDE; diff --git a/src/gui/loot_handler.cpp b/src/gui/loot_handler.cpp index bb80158d..e58c6315 100644 --- a/src/gui/loot_handler.cpp +++ b/src/gui/loot_handler.cpp @@ -32,11 +32,13 @@ #include #include #include +#include #include #include #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; } diff --git a/src/gui/loot_scheme_handler_factory.cpp b/src/gui/loot_scheme_handler_factory.cpp index d9c52c8b..4d4fd055 100644 --- a/src/gui/loot_scheme_handler_factory.cpp +++ b/src/gui/loot_scheme_handler_factory.cpp @@ -26,6 +26,7 @@ along with LOOT. If not, see #include "backend/app/loot_paths.h" +#include #include #include @@ -43,27 +44,49 @@ CefRefPtr LootSchemeHandlerFactory::Create(CefRefPtr frame, const CefString& scheme_name, CefRefPtr 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/ - 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 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 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 stream = CefStreamReader::CreateForData((void*)error404.c_str(), error404.size()); - return new CefStreamResourceHandler(404, "Not Found", "application/octet-stream", headers, stream); - } + return headers; } } diff --git a/src/gui/loot_scheme_handler_factory.h b/src/gui/loot_scheme_handler_factory.h index 174ad0cc..564d47b1 100644 --- a/src/gui/loot_scheme_handler_factory.h +++ b/src/gui/loot_scheme_handler_factory.h @@ -36,6 +36,10 @@ public: const CefString& scheme_name, CefRefPtr 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); }; diff --git a/src/tests/backend/app/loot_paths_test.h b/src/tests/backend/app/loot_paths_test.h index cefbe5f4..9815f74a 100644 --- a/src/tests/backend/app/loot_paths_test.h +++ b/src/tests/backend/app/loot_paths_test.h @@ -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) {