From f30b4a04a0476ba9236146a656f6f7826403e4f4 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Sun, 3 Feb 2019 19:25:42 +0100 Subject: [PATCH] Add new options: log_file, log_severity, cache_path, ... (#221) remote_debugging_port, external_drag, command_line_switches, context_menu. WebRTC and Flash are enabled by default from now on. --- build.sh | 4 +- src/app.cpp | 52 +++++++++++++++++++++++ src/app.h | 7 +++- src/client_handler.cpp | 92 +++++++++++++++++++++++++++++++++++++++++ src/client_handler.h | 24 +++++++++++ src/main.cpp | 54 ++++++++++++++++++++---- src/mongoose_server.cpp | 8 +++- src/mongoose_server.h | 1 + src/settings.json | 6 ++- src/utils.cpp | 42 +++++++++++++++++++ src/utils.h | 1 + src/version.h | 2 +- 12 files changed, 276 insertions(+), 17 deletions(-) diff --git a/build.sh b/build.sh index 54b7182..d77df72 100755 --- a/build.sh +++ b/build.sh @@ -35,8 +35,8 @@ if [[ ${rc} = 0 ]]; then fi cp -r src/www/ build/bin/ ./build/bin/phpdesktop - rm -r blob_storage/ - rm -r GPUCache/ + #rm -r build/bin/blob_storage/ + #rm -r build/bin/GPUCache/ else echo "ERROR"; exit ${rc}; diff --git a/src/app.cpp b/src/app.cpp index f157ae9..81492e2 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -5,10 +5,62 @@ #include "app.h" #include "include/wrapper/cef_helpers.h" #include "print_handler_gtk.h" +#include "settings.h" App::App() { } +// CefApp + +void App::OnBeforeCommandLineProcessing( + const CefString& process_type, + CefRefPtr command_line) { + // command_line_switches option + if (process_type.empty()) { + // Browser process type is an empty string + json_value* app_settings = get_app_settings(); + json_value switches = + (*app_settings)["chrome"]["command_line_switches"]; + if (switches.type == json_object) { + int length = switches.u.object.length; + for (int i = 0; i < length; i++) { + std::string name = switches.u.object.values[i].name; + std::string value = static_cast( + *switches.u.object.values[i].value); + if (name.find("-") == 0) { + LOG(WARNING) << "Invalid command line switch: " << name; + continue; + } + if (value.empty()) { + LOG(INFO) << "Processing switch: " << name; + } else { + LOG(INFO) << "Processing switch: " << name << "=" << value; + } + if (command_line->HasSwitch(name)) { + if (value.empty()) { + // Switch already set, do nothing + } else { + std::string old_value = + command_line->GetSwitchValue(name); + if (old_value != value) { + // Overwrite the switch with a new value + command_line->AppendSwitchWithValue(name, value); + } + } + } else { + if (value.empty()) { + command_line->AppendSwitch(name); + } else { + command_line->AppendSwitchWithValue(name, value); + } + } + } + } + } +} + +// CefBrowserProcessHandler + void App::OnContextInitialized() { CEF_REQUIRE_UI_THREAD(); print_handler_ = new ClientPrintHandlerGtk(); diff --git a/src/app.h b/src/app.h index 37f1211..0cd1f74 100644 --- a/src/app.h +++ b/src/app.h @@ -11,13 +11,16 @@ class App : public CefApp, public: App(); - // CefApp methods: + // CefApp virtual CefRefPtr GetBrowserProcessHandler() override { return this; } + virtual void OnBeforeCommandLineProcessing( + const CefString& process_type, + CefRefPtr command_line) override; - // CefBrowserProcessHandler methods: + // CefBrowserProcessHandler virtual void OnContextInitialized() override; virtual CefRefPtr GetPrintHandler() override; diff --git a/src/client_handler.cpp b/src/client_handler.cpp index 77245d4..025cad1 100644 --- a/src/client_handler.cpp +++ b/src/client_handler.cpp @@ -47,6 +47,76 @@ CefRefPtr ClientHandler::FindBrowserByXid(::Window xid) { return NULL; } +// CefContextMenuHandler + +#define _MENU_ID_DEVTOOLS MENU_ID_USER_FIRST + 1 +#define _MENU_ID_RELOAD_PAGE MENU_ID_USER_FIRST + 2 + +void ClientHandler::OnBeforeContextMenu(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr params, + CefRefPtr model) { + CEF_REQUIRE_UI_THREAD(); + + json_value* settings = get_app_settings(); + bool enable_menu = (*settings)["chrome"]["context_menu"]["enable_menu"]; + bool navigation = (*settings)["chrome"]["context_menu"]["navigation"]; + bool print = (*settings)["chrome"]["context_menu"]["print"]; + bool view_source = (*settings)["chrome"]["context_menu"]["view_source"]; + bool devtools = (*settings)["chrome"]["context_menu"]["devtools"]; + + if (!enable_menu) { + model->Clear(); + return; + } + + if (!navigation) { + model->Remove(MENU_ID_BACK); + model->Remove(MENU_ID_FORWARD); + // Remote separator. + model->RemoveAt(0); + } + if (!print) { + model->Remove(MENU_ID_PRINT); + } + if (!view_source) { + model->Remove(MENU_ID_VIEW_SOURCE); + } + + if (!params->IsEditable() && params->GetSelectionText().empty() + && (params->GetPageUrl().length() + || params->GetFrameUrl().length())) { + if (navigation) { + model->InsertItemAt(2, _MENU_ID_RELOAD_PAGE, "Reload"); + } + if (devtools) { + model->AddSeparator(); + model->AddItem(_MENU_ID_DEVTOOLS, "Show Developer Tools"); + } + } +} + +bool ClientHandler::OnContextMenuCommand(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr params, + int command_id, + EventFlags event_flags) { + CEF_REQUIRE_UI_THREAD(); + if (command_id == _MENU_ID_RELOAD_PAGE) { + browser->ReloadIgnoreCache(); + return true; + } else if (command_id == _MENU_ID_DEVTOOLS) { + CefWindowInfo window_info; + CefBrowserSettings settings; + CefPoint inspect; + browser->GetHost()->ShowDevTools(window_info, NULL, settings, inspect); + return true; + } + return false; +} + +// CefDownloadHandler + void ClientHandler::OnBeforeDownload( CefRefPtr browser, CefRefPtr download_item, @@ -61,6 +131,21 @@ void ClientHandler::OnBeforeDownload( } } +// CefDragHandler + +bool ClientHandler::OnDragEnter(CefRefPtr browser, + CefRefPtr dragData, + DragOperationsMask mask) { + bool external_drag = (*get_app_settings())["chrome"]["external_drag"]; + if (external_drag) { + return false; + } else { + return true; + } +} + +// CefLifeSpanHandler + void ClientHandler::OnAfterCreated(CefRefPtr browser) { CEF_REQUIRE_UI_THREAD(); // Add to the list of existing browsers. @@ -77,6 +162,11 @@ void ClientHandler::OnAfterCreated(CefRefPtr browser) { void ClientHandler::OnBeforeClose(CefRefPtr browser) { CEF_REQUIRE_UI_THREAD(); + // Cookies are not flushed to disk when closing app immediately. + // Need to call FlushStore manually when browser is closing. + browser->GetHost()->GetRequestContext()->GetDefaultCookieManager(NULL) + ->FlushStore(NULL); + // Remove from the list of existing browsers. BrowserList::iterator bit = browser_list_.begin(); for (; bit != browser_list_.end(); ++bit) { @@ -92,6 +182,8 @@ void ClientHandler::OnBeforeClose(CefRefPtr browser) { } } +// CefRequestHandler + bool ClientHandler::OnQuotaRequest(CefRefPtr browser, const CefString& origin_url, int64 new_size, diff --git a/src/client_handler.h b/src/client_handler.h index 1309e4b..72b4d00 100644 --- a/src/client_handler.h +++ b/src/client_handler.h @@ -10,8 +10,10 @@ #include "dialog_handler_gtk.h" class ClientHandler : public CefClient, + public CefContextMenuHandler, public CefDisplayHandler, public CefDownloadHandler, + public CefDragHandler, public CefLifeSpanHandler, public CefLoadHandler, public CefRequestHandler @@ -26,6 +28,9 @@ class ClientHandler : public CefClient, virtual CefRefPtr FindBrowserByXid(::Window xid); // CefClient methods: + CefRefPtr GetContextMenuHandler() override { + return this; + } CefRefPtr GetDialogHandler() override { return dialog_handler_; } @@ -35,6 +40,9 @@ class ClientHandler : public CefClient, CefRefPtr GetDownloadHandler() override { return this; } + CefRefPtr GetDragHandler() override { + return this; + } CefRefPtr GetJSDialogHandler() override { return dialog_handler_; } @@ -48,6 +56,17 @@ class ClientHandler : public CefClient, return this; } + // CefContextMenuHandler + virtual void OnBeforeContextMenu(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr params, + CefRefPtr model) override; + virtual bool OnContextMenuCommand(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr params, + int command_id, + EventFlags event_flags) override; + // CefDownloadHandler virtual void OnBeforeDownload( CefRefPtr browser, @@ -55,6 +74,11 @@ class ClientHandler : public CefClient, const CefString& suggested_name, CefRefPtr callback) override; + // CefDragHandler + virtual bool OnDragEnter(CefRefPtr browser, + CefRefPtr dragData, + DragOperationsMask mask) override; + // CefLifeSpanHandler virtual void OnAfterCreated(CefRefPtr browser) override; virtual void OnBeforeClose(CefRefPtr browser) override; diff --git a/src/main.cpp b/src/main.cpp index 21fe2f2..fbbf078 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -164,15 +164,51 @@ int main(int argc, char **argv) { // Start Mongoose server mongoose_start(); - // Specify CEF global settings here. - CefSettings settings; - settings.no_sandbox = true; - CefString( &settings.log_file ) = "debug.log"; // @TODO from settings.json - settings.log_severity = LOGSEVERITY_INFO; // @TODO from settings.json - // @TODO cache_path settings.json option + // Specify CEF global settings here + CefSettings cef_settings; + cef_settings.no_sandbox = true; + + // log_file + std::string log_file((*app_settings)["chrome"]["log_file"]); + log_file = get_full_path(log_file); + CefString(&cef_settings.log_file) = log_file; + + // log_severity + std::string log_severity((*app_settings)["chrome"]["log_severity"]); + if (log_severity == "verbose") { + cef_settings.log_severity = LOGSEVERITY_VERBOSE; + } else if (log_severity == "info") { + cef_settings.log_severity = LOGSEVERITY_INFO; + } else if (log_severity == "warning") { + cef_settings.log_severity = LOGSEVERITY_WARNING; + } else if (log_severity == "error") { + cef_settings.log_severity = LOGSEVERITY_ERROR; + } else if (log_severity == "disable") { + cef_settings.log_severity = LOGSEVERITY_DISABLE; + } else { + cef_settings.log_severity = LOGSEVERITY_DEFAULT; + } - // Remote debugging port - // @todo from settings.json + // cache_path + std::string cache_path((*app_settings)["chrome"]["cache_path"]); + cache_path = get_full_path(cache_path); + CefString(&cef_settings.cache_path) = cache_path; + + // remote_debugging_port + int remote_debugging_port( + (*app_settings)["chrome"]["remote_debugging_port"]); + if (remote_debugging_port == 0) { + remote_debugging_port = random(49152, 65535+1); + int i = 100; + while (((i--) > 0) + && remote_debugging_port == mongoose_get_port_int()) { + remote_debugging_port = random(49152, 65535+1); + } + } + if (remote_debugging_port > 0) { + LOG(INFO) << "remote_debugging_port = " << remote_debugging_port; + cef_settings.remote_debugging_port = remote_debugging_port; + } // App implements application-level callbacks for the browser // process. @@ -188,7 +224,7 @@ int main(int argc, char **argv) { // file only after CEF was initialized. Before CEF is initialized // all logs are only printed to console. LOG(INFO) << "Initialize CEF"; - CefInitialize(main_args, settings, app.get(), NULL); + CefInitialize(main_args, cef_settings, app.get(), NULL); // The Chromium sandbox requires that there only be a single thread during // initialization. Therefore initialize GTK after CEF. diff --git a/src/mongoose_server.cpp b/src/mongoose_server.cpp index e0d2fcf..c9abdb0 100644 --- a/src/mongoose_server.cpp +++ b/src/mongoose_server.cpp @@ -7,7 +7,8 @@ #include "version.h" #include "include/base/cef_logging.h" -std::string g_mongoose_port = "0"; // @TODO from settings.json +std::string g_mongoose_port = "0"; +int g_mongoose_port_int = 0; std::string g_mongoose_ip_address = "127.0.0.1"; // @TODO from settings.json std::string g_mongoose_url = ""; @@ -123,6 +124,7 @@ bool mongoose_start() { // When port was set to 0 then a random free port was assigned // by OS. int port = mg_get_listening_port(g_mongoose_context); + g_mongoose_port_int = port; std::stringstream port_ss; port_ss << port; g_mongoose_port = port_ss.str(); @@ -149,6 +151,10 @@ std::string mongoose_get_port() { return g_mongoose_port; } +int mongoose_get_port_int() { + return g_mongoose_port_int; +} + std::string mongoose_get_ip_address() { return g_mongoose_ip_address; } diff --git a/src/mongoose_server.h b/src/mongoose_server.h index 0e3101f..d7773ce 100644 --- a/src/mongoose_server.h +++ b/src/mongoose_server.h @@ -7,5 +7,6 @@ bool mongoose_start(); void mongoose_stop(); std::string mongoose_get_port(); +int mongoose_get_port_int(); std::string mongoose_get_ip_address(); std::string mongoose_get_url(); diff --git a/src/settings.json b/src/settings.json index 41bfaf9..3bc5a5d 100644 --- a/src/settings.json +++ b/src/settings.json @@ -24,14 +24,16 @@ "cache_path": "webcache", "external_drag": true, "remote_debugging_port": 0, - "command_line_switches": {}, + "command_line_switches": { + "enable-media-stream": "", + "enable-system-flash": "" + }, "enable_downloads": true, "context_menu": { "enable_menu": true, "navigation": true, "print": true, "view_source": true, - "open_in_external_browser": true, "devtools": true } } diff --git a/src/utils.cpp b/src/utils.cpp index bbb3e5b..e62f046 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -49,3 +49,45 @@ std::string get_full_path(std::string path) { new_path.append(path); return new_path; } + +unsigned long mix(unsigned long a, unsigned long b, unsigned long c) { + a=a-b; a=a-c; a=a^(c >> 13); + b=b-c; b=b-a; b=b^(a << 8); + c=c-a; c=c-b; c=c^(b >> 13); + a=a-b; a=a-c; a=a^(c >> 12); + b=b-c; b=b-a; b=b^(a << 16); + c=c-a; c=c-b; c=c^(b >> 5); + a=a-b; a=a-c; a=a^(c >> 3); + b=b-c; b=b-a; b=b^(a << 10); + c=c-a; c=c-b; c=c^(b >> 15); + return c; +} + +int random(unsigned int min, unsigned int max, int recursion_level) { + /* Returns a semi-open interval [min, max) */ + static bool srand_initialized = false; + if (!srand_initialized) { + srand_initialized = true; + unsigned long seed = mix(clock(), time(NULL), getpid()); + srand(seed); + } + if (recursion_level > 100) { + // A fallback. + int ret = min + (rand() % (int)(max - min)); + return ret; + } + int base_random = rand(); /* in [0, RAND_MAX] */ + if (RAND_MAX == base_random) + return random(min, max, recursion_level + 1); + /* now guaranteed to be in [0, RAND_MAX) */ + int range = max - min, + remainder = RAND_MAX % range, + bucket = RAND_MAX / range; + /* There are range buckets, plus one smaller interval + within remainder of RAND_MAX */ + if (base_random < RAND_MAX - remainder) { + return min + base_random/bucket; + } else { + return random(min, max, recursion_level + 1); + } +} diff --git a/src/utils.h b/src/utils.h index ff8f552..402ab0e 100644 --- a/src/utils.h +++ b/src/utils.h @@ -7,3 +7,4 @@ std::string get_executable_dir(); std::string get_file_contents(std::string file); std::string get_full_path(std::string path); +int random(unsigned int min, unsigned int max, int recursion_level=0); diff --git a/src/version.h b/src/version.h index e4e9203..a24d7a2 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define PHPDESKTOP_VERSION "70.2" +#define PHPDESKTOP_VERSION "70.3"