diff --git a/src/backend/helpers.cpp b/src/backend/helpers.cpp index d364cf00..d90cdcdd 100644 --- a/src/backend/helpers.cpp +++ b/src/backend/helpers.cpp @@ -52,6 +52,7 @@ # endif # include "windows.h" # include "shlobj.h" +# include "shlwapi.h" #endif #define BUFSIZE 4096 @@ -218,18 +219,34 @@ namespace loot { //Turns an absolute filesystem path into a valid file:// URL. std::string ToFileURL(const fs::path& file) { BOOST_LOG_TRIVIAL(trace) << "Converting file path " << file << " to a URL."; - return "file:///" + file.string(); //Seems that we don't need to worry about encoding, tested with Unicode paths. + +#if _WIN32 || _WIN64 + wstring wstr(MAX_PATH, 0); + DWORD len = MAX_PATH; + UrlCreateFromPath(ToWinWide(file.string()).c_str(), &wstr[0], &len, NULL); + string str = FromWinWide(wstr.c_str()); // Passing c_str() cuts off any unused buffer. + BOOST_LOG_TRIVIAL(trace) << "Converted to: " << str; + + return str; +#endif } #if _WIN32 || _WIN64 //Helper to turn UTF8 strings into strings that can be used by WinAPI. std::wstring ToWinWide(const std::string& str) { - int len = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length() + 1, 0, 0); - std::wstring wstr(len, NULL); - MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length() + 1, &(wstr[0]), len); + int len = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), 0, 0); + std::wstring wstr(len, 0); + MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), &(wstr[0]), len); return wstr; } + + std::string FromWinWide(const std::wstring& wstr) { + int len = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], wstr.length(), NULL, 0, NULL, NULL); + std::string str(len, 0); + WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), wstr.length(), &str[0], len, NULL, NULL); + return str; + } #endif Language::Language(const unsigned int code) { diff --git a/src/backend/helpers.h b/src/backend/helpers.h index 9d3d786e..301623d1 100644 --- a/src/backend/helpers.h +++ b/src/backend/helpers.h @@ -63,6 +63,8 @@ namespace loot { #if _WIN32 || _WIN64 //Helper to turn UTF8 strings into strings that can be used by WinAPI. std::wstring ToWinWide(const std::string& str); + + std::string FromWinWide(const std::wstring& wstr); #endif //Language class for simpler language support. diff --git a/src/gui/handler.cpp b/src/gui/handler.cpp index 85a0ba67..522426ed 100644 --- a/src/gui/handler.cpp +++ b/src/gui/handler.cpp @@ -533,6 +533,31 @@ namespace loot { frame->LoadString(ss.str(), failedUrl); } + // CefRequestHandler methods + //-------------------------- + + bool LootHandler::OnBeforeBrowse(CefRefPtr< CefBrowser > browser, + CefRefPtr< CefFrame > frame, + CefRefPtr< CefRequest > request, + bool is_redirect) { + + BOOST_LOG_TRIVIAL(trace) << "Attemping to open link: " << request->GetURL().ToString(); + BOOST_LOG_TRIVIAL(trace) << "Comparing with URL: " << ToFileURL(g_path_report); + + if (request->GetURL() == ToFileURL(g_path_report)) { + BOOST_LOG_TRIVIAL(trace) << "Link is to LOOT page, allowing CEF's default handling."; + return false; + } + + BOOST_LOG_TRIVIAL(info) << "Opening link in Windows' default handler."; + // Open readme in default application. + HINSTANCE ret = ShellExecute(0, NULL, request->GetURL().ToWString().c_str(), NULL, NULL, SW_SHOWNORMAL); + if ((int)ret <= 32) + throw error(error::windows_error, "Shell execute failed."); + + return true; + } + void LootHandler::CloseAllBrowsers(bool force_close) { if (!CefCurrentlyOn(TID_UI)) { diff --git a/src/gui/handler.h b/src/gui/handler.h index b4cf3a85..a26873a4 100644 --- a/src/gui/handler.h +++ b/src/gui/handler.h @@ -59,7 +59,8 @@ namespace loot { class LootHandler : public CefClient, public CefDisplayHandler, public CefLifeSpanHandler, - public CefLoadHandler { + public CefLoadHandler, + public CefRequestHandler { public: LootHandler(); ~LootHandler(); @@ -96,6 +97,19 @@ namespace loot { const CefString& errorText, const CefString& failedUrl) OVERRIDE; + // CefRequestHandler methods + //-------------------------- + + + virtual CefRefPtr GetRequestHandler() OVERRIDE{ + return this; + } + + virtual bool OnBeforeBrowse(CefRefPtr< CefBrowser > browser, + CefRefPtr< CefFrame > frame, + CefRefPtr< CefRequest > request, + bool is_redirect) OVERRIDE; + // Request that all existing browser windows close. void CloseAllBrowsers(bool force_close);