diff --git a/api/ApplicationSettings.md b/api/ApplicationSettings.md index 390b3905..4dc0ff11 100644 --- a/api/ApplicationSettings.md +++ b/api/ApplicationSettings.md @@ -287,9 +287,9 @@ a value of "verbose", "info", "warning", "error", "error-report" or Accepted values - constants available in the cefpython module: * LOGSEVERITY_VERBOSE -* LOGSEVERITY_INFO (default) +* LOGSEVERITY_INFO * LOGSEVERITY_WARNING -* LOGSEVERITY_ERROR +* LOGSEVERITY_ERROR (default) * LOGSEVERITY_ERROR_REPORT * LOGSEVERITY_DISABLE diff --git a/docs/Knowledge-Base.md b/docs/Knowledge-Base.md index 5361122d..af38bd94 100644 --- a/docs/Knowledge-Base.md +++ b/docs/Knowledge-Base.md @@ -167,8 +167,12 @@ You can pass "--debug" command line flag to any of CEF Python examples and unit tests. It will also work with your app, as this feature is enabled in CEF Python's core. When this flag is passed the following settings will be set: -``` -settings = {"debug": True, "log_severity": cef.LOGSEVERITY_WARNING} +```python +settings = { + "debug": True, + "log_severity": cef.LOGSEVERITY_INFO, + "log_file": "debug.log", +} cef.Initialize(settings=settings) ``` diff --git a/docs/Tutorial.md b/docs/Tutorial.md index bbd3054b..91cc029a 100644 --- a/docs/Tutorial.md +++ b/docs/Tutorial.md @@ -244,7 +244,7 @@ To enable debugging set these settings: ```python settings = { "debug": True, - "log_severity": cef.LOGSEVERITY_WARNING, + "log_severity": cef.LOGSEVERITY_INFO, "log_file": "debug.log", } cef.Initialize(settings=settings) diff --git a/examples/wxpython.py b/examples/wxpython.py index 416805ce..b3b5f0f6 100644 --- a/examples/wxpython.py +++ b/examples/wxpython.py @@ -1,9 +1,8 @@ # Example of embedding CEF Python browser using wxPython library. # This example has a top menu and a browser widget without navigation bar. -# To install wxPython on Linux type "sudo apt-get install python-wxtools". - # Tested configurations: +# - wxPython 4.0 on Windows/Linux # - wxPython 3.0 on Windows/Mac # - wxPython 2.8 on Linux # - CEF Python v55.4+ @@ -35,8 +34,7 @@ def main(): sys.excepthook = cef.ExceptHook # To shutdown all CEF processes on error settings = {} if WINDOWS: - # High DPI support - settings["auto_zooming"] = "system_dpi" + settings["auto_zooming"] = "system_dpi" # High DPI support # noinspection PyUnresolvedReferences, PyArgumentList cef.DpiAware.SetProcessDpiAware() # Alternative is to embed manifest cef.Initialize(settings=settings) diff --git a/src/cefpython.pyx b/src/cefpython.pyx index dc7a672e..7b5755eb 100644 --- a/src/cefpython.pyx +++ b/src/cefpython.pyx @@ -438,12 +438,12 @@ from cef_image cimport * from main_message_loop cimport * # noinspection PyUnresolvedReferences from cef_views cimport * +from cef_log cimport * # ----------------------------------------------------------------------------- # GLOBAL VARIABLES g_debug = False -g_debugFile = "debug.log" # When put None here and assigned a local dictionary in Initialize(), later # while running app this global variable was garbage collected, see topic: @@ -462,6 +462,7 @@ cdef scoped_ptr[MainMessageLoopExternalPump] g_external_message_pump cdef py_bool g_MessageLoop_called = False cdef py_bool g_MessageLoopWork_called = False +cdef py_bool g_cef_initialized = False cdef dict g_globalClientCallbacks = {} @@ -530,14 +531,11 @@ include "handlers/v8function_handler.pyx" # Utility functions to provide settings to the C++ browser process code. cdef public void cefpython_GetDebugOptions( - cpp_bool* debug, - cpp_string* debugFile + cpp_bool* debug ) except * with gil: # Called from subprocess/cefpython_app.cpp -> CefPythonApp constructor. - cdef cpp_string cppString = PyStringToChar(g_debugFile) try: debug[0] = bool(g_debug) - debugFile.assign(cppString) except: (exc_type, exc_value, exc_trace) = sys.exc_info() sys.excepthook(exc_type, exc_value, exc_trace) @@ -618,16 +616,17 @@ def Initialize(applicationSettings=None, commandLineSwitches=None, **kwargs): # Debug settings need to be set before Debug() is called # and before the CefPythonApp class is instantiated. global g_debug - global g_debugFile if "--debug" in sys.argv: application_settings["debug"] = True - application_settings["log_file"] = "debug.log" - application_settings["log_severity"] = LOGSEVERITY_WARNING + application_settings["log_file"] = os.path.join(os.getcwd(), + "debug.log") + application_settings["log_severity"] = LOGSEVERITY_INFO sys.argv.remove("--debug") if "debug" in application_settings: g_debug = bool(application_settings["debug"]) - if "log_file" in application_settings: - g_debugFile = application_settings["log_file"] + if "log_severity" in application_settings: + if application_settings["log_severity"] <= LOGSEVERITY_INFO: + g_debug = True Debug("Initialize() called") @@ -719,11 +718,9 @@ def Initialize(applicationSettings=None, commandLineSwitches=None, **kwargs): # TODO: use the CefMainArgs(int argc, char** argv) constructor. cdef CefMainArgs cefMainArgs cdef int exitCode = 1 - with nogil: - exitCode = CefExecuteProcess(cefMainArgs, cefApp, NULL) - Debug("CefExecuteProcess(): exitCode = %s" % exitCode) - if exitCode >= 0: - sys.exit(exitCode) + + # NOTE: CefExecuteProcess shall not be called here. It should + # be called only in the subprocess main.cpp. # Make a copy as applicationSettings is a reference only # that might get destroyed later. @@ -755,6 +752,9 @@ def Initialize(applicationSettings=None, commandLineSwitches=None, **kwargs): with nogil: ret = CefInitialize(cefMainArgs, cefApplicationSettings, cefApp, NULL) + global g_cef_initialized + g_cef_initialized = True + if not ret: Debug("CefInitialize() failed") diff --git a/src/client_handler/Makefile b/src/client_handler/Makefile index 13586c8e..bdb2ee72 100644 --- a/src/client_handler/Makefile +++ b/src/client_handler/Makefile @@ -23,6 +23,7 @@ SRC = client_handler.cpp cookie_visitor.cpp resource_handler.cpp \ download_handler.cpp focus_handler.cpp js_dialog_handler.cpp \ keyboard_handler.cpp lifespan_handler.cpp load_handler.cpp \ render_handler.cpp request_handler.cpp dialog_handler.cpp \ + cef_log.cpp \ $(SRC_MORE) OBJ = $(filter %.o, $(SRC:.cpp=.o) $(SRC:.mm=.o)) diff --git a/src/client_handler/cef_log.cpp b/src/client_handler/cef_log.cpp new file mode 100644 index 00000000..62ef9ba8 --- /dev/null +++ b/src/client_handler/cef_log.cpp @@ -0,0 +1,17 @@ +// Copyright (c) 2017 CEF Python, see the Authors file. +// All rights reserved. Licensed under BSD 3-clause license. +// Project website: https://github.com/cztomczak/cefpython + +#include "include/base/cef_logging.h" + +void cef_log_info(char* msg) { + LOG(INFO) << msg; +} + +void cef_log_warning(char* msg) { + LOG(WARNING) << msg; +} + +void cef_log_error(char* msg) { + LOG(ERROR) << msg; +} diff --git a/src/client_handler/cef_log.h b/src/client_handler/cef_log.h new file mode 100644 index 00000000..094bc719 --- /dev/null +++ b/src/client_handler/cef_log.h @@ -0,0 +1,9 @@ +// Copyright (c) 2017 CEF Python, see the Authors file. +// All rights reserved. Licensed under BSD 3-clause license. +// Project website: https://github.com/cztomczak/cefpython + +#pragma once + +void cef_log_info(char* msg); +void cef_log_warning(char* msg); +void cef_log_error(char* msg); diff --git a/src/client_handler/client_handler.cpp b/src/client_handler/client_handler.cpp index f14fbaf8..f55da812 100644 --- a/src/client_handler/client_handler.cpp +++ b/src/client_handler/client_handler.cpp @@ -8,7 +8,7 @@ #include "client_handler.h" #include "common/cefpython_public_api.h" -#include "common/DebugLog.h" +#include "include/base/cef_logging.h" #if defined(OS_WIN) #include @@ -34,9 +34,9 @@ bool ClientHandler::OnProcessMessageReceived( return false; } std::string messageName = message->GetName().ToString(); - std::string logMessage = "Browser: OnProcessMessageReceived(): "; + std::string logMessage = "[Browser process] OnProcessMessageReceived(): "; logMessage.append(messageName.c_str()); - DebugLog(logMessage.c_str()); + LOG(INFO) << logMessage.c_str(); if (messageName == "OnContextCreated") { CefRefPtr arguments = message->GetArgumentList(); if (arguments->GetSize() == 1 && arguments->GetType(0) == VTYPE_INT) { @@ -45,8 +45,8 @@ bool ClientHandler::OnProcessMessageReceived( V8ContextHandler_OnContextCreated(browser, frame); return true; } else { - DebugLog("Browser: OnProcessMessageReceived(): invalid arguments" \ - ", messageName = OnContextCreated"); + LOG(ERROR) << "[Browser process] OnProcessMessageReceived():" + " invalid arguments, messageName=OnContextCreated"; return false; } } else if (messageName == "OnContextReleased") { @@ -59,8 +59,8 @@ bool ClientHandler::OnProcessMessageReceived( V8ContextHandler_OnContextReleased(browserId, frameId); return true; } else { - DebugLog("Browser: OnProcessMessageReceived(): invalid arguments" \ - ", messageName = OnContextReleased"); + LOG(ERROR) << "[Browser process] OnProcessMessageReceived():" + " invalid arguments, messageName=OnContextReleased"; return false; } } else if (messageName == "V8FunctionHandler::Execute") { @@ -80,8 +80,9 @@ bool ClientHandler::OnProcessMessageReceived( functionArguments); return true; } else { - DebugLog("Browser: OnProcessMessageReceived(): invalid arguments" \ - ", messageName = V8FunctionHandler::Execute"); + LOG(ERROR) << "[Browser process] OnProcessMessageReceived():" + " invalid arguments," + " messageName=V8FunctionHandler::Execute"; return false; } } else if (messageName == "ExecutePythonCallback") { @@ -94,8 +95,9 @@ bool ClientHandler::OnProcessMessageReceived( ExecutePythonCallback(browser, callbackId, functionArguments); return true; } else { - DebugLog("Browser: OnProcessMessageReceived(): invalid arguments" \ - ", messageName = ExecutePythonCallback"); + LOG(ERROR) << "[Browser process] OnProcessMessageReceived():" + " invalid arguments," + " messageName=ExecutePythonCallback"; return false; } } else if (messageName == "RemovePythonCallbacksForFrame") { @@ -105,8 +107,9 @@ bool ClientHandler::OnProcessMessageReceived( RemovePythonCallbacksForFrame(frameId); return true; } else { - DebugLog("Browser: OnProcessMessageReceived(): invalid arguments" \ - ", messageName = ExecutePythonCallback"); + LOG(ERROR) << "[Browser process] OnProcessMessageReceived():" + " invalid arguments," + " messageName=ExecutePythonCallback"; return false; } } diff --git a/src/client_handler/context_menu_handler.cpp b/src/client_handler/context_menu_handler.cpp index 1304e803..e6be3986 100644 --- a/src/client_handler/context_menu_handler.cpp +++ b/src/client_handler/context_menu_handler.cpp @@ -3,7 +3,7 @@ // Project website: https://github.com/cztomczak/cefpython #include "context_menu_handler.h" -#include "common/DebugLog.h" +#include "include/base/cef_logging.h" #define _MENU_ID_DEVTOOLS MENU_ID_USER_FIRST + 1 #define _MENU_ID_RELOAD_PAGE MENU_ID_USER_FIRST + 2 @@ -127,12 +127,13 @@ void OpenInExternalBrowser(const std::string& url) // Linux equivalent of ShellExecute if (url.empty()) { - DebugLog("Browser: OpenInExternalBrowser() FAILED: url is empty"); + LOG(ERROR) << "[Browser process] OpenInExternalBrowser():" + " url is empty"; return; } - std::string msg = "Browser: OpenInExternalBrowser(): url="; + std::string msg = "[Browser process] OpenInExternalBrowser(): url="; msg.append(url.c_str()); - DebugLog(msg.c_str()); + LOG(INFO) << msg.c_str(); // xdg-open is a desktop-independent tool for running // default applications. Installed by default on Ubuntu. diff --git a/src/client_handler/deprecated_client_handler_py27_64bit.vcproj b/src/client_handler/deprecated/deprecated_client_handler_py27_64bit.vcproj similarity index 100% rename from src/client_handler/deprecated_client_handler_py27_64bit.vcproj rename to src/client_handler/deprecated/deprecated_client_handler_py27_64bit.vcproj diff --git a/src/client_handler/client_handler_py27_win32.vcproj b/src/client_handler/deprecated/deprecated_client_handler_py27_win32.vcproj similarity index 100% rename from src/client_handler/client_handler_py27_win32.vcproj rename to src/client_handler/deprecated/deprecated_client_handler_py27_win32.vcproj diff --git a/src/client_handler/deprecated_client_handler_py34_32bit.vcproj b/src/client_handler/deprecated/deprecated_client_handler_py34_32bit.vcproj similarity index 100% rename from src/client_handler/deprecated_client_handler_py34_32bit.vcproj rename to src/client_handler/deprecated/deprecated_client_handler_py34_32bit.vcproj diff --git a/src/client_handler/dialog_handler_gtk.cpp b/src/client_handler/dialog_handler_gtk.cpp index 76bf1851..3d53e78a 100644 --- a/src/client_handler/dialog_handler_gtk.cpp +++ b/src/client_handler/dialog_handler_gtk.cpp @@ -18,7 +18,7 @@ #include "include/cef_parser.h" #include "include/wrapper/cef_helpers.h" -#include "LOG_DEBUG.h" +#include "include/base/cef_logging.h" #include "dialog_handler_gtk.h" #include "x11.h" @@ -159,7 +159,7 @@ GtkWindow* GetWindow(CefRefPtr browser) { // internally, so GTK wasn't yet initialized and must do it // now, so that display is available. Also must install X11 // error handlers to avoid 'BadWindow' errors. - LOG_DEBUG << "Initialize GTK"; + LOG(INFO) << "[Browser process] Initialize GTK"; gtk_init(0, NULL); InstallX11ErrorHandlers(); // Now the display is available diff --git a/src/client_handler/download_handler.cpp b/src/client_handler/download_handler.cpp index fae9b313..9e887e46 100644 --- a/src/client_handler/download_handler.cpp +++ b/src/client_handler/download_handler.cpp @@ -3,7 +3,7 @@ // Project website: https://github.com/cztomczak/cefpython #include "download_handler.h" -#include "common/DebugLog.h" +#include "include/base/cef_logging.h" void DownloadHandler::OnBeforeDownload( @@ -15,12 +15,13 @@ void DownloadHandler::OnBeforeDownload( REQUIRE_UI_THREAD(); bool downloads_enabled = ApplicationSettings_GetBool("downloads_enabled"); if (downloads_enabled) { - std::string msg = "Browser: About to download file: "; + std::string msg = "[Browser process] About to download file: "; msg.append(suggested_name.ToString().c_str()); - DebugLog(msg.c_str()); + LOG(INFO) << msg.c_str(); callback->Continue(suggested_name, true); } else { - DebugLog("Browser: Tried to download file, but downloads are disabled"); + LOG(INFO) << "[Browser process] Tried to download file," + " but downloads are disabled"; } } @@ -32,10 +33,10 @@ void DownloadHandler::OnDownloadUpdated( { REQUIRE_UI_THREAD(); if (download_item->IsComplete()) { - std::string msg = "Browser: Download completed, saved to: "; + std::string msg = "[Browser process] Download completed, saved to: "; msg.append(download_item->GetFullPath().ToString().c_str()); - DebugLog(msg.c_str()); + LOG(INFO) << msg.c_str(); } else if (download_item->IsCanceled()) { - DebugLog("Browser: Download was cancelled"); + LOG(INFO) << "[Browser process] Download was cancelled"; } } diff --git a/src/client_handler/dpi_aware.cpp b/src/client_handler/dpi_aware.cpp index 6c8a9213..48e2a13f 100644 --- a/src/client_handler/dpi_aware.cpp +++ b/src/client_handler/dpi_aware.cpp @@ -10,7 +10,7 @@ #include "dpi_aware.h" #include "include/wrapper/cef_closure_task.h" #include "include/base/cef_bind.h" -#include "LOG_DEBUG.h" +#include "include/base/cef_logging.h" const int DEFAULT_DPIX = 96; @@ -56,7 +56,8 @@ PROCESS_DPI_AWARENESS GetProcessDpiAwareness() { return result; } // Possible failures include E_INVALIDARG or E_ACCESSDENIED. - LOG_DEBUG << "Browser: GetProcessDpiAwareness failed with HR=" << hr; + LOG(INFO) << "[Browser process] GetProcessDpiAwareness():" + " hr=" << hr; } return PROCESS_DPI_UNAWARE; } @@ -88,23 +89,23 @@ void SetProcessDpiAware() { GetProcAddress(GetModuleHandleA("user32.dll"), "SetProcessDpiAwarenessInternal")); if (set_process_dpi_awareness_func) { - LOG_DEBUG << "Browser: SetProcessDpiAware: " - << "calling user32.dll SetProcessDpiAwareness"; + LOG(INFO) << "[Browser process] SetProcessDpiAware():" + " calling user32.dll SetProcessDpiAwareness"; HRESULT hr = set_process_dpi_awareness_func(PROCESS_SYSTEM_DPI_AWARE); if (SUCCEEDED(hr)) { - LOG_DEBUG << "Browser: SetBrowserDpiAware: " - "SetProcessDpiAwareness succeeded"; + LOG(INFO) << "[Browser process]: SetBrowserDpiAware():" + " SetProcessDpiAwareness succeeded"; return; } else if (hr == E_ACCESSDENIED) { - LOG_DEBUG << "Browser: SetBrowserDpiAware: " - "SetProcessDpiAwareness FAILED: " - "The DPI awareness is already set, either by calling " - "this API previously or through the application (.exe) " - "manifest."; + LOG(ERROR) << "[Browser process] SetBrowserDpiAware():" + " SetProcessDpiAwareness failed:" + " The DPI awareness is already set, either by calling" + " this API previously or through the application" + " (.exe) manifest."; // Do not return here, let's try to call SetProcessDPIAware. } else { - LOG_DEBUG << "Browser: SetBrowserDpiAware: " - "SetProcessDpiAwareness FAILED"; + LOG(ERROR) << "[Browser process] SetBrowserDpiAware():" + " SetProcessDpiAwareness failed"; // Do not return here, let's try to call SetProcessDPIAware. } } @@ -119,8 +120,8 @@ void SetProcessDpiAware() { // If cefpython.Initialize() wasn't yet called, then // this log message won't be written, as g_debug is // is set during CEF initialization. - LOG_DEBUG << "Browser: SetProcessDpiAware: " - << "calling user32.dll SetProcessDPIAware"; + LOG(INFO) << "[Browser process] SetProcessDpiAware():" + " calling user32.dll SetProcessDPIAware"; set_process_dpi_aware_func(); } } @@ -153,9 +154,9 @@ void GetDpiAwareWindowSize(int* width, int* height) { if (newZoomLevel > 0.0) { *width = *width + (int)ceil(newZoomLevel * 0.25 * (*width)); *height = *height + (int)ceil(newZoomLevel * 0.25 * (*height)); - LOG_DEBUG << "Browser: GetDpiAwareWindowSize: " - << "enlarged by " << ceil(newZoomLevel * 0.25 * 100) << "% " - << "new size = " << *width << "/" << *height; + LOG(INFO) << "[Browser process] GetDpiAwareWindowSize():" + " enlarged by " << ceil(newZoomLevel * 0.25 * 100) << "%" + " new size = " << *width << "/" << *height; } } @@ -191,9 +192,9 @@ void SetBrowserDpiSettings(CefRefPtr cefBrowser, cefBrowser->GetHost()->SetZoomLevel(newZoomLevel); if (cefBrowser->GetHost()->GetZoomLevel() != oldZoomLevel) { // OK succes. - LOG_DEBUG << "Browser: SetBrowserDpiSettings: " - << "DPI=" << dpix << " " - << "zoom=" << cefBrowser->GetHost()->GetZoomLevel(); + LOG(INFO) << "[Browser process] SetBrowserDpiSettings():" + " DPI=" << dpix << "" + " zoom=" << cefBrowser->GetHost()->GetZoomLevel(); } } else { // This code block running can also be a result of executing @@ -206,9 +207,9 @@ void SetBrowserDpiSettings(CefRefPtr cefBrowser, if (!already_logged) { already_logged = true; // OK success. - LOG_DEBUG << "Browser: SetBrowserDpiSettings: " - << "DPI=" << dpix << " " - << "zoom=" << cefBrowser->GetHost()->GetZoomLevel(); + LOG(INFO) << "[Browser process] SetBrowserDpiSettings():" + " DPI=" << dpix << "" + " zoom=" << cefBrowser->GetHost()->GetZoomLevel(); } } // We need to check zooming constantly, during loading of pages. diff --git a/src/client_handler/lifespan_handler.cpp b/src/client_handler/lifespan_handler.cpp index 0cfd2d1b..d54f5f0a 100644 --- a/src/client_handler/lifespan_handler.cpp +++ b/src/client_handler/lifespan_handler.cpp @@ -6,7 +6,7 @@ #if defined(OS_WIN) #include "dpi_aware.h" #endif -#include "LOG_DEBUG.h" +#include "include/base/cef_logging.h" bool LifespanHandler::OnBeforePopup(CefRefPtr browser, @@ -38,8 +38,8 @@ void LifespanHandler::OnAfterCreated(CefRefPtr browser) // High DPI support. CefString auto_zooming = ApplicationSettings_GetString("auto_zooming"); if (!auto_zooming.empty()) { - LOG_DEBUG << "Browser: OnAfterCreated(): auto_zooming = " - << auto_zooming.ToString(); + LOG(INFO) << "[Browser process] OnAfterCreated(): auto_zooming = " + << auto_zooming.ToString(); SetBrowserDpiSettings(browser, auto_zooming); } #endif // OS_WIN diff --git a/src/client_handler/request_context_handler.cpp b/src/client_handler/request_context_handler.cpp index ef7cc8b9..bf816cf5 100644 --- a/src/client_handler/request_context_handler.cpp +++ b/src/client_handler/request_context_handler.cpp @@ -4,7 +4,6 @@ #include "request_context_handler.h" #include "common/cefpython_public_api.h" -#include "DebugLog.h" // -------------------------------------------------------------------------- // CefRequestContextHandler diff --git a/src/client_handler/request_handler.cpp b/src/client_handler/request_handler.cpp index 69904377..c06e098d 100644 --- a/src/client_handler/request_handler.cpp +++ b/src/client_handler/request_handler.cpp @@ -3,7 +3,7 @@ // Project website: https://github.com/cztomczak/cefpython #include "request_handler.h" -#include "common/DebugLog.h" +#include "include/base/cef_logging.h" bool RequestHandler::OnBeforeBrowse(CefRefPtr browser, @@ -104,7 +104,7 @@ void RequestHandler::OnRenderProcessTerminated(CefRefPtr browser, cef_termination_status_t status) { REQUIRE_UI_THREAD(); - DebugLog("Browser: OnRenderProcessTerminated()"); + LOG(ERROR) << "[Browser process] OnRenderProcessTerminated()"; RequestHandler_OnRendererProcessTerminated(browser, status); } diff --git a/src/client_handler/x11.cpp b/src/client_handler/x11.cpp index 0c37bff4..18f7ce03 100644 --- a/src/client_handler/x11.cpp +++ b/src/client_handler/x11.cpp @@ -3,10 +3,10 @@ // Project website: https://github.com/cztomczak/cefpython #include "x11.h" -#include "LOG_DEBUG.h" +#include "include/base/cef_logging.h" int XErrorHandlerImpl(Display *display, XErrorEvent *event) { - LOG_DEBUG + LOG(INFO) << "[Browser process] " << "X error received: " << "type " << event->type << ", " << "serial " << event->serial << ", " diff --git a/src/common/DebugLog.h b/src/common/DebugLog.h deleted file mode 100644 index 4c5419a6..00000000 --- a/src/common/DebugLog.h +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) 2012 CEF Python, see the Authors file. -// All rights reserved. Licensed under BSD 3-clause license. -// Project website: https://github.com/cztomczak/cefpython - -#pragma once -#include - -extern bool g_debug; -extern std::string g_logFile; - -// Defined as "inline" to get rid of the "already defined" errors -// when linking. -inline void DebugLog(const char* szString) -{ - if (!g_debug) - return; - // TODO: get the log_file option from CefSettings. - printf("[CEF Python] %s\n", szString); - if (g_logFile.length()) { - FILE* pFile = fopen(g_logFile.c_str(), "a"); - fprintf(pFile, "[CEF Python] App: %s\n", szString); - fclose(pFile); - } -} diff --git a/src/common/LOG_DEBUG.h b/src/common/LOG_DEBUG.h deleted file mode 100644 index 672ad25e..00000000 --- a/src/common/LOG_DEBUG.h +++ /dev/null @@ -1,211 +0,0 @@ -// Taken from here: http://www.drdobbs.com/cpp/logging-in-c/201804215 -// Original author: Petru Marginean -// Modified by: Czarek Tomczak - -// Usage: -// LOG_DEBUG << "Browser: someVar = " << someVar; -// Warning: -// Log is written when ~Log() destructor is called, which -// occurs when outside of scope. This could result in log -// not being written if program crashes before code goes -// outside of current scope. You could embrace LOG_DEBUG -// statements with braces {} to guarantee the log to be -// written immediately. - -#ifndef __LOG_DEBUG_H__ -#define __LOG_DEBUG_H__ - -#include -#include -#include -#include "DebugLog.h" - -inline std::string NowTime(); - -enum TLogLevel {logERROR, logWARNING, logINFO, logDEBUG, - logDEBUG1, logDEBUG2, logDEBUG3, logDEBUG4}; - -template -class Log -{ -public: - Log(); - virtual ~Log(); - std::ostringstream& Get(TLogLevel level = logINFO); -public: - static TLogLevel& ReportingLevel(); - static std::string ToString(TLogLevel level); - static TLogLevel FromString(const std::string& level); -protected: - std::ostringstream os; -private: - Log(const Log&); - Log& operator =(const Log&); -}; - -template -Log::Log() -{ -} - -template -std::ostringstream& Log::Get(TLogLevel level) -{ - // os << "- " << NowTime(); - // os << " " << ToString(level) << ": "; - // os << std::string(level > logDEBUG ? level - logDEBUG : 0, '\t'); - return os; -} - -template -Log::~Log() -{ - os << std::endl; - /* - if (T::Stream() != stderr) { - fprintf(stderr, "%s", os.str().c_str()); - fflush(stderr); - } - T::Output(os.str()); - */ - DebugLog(os.str().c_str()); -} - -template -TLogLevel& Log::ReportingLevel() -{ - static TLogLevel reportingLevel = logDEBUG4; - return reportingLevel; -} - -template -std::string Log::ToString(TLogLevel level) -{ - static const char* const buffer[] = {"ERROR", "WARNING", "INFO", "DEBUG", - "DEBUG1", "DEBUG2", "DEBUG3", "DEBUG4"}; - return buffer[level]; -} - -template -TLogLevel Log::FromString(const std::string& level) -{ - if (level == "DEBUG4") - return logDEBUG4; - if (level == "DEBUG3") - return logDEBUG3; - if (level == "DEBUG2") - return logDEBUG2; - if (level == "DEBUG1") - return logDEBUG1; - if (level == "DEBUG") - return logDEBUG; - if (level == "INFO") - return logINFO; - if (level == "WARNING") - return logWARNING; - if (level == "ERROR") - return logERROR; - Log().Get(logWARNING) << "Unknown logging level '" << level - << "'. Using INFO level as default."; - return logINFO; -} - -class Output2FILE -{ -public: - static FILE*& Stream(); - static void Output(const std::string& msg); -}; - -inline FILE*& Output2FILE::Stream() -{ - static FILE* pStream = stderr; - return pStream; -} - -inline void Output2FILE::Output(const std::string& msg) -{ - /* - FILE* pStream = Stream(); - if (!pStream) - return; - fprintf(pStream, "%s", msg.c_str()); - fflush(pStream); - */ -} - -#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) -# if defined (BUILDING_FILELOG_DLL) -# define FILELOG_DECLSPEC __declspec (dllexport) -# elif defined (USING_FILELOG_DLL) -# define FILELOG_DECLSPEC __declspec (dllimport) -# else -# define FILELOG_DECLSPEC -# endif // BUILDING_DBSIMPLE_DLL -#else -# define FILELOG_DECLSPEC -#endif // _WIN32 - -class FILELOG_DECLSPEC FILELog : public Log {}; -//typedef Log FILELog; - -#ifndef FILELOG_MAX_LEVEL -#define FILELOG_MAX_LEVEL logDEBUG4 -#endif - -// Name conflits with cef_logging.h, see: -// https://bitbucket.org/chromiumembedded/cef/issues/1830 -// LOG, LOG_ERROR, LOG_WARNING and LOG_INFO are already defined -// in cef_logging.h and must not be used here. So far we've only -// used LOG_DEBUG in code. - -#define CEFPYTHON_LOG(level) \ - if (level > FILELOG_MAX_LEVEL) ;\ - else if (level > FILELog::ReportingLevel() || !Output2FILE::Stream()) ; \ - else FILELog().Get(level) \ - -// #define LOG_ERROR LOG(logERROR) -// #define LOG_WARNING LOG(logWARNING) -// #define LOG_INFO LOG(logINFO) -#define LOG_DEBUG CEFPYTHON_LOG(logDEBUG) - -#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) - -#include - -inline std::string NowTime() -{ - const int MAX_LEN = 200; - char buffer[MAX_LEN]; - if (GetTimeFormatA(LOCALE_USER_DEFAULT, 0, 0, - "HH':'mm':'ss", buffer, MAX_LEN) == 0) - return "Error in NowTime()"; - - char result[100] = {0}; - static DWORD first = GetTickCount(); - #pragma warning(suppress: 4996) - sprintf(result, "%s.%03ld", buffer, (long)(GetTickCount() - first) % 1000); - return result; -} - -#else - -#include - -inline std::string NowTime() -{ - char buffer[11]; - time_t t; - time(&t); - tm r = {0}; - strftime(buffer, sizeof(buffer), "%X", localtime_r(&t, &r)); - struct timeval tv; - gettimeofday(&tv, 0); - char result[100] = {0}; - sprintf(result, "%s.%03ld", buffer, (long)tv.tv_usec / 1000); - return result; -} - -#endif //WIN32 - -#endif //__LOG_DEBUG_H__ diff --git a/src/compile_time_constants.pxi b/src/compile_time_constants.pxi index 632aab59..35f85002 100644 --- a/src/compile_time_constants.pxi +++ b/src/compile_time_constants.pxi @@ -1,3 +1,3 @@ # This file was generated by setup.py -DEF UNAME_SYSNAME = "Windows" -DEF PY_MAJOR_VERSION = 3 +DEF UNAME_SYSNAME = "Linux" +DEF PY_MAJOR_VERSION = 2 diff --git a/src/extern/cef_log.pxd b/src/extern/cef_log.pxd new file mode 100644 index 00000000..04a32cfb --- /dev/null +++ b/src/extern/cef_log.pxd @@ -0,0 +1,8 @@ +# Copyright (c) 2017 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython + +cdef extern from "client_handler/cef_log.h": + void cef_log_info(char* msg) + void cef_log_warning(char* msg) + void cef_log_error(char* msg) diff --git a/src/handlers/browser_process_handler.pyx b/src/handlers/browser_process_handler.pyx index 5847d670..09463b0e 100644 --- a/src/handlers/browser_process_handler.pyx +++ b/src/handlers/browser_process_handler.pyx @@ -8,7 +8,6 @@ cdef public void BrowserProcessHandler_OnRenderProcessThreadCreated( CefRefPtr[CefListValue] extra_info ) except * with gil: try: - # Keys 0 and 1 are already set in C++ code - to pass debug options. pass except: (exc_type, exc_value, exc_trace) = sys.exc_info() @@ -19,7 +18,6 @@ cdef public void BrowserProcessHandler_OnBeforeChildProcessLaunch( ) except * with gil: try: AppendSwitchesToCommandLine(cefCommandLine, g_commandLineSwitches) - Debug("BrowserProcessHandler_OnBeforeChildProcessLaunch()") except: (exc_type, exc_value, exc_trace) = sys.exc_info() sys.excepthook(exc_type, exc_value, exc_trace) diff --git a/src/linux/binaries_64bit/kivy_.py b/src/linux/binaries_64bit/kivy_.py index 7d7ef4cc..c980aa9f 100644 --- a/src/linux/binaries_64bit/kivy_.py +++ b/src/linux/binaries_64bit/kivy_.py @@ -148,9 +148,6 @@ def start_cef(self): # Configure CEF settings = { - "debug": True, # debug messages in console and in log_file - "log_severity": cef.LOGSEVERITY_INFO, - "log_file": "debug.log", # This directories must be set on Linux "locales_dir_path": cef.GetModuleDirectory()+"/locales", "resources_dir_path": cef.GetModuleDirectory(), diff --git a/src/subprocess/cefpython_app.cpp b/src/subprocess/cefpython_app.cpp index 1f51ba27..95077702 100644 --- a/src/subprocess/cefpython_app.cpp +++ b/src/subprocess/cefpython_app.cpp @@ -22,8 +22,7 @@ #include "util.h" #include "include/wrapper/cef_closure_task.h" #include "include/base/cef_bind.h" -#include "DebugLog.h" -#include "LOG_DEBUG.h" +#include "include/base/cef_logging.h" #include #include #include "v8utils.h" @@ -34,12 +33,12 @@ #include "main_message_loop/main_message_loop_external_pump.h" #endif +// GLOBALS bool g_debug = false; -std::string g_logFile = "debug.log"; CefPythonApp::CefPythonApp() { #ifdef BROWSER_PROCESS - cefpython_GetDebugOptions(&g_debug, &g_logFile); + cefpython_GetDebugOptions(&g_debug); #endif } @@ -62,21 +61,26 @@ void CefPythonApp::OnBeforeCommandLineProcessing( if (process_name.empty()) { process_name = "browser"; } - std::string logMessage = "Command line string for the "; +#ifdef BROWSER_PROCESS + std::string logMessage = "[Browser process] "; +#else + std::string logMessage = "[Non-browser process] "; +#endif + logMessage.append("Command line string for the "); logMessage.append(process_name); logMessage.append(" process: "); std::string clString = command_line->GetCommandLineString().ToString(); logMessage.append(clString.c_str()); - // OnBeforeCommandLineProcessing() is called before - // CefRenderHandler::OnRenderThreadCreated() which sets - // the debug options. Thus debugging will always be Off - // at the time this method is called. The fix for that - // is to keep the command line string somewhere and call - // DebugLog later in OnRenderThreadCreated(). + // There is a bug in upstream CEF, log settings are initialized + // after OnBeforeCommandLineProcessing. So if g_debug is not + // checked it would always log msg even though logging info is + // disabled. However this issue does not matter, because command + // line is also logged in OnBeforeChildProcessLaunch(). + // In OnBeforeCommandLineProcessing() command line for browser + // process is logged and in OnBeforeChildProcessLaunch() command + // line for other processes is logged. if (g_debug) { - DebugLog(logMessage.c_str()); - } else { - commandLineString_ = logMessage; + LOG(INFO) << logMessage.c_str(); } } @@ -116,6 +120,16 @@ void CefPythonApp::OnBeforeChildProcessLaunch( // the libcefpythonapp library. BrowserProcessHandler_OnBeforeChildProcessLaunch(command_line); #endif // BROWSER_PROCESS + +#ifdef BROWSER_PROCESS + std::string logMessage = "[Browser process] "; +#else + std::string logMessage = "[Non-browser process] "; +#endif // BROWSER_PROCESS + logMessage.append("OnBeforeChildProcessLaunch() command line: "); + std::string clString = command_line->GetCommandLineString().ToString(); + logMessage.append(clString.c_str()); + LOG(INFO) << logMessage.c_str(); } void CefPythonApp::OnRenderProcessThreadCreated( @@ -127,8 +141,9 @@ void CefPythonApp::OnRenderProcessThreadCreated( // The equivalent in Cython is: // | extra_info.Assign(mylist.get()) REQUIRE_IO_THREAD(); - extra_info->SetBool(0, g_debug); - extra_info->SetString(1, g_logFile); + // Eg.: + // | extra_info->SetBool(0, false); + // | extra_info->SetString(1, "test"); // This is included only in the Browser process, when building // the libcefpythonapp library. BrowserProcessHandler_OnRenderProcessThreadCreated(extra_info); @@ -142,7 +157,7 @@ CefRefPtr CefPythonApp::GetPrintHandler() { // required for some of the examples. GdkDisplay* gdk_display = gdk_display_get_default(); if (!gdk_display) { - LOG_DEBUG << "Initialize GTK"; + LOG(INFO) << "[Browser process] Initialize GTK"; gtk_init(0, NULL); } #endif @@ -165,24 +180,6 @@ void CefPythonApp::OnScheduleMessagePumpWork(int64 delay_ms) { // ----------------------------------------------------------------------------- void CefPythonApp::OnRenderThreadCreated(CefRefPtr extra_info) { - if (extra_info->GetType(0) == VTYPE_BOOL) { - g_debug = extra_info->GetBool(0); - if (g_debug) { - FILELog::ReportingLevel() = logDEBUG; - } else { - // In reality this disables logging in LOG_DEBUG.h, as - // we're using only LOG_DEBUG macro. - FILELog::ReportingLevel() = logERROR; - } - } - if (extra_info->GetType(1) == VTYPE_STRING) { - g_logFile = extra_info->GetString(1).ToString(); - } - if (!commandLineString_.empty()) { - // See comment in OnBeforeCommandLineProcessing(). - DebugLog(commandLineString_.c_str()); - commandLineString_ = ""; - } } void CefPythonApp::OnWebKitInitialized() { @@ -192,7 +189,7 @@ void CefPythonApp::OnBrowserCreated(CefRefPtr browser) { } void CefPythonApp::OnBrowserDestroyed(CefRefPtr browser) { - DebugLog("Renderer: OnBrowserDestroyed()"); + LOG(INFO) << "[Renderer process] OnBrowserDestroyed()"; RemoveJavascriptBindings(browser); } @@ -207,7 +204,7 @@ bool CefPythonApp::OnBeforeNavigation(CefRefPtr browser, void CefPythonApp::OnContextCreated(CefRefPtr browser, CefRefPtr frame, CefRefPtr context) { - DebugLog("Renderer: OnContextCreated()"); + LOG(INFO) << "[Renderer process] OnContextCreated()"; CefRefPtr message = CefProcessMessage::Create( "OnContextCreated"); CefRefPtr arguments = message->GetArgumentList(); @@ -220,12 +217,12 @@ void CefPythonApp::OnContextCreated(CefRefPtr browser, /* // Example of converting int64 to string. Still need an // example of converting it back from string. - std::string logMessage = "OnContextCreated(): frameId="; + std::string logMessage = "[Renderer process] OnContextCreated(): frameId="; stringstream stream; int64 value = frame->GetIdentifier(); stream << value; logMessage.append(stream.str()); - DebugLog(logMessage.c_str()); + LOG(INFO) << logMessage.c_str(); */ // TODO: losing int64 precision, the solution is to convert // it to string and then in the Browser process back @@ -255,7 +252,7 @@ void CefPythonApp::OnContextCreated(CefRefPtr browser, void CefPythonApp::OnContextReleased(CefRefPtr browser, CefRefPtr frame, CefRefPtr context) { - DebugLog("Renderer: OnContextReleased()"); + LOG(INFO) << "[Renderer process] OnContextReleased()"; CefRefPtr message; CefRefPtr arguments; // ------------------------------------------------------------------------ @@ -308,9 +305,9 @@ bool CefPythonApp::OnProcessMessageReceived(CefRefPtr browser, CefProcessId source_process, CefRefPtr message) { std::string messageName = message->GetName().ToString(); - std::string logMessage = "Renderer: OnProcessMessageReceived(): "; + std::string logMessage = "[Renderer process] OnProcessMessageReceived(): "; logMessage.append(messageName.c_str()); - DebugLog(logMessage.c_str()); + LOG(INFO) << logMessage.c_str(); CefRefPtr args = message->GetArgumentList(); if (messageName == "DoJavascriptBindings") { if (args->GetSize() == 1 @@ -321,8 +318,9 @@ bool CefPythonApp::OnProcessMessageReceived(CefRefPtr browser, args->GetDictionary(0)->Copy(false)); DoJavascriptBindingsForBrowser(browser); } else { - DebugLog("Renderer: OnProcessMessageReceived(): invalid arguments,"\ - " messageName=DoJavascriptBindings"); + LOG(ERROR) << "[Renderer process] OnProcessMessageReceived():" + " invalid arguments," + " messageName=DoJavascriptBindings"; return false; } } else if (messageName == "ExecuteJavascriptCallback") { @@ -338,9 +336,9 @@ bool CefPythonApp::OnProcessMessageReceived(CefRefPtr browser, jsArgs->Remove(0); ExecuteJavascriptCallback(jsCallbackId, jsArgs); } else { - DebugLog("Renderer: OnProcessMessageReceived: invalid arguments," \ - "expected first argument to be a javascript callback " \ - "(int)"); + LOG(ERROR) << "[Renderer process] OnProcessMessageReceived:" + " invalid arguments, expected first argument to be" + " a javascript callback (int)"; return false; } } @@ -383,16 +381,16 @@ bool CefPythonApp::BindedFunctionExists(CefRefPtr browser, std::string::npos)); if (!(jsBindings->HasKey("objects") && jsBindings->GetType("objects") == VTYPE_DICTIONARY)) { - DebugLog("Renderer: BindedFunctionExists() FAILED: "\ - "objects dictionary not found"); + LOG(ERROR) << "[Renderer process] BindedFunctionExists():" + " objects dictionary not found"; return false; } CefRefPtr objects = \ jsBindings->GetDictionary("objects"); if (objects->HasKey(objectName)) { if (!(objects->GetType(objectName) == VTYPE_DICTIONARY)) { - DebugLog("Renderer: BindedFunctionExists() FAILED: "\ - "objects dictionary has invalid type"); + LOG(ERROR) << "[Renderer process] BindedFunctionExists():" + " objects dictionary has invalid type"; return false; } CefRefPtr methods = \ @@ -405,8 +403,8 @@ bool CefPythonApp::BindedFunctionExists(CefRefPtr browser, // This is a function call. if (!(jsBindings->HasKey("functions") && jsBindings->GetType("functions") == VTYPE_DICTIONARY)) { - DebugLog("Renderer: BindedFunctionExists() FAILED: "\ - "functions dictionary not found"); + LOG(ERROR) << "[Renderer process] BindedFunctionExists():" + " functions dictionary not found"; return false; } CefRefPtr functions = \ @@ -425,8 +423,8 @@ void CefPythonApp::DoJavascriptBindingsForBrowser( CefRefPtr jsBindings = GetJavascriptBindings(browser); if (!jsBindings.get()) { // Bindings must be set before this function is called. - DebugLog("Renderer: DoJavascriptBindingsForBrowser() FAILED: " \ - "bindings not set"); + LOG(ERROR) << "[Renderer process] DoJavascriptBindingsForBrowser():" + " bindings not set"; return; } std::vector frameIds; @@ -461,8 +459,8 @@ void CefPythonApp::DoJavascriptBindingsForBrowser( frameIds.push_back(browser->GetMainFrame()->GetIdentifier()); } if (!frameIds.size()) { - DebugLog("Renderer: DoJavascriptBindingsForBrowser() FAILED: " \ - "frameIds.size() == 0"); + LOG(ERROR) << "[Renderer process] DoJavascriptBindingsForBrowser():" + " frameIds.size() == 0"; return; } for (std::vector::iterator it = frameIds.begin(); \ @@ -472,15 +470,15 @@ void CefPythonApp::DoJavascriptBindingsForBrowser( // filled with zeros. This problem was fixed by using' // GetFrameNames() so this block of code should not // be executed anymore. - DebugLog("Renderer: DoJavascriptBindingsForBrowser() WARNING: " \ - "frameId <= 0"); + LOG(ERROR) << "[Renderer process] DoJavascriptBindingsForBrowser():" + " frameId <= 0"; // printf("[CEF Python] Renderer: frameId = %lli\n", *it); continue; } CefRefPtr frame = browser->GetFrame(*it); if (!frame.get()) { - DebugLog("Renderer: DoJavascriptBindingsForBrowser() WARNING: " \ - "GetFrame() failed"); + LOG(ERROR) << "[Renderer process] DoJavascriptBindingsForBrowser():" + " GetFrame() failed"; continue; } CefRefPtr context = frame->GetV8Context(); @@ -498,10 +496,12 @@ void CefPythonApp::DoJavascriptBindingsForFrame(CefRefPtr browser, CefRefPtr jsBindings = GetJavascriptBindings(browser); if (!jsBindings.get()) { // Bindings may not yet be set, it's okay. - DebugLog("Renderer: DoJavascriptBindingsForFrame(): bindings not set"); + LOG(INFO) << "[Renderer process] DoJavascriptBindingsForFrame():" + " bindings not set yet"; return; } - DebugLog("Renderer: DoJavascriptBindingsForFrame(): bindings are set"); + LOG(INFO) << "[Renderer process] DoJavascriptBindingsForFrame():" + " bindings are set"; if (!(jsBindings->HasKey("functions") && jsBindings->GetType("functions") == VTYPE_DICTIONARY && jsBindings->HasKey("properties") @@ -510,8 +510,8 @@ void CefPythonApp::DoJavascriptBindingsForFrame(CefRefPtr browser, && jsBindings->GetType("objects") == VTYPE_DICTIONARY && jsBindings->HasKey("bindToFrames") && jsBindings->GetType("bindToFrames") == VTYPE_BOOL)) { - DebugLog("Renderer: DoJavascriptBindingsForFrame() FAILED: " \ - "invalid data [1]"); + LOG(ERROR) << "[Renderer process] DoJavascriptBindingsForFrame():" + " invalid data [1]"; return; } @@ -527,8 +527,10 @@ void CefPythonApp::DoJavascriptBindingsForFrame(CefRefPtr browser, // not be valid. May be a timing issue. Or may be caused by // a redirect to a different origin and that creates a new // renderer process. - DebugLog("Renderer: DoJavascriptBindingsForFrame() FAILED:"\ - " V8 context provided by CEF is invalid"); + // This message is logged in the tutorial.py example which + // uses data uri created from html string. + LOG(INFO) << "[Renderer process] DoJavascriptBindingsForFrame():" + " V8 context provided by CEF is invalid"; return; } context->Enter(); @@ -544,8 +546,8 @@ void CefPythonApp::DoJavascriptBindingsForFrame(CefRefPtr browser, // | bool bindToFrames = jsBindings->GetBool("bindToFrames"); if (!(functions->IsValid() && properties->IsValid() && objects->IsValid())) { - DebugLog("Renderer: DoJavascriptBindingsForFrame() FAILED: " \ - "invalid data [2]"); + LOG(ERROR) << "[Renderer process] DoJavascriptBindingsForFrame():" + " invalid data [2]"; if (didEnterContext) context->Exit(); return; @@ -556,8 +558,8 @@ void CefPythonApp::DoJavascriptBindingsForFrame(CefRefPtr browser, // FUNCTIONS. std::vector functionsVector; if (!functions->GetKeys(functionsVector)) { - DebugLog("Renderer: DoJavascriptBindingsForFrame(): " \ - "functions->GetKeys() FAILED"); + LOG(ERROR) << "[Renderer process] DoJavascriptBindingsForFrame():" + " functions->GetKeys() failed"; if (didEnterContext) context->Exit(); return; @@ -575,8 +577,8 @@ void CefPythonApp::DoJavascriptBindingsForFrame(CefRefPtr browser, properties); std::vector v8Keys; if (!v8Properties->GetKeys(v8Keys)) { - DebugLog("DoJavascriptBindingsForFrame() FAILED: " \ - "v8Properties->GetKeys() failed"); + LOG(ERROR) << "[Renderer process] DoJavascriptBindingsForFrame():" + " v8Properties->GetKeys() failed"; if (didEnterContext) context->Exit(); return; @@ -590,8 +592,8 @@ void CefPythonApp::DoJavascriptBindingsForFrame(CefRefPtr browser, // OBJECTS AND ITS METHODS. std::vector objectsVector; if (!objects->GetKeys(objectsVector)) { - DebugLog("Renderer: DoJavascriptBindingsForFrame() FAILED: " \ - "objects->GetKeys() failed"); + LOG(ERROR) << "[Renderer process] DoJavascriptBindingsForFrame():" + " objects->GetKeys() failed"; if (didEnterContext) context->Exit(); return; @@ -603,8 +605,8 @@ void CefPythonApp::DoJavascriptBindingsForFrame(CefRefPtr browser, v8Window->SetValue(objectName, v8Object, V8_PROPERTY_ATTRIBUTE_NONE); // METHODS. if (!(objects->GetType(objectName) == VTYPE_DICTIONARY)) { - DebugLog("Renderer: DoJavascriptBindingsForFrame() FAILED: " \ - "objects->GetType() != VTYPE_DICTIONARY"); + LOG(ERROR) << "[Renderer process] DoJavascriptBindingsForFrame():" + " objects->GetType() != VTYPE_DICTIONARY"; if (didEnterContext) context->Exit(); return; @@ -613,8 +615,8 @@ void CefPythonApp::DoJavascriptBindingsForFrame(CefRefPtr browser, objects->GetDictionary(objectName); std::vector methodsVector; if (!(methods->IsValid() && methods->GetKeys(methodsVector))) { - DebugLog("Renderer: DoJavascriptBindingsForFrame() FAILED: " \ - "methods->GetKeys() failed"); + LOG(ERROR) << "[Renderer process] DoJavascriptBindingsForFrame():" + " methods->GetKeys() failed"; if (didEnterContext) context->Exit(); return; diff --git a/src/subprocess/cefpython_app.h b/src/subprocess/cefpython_app.h index e76b2691..f9336ba3 100644 --- a/src/subprocess/cefpython_app.h +++ b/src/subprocess/cefpython_app.h @@ -10,9 +10,9 @@ // CefPythonApp class is instantiated in subprocess and in // cefpython.pyx for the browser process, so the code is shared. -// Using printf() in CefRenderProcessHandler won't work, use -// the DebugLog() function instead, it will write the message -// to the "debug.log" file. +// Using printf() in CefRenderProcessHandler won't work on some +// operating systems, use LOG(INFO) macro instead, it will write +// the message to the "debug.log" file. class CefPythonApp : public CefApp, @@ -20,7 +20,6 @@ class CefPythonApp : public CefRenderProcessHandler { protected: std::map > javascriptBindings_; - std::string commandLineString_; CefRefPtr print_handler_; public: diff --git a/src/subprocess/deprecated_libcefpythonapp_py27_64bit.vcproj b/src/subprocess/deprecated/deprecated_libcefpythonapp_py27_64bit.vcproj similarity index 100% rename from src/subprocess/deprecated_libcefpythonapp_py27_64bit.vcproj rename to src/subprocess/deprecated/deprecated_libcefpythonapp_py27_64bit.vcproj diff --git a/src/subprocess/libcefpythonapp_py27_win32.vcproj b/src/subprocess/deprecated/deprecated_libcefpythonapp_py27_win32.vcproj similarity index 100% rename from src/subprocess/libcefpythonapp_py27_win32.vcproj rename to src/subprocess/deprecated/deprecated_libcefpythonapp_py27_win32.vcproj diff --git a/src/subprocess/deprecated_libcefpythonapp_py34_32bit.vcproj b/src/subprocess/deprecated/deprecated_libcefpythonapp_py34_32bit.vcproj similarity index 100% rename from src/subprocess/deprecated_libcefpythonapp_py34_32bit.vcproj rename to src/subprocess/deprecated/deprecated_libcefpythonapp_py34_32bit.vcproj diff --git a/src/subprocess/deprecated_subprocess_64bit.vcproj b/src/subprocess/deprecated/deprecated_subprocess_64bit.vcproj similarity index 100% rename from src/subprocess/deprecated_subprocess_64bit.vcproj rename to src/subprocess/deprecated/deprecated_subprocess_64bit.vcproj diff --git a/src/subprocess/subprocess_win32.vcproj b/src/subprocess/deprecated/deprecated_subprocess_win32.vcproj similarity index 100% rename from src/subprocess/subprocess_win32.vcproj rename to src/subprocess/deprecated/deprecated_subprocess_win32.vcproj diff --git a/src/subprocess/javascript_callback.cpp b/src/subprocess/javascript_callback.cpp index fd9f55e5..9aeaf80c 100644 --- a/src/subprocess/javascript_callback.cpp +++ b/src/subprocess/javascript_callback.cpp @@ -5,9 +5,9 @@ #include "javascript_callback.h" #include #include -#include "DebugLog.h" #include "v8utils.h" #include "cefpython_app.h" +#include "include/base/cef_logging.h" template inline std::string AnyToString(const T& value) @@ -49,17 +49,18 @@ CefString PutJavascriptCallback( bool ExecuteJavascriptCallback(int callbackId, CefRefPtr args) { if (g_jsCallbackMap.empty()) { - DebugLog("Renderer: ExecuteJavascriptCallback() FAILED: " \ - "callback map is empty"); + LOG(ERROR) << "[Renderer process] ExecuteJavascriptCallback():" + " callback map is empty"; return false; } JavascriptCallbackMap::const_iterator it = g_jsCallbackMap.find( callbackId); if (it == g_jsCallbackMap.end()) { - std::string logMessage = "Renderer: ExecuteJavascriptCallback() " - "FAILED: callback not found, id="; + std::string logMessage = "[Renderer process]" + " ExecuteJavascriptCallback():" + " callback not found, id="; logMessage.append(AnyToString(callbackId)); - DebugLog(logMessage.c_str()); + LOG(ERROR) << logMessage.c_str(); return false; } CefRefPtr frame = it->second.first; @@ -74,8 +75,8 @@ bool ExecuteJavascriptCallback(int callbackId, CefRefPtr args) { return true; } else { context->Exit(); - DebugLog("Renderer: ExecuteJavascriptCallback() FAILED: " \ - "callback->ExecuteFunction() FAILED"); + LOG(ERROR) << "[Renderer process] ExecuteJavascriptCallback():" + " callback->ExecuteFunction() failed"; return false; } } @@ -95,8 +96,9 @@ void RemoveJavascriptCallbacksForFrame(CefRefPtr frame) { // | ++it; // This would cause an infinite loop. g_jsCallbackMap.erase(it++); - DebugLog("Renderer: RemoveJavascriptCallbacksForFrame(): " \ - "removed js callback from the map"); + LOG(INFO) << "[Renderer process]" + " RemoveJavascriptCallbacksForFrame():" + " removed js callback from the map"; } else { ++it; } diff --git a/src/subprocess/v8function_handler.cpp b/src/subprocess/v8function_handler.cpp index 508a78bb..0ce3a980 100644 --- a/src/subprocess/v8function_handler.cpp +++ b/src/subprocess/v8function_handler.cpp @@ -4,7 +4,7 @@ #include "cefpython_app.h" #include "v8utils.h" -#include "DebugLog.h" +#include "include/base/cef_logging.h" bool V8FunctionHandler::Execute(const CefString& functionName, CefRefPtr thisObject, @@ -14,15 +14,16 @@ bool V8FunctionHandler::Execute(const CefString& functionName, if (!CefV8Context::InContext()) { // CefV8Context::GetCurrentContext may not be called when // not in a V8 context. - DebugLog("Renderer: V8FunctionHandler::Execute() FAILED:"\ - " not inside a V8 context"); + LOG(ERROR) << "[Renderer process] V8FunctionHandler::Execute():" + " not inside a V8 context"; return false; } CefRefPtr context = CefV8Context::GetCurrentContext(); CefRefPtr browser = context.get()->GetBrowser(); CefRefPtr frame = context.get()->GetFrame(); if (pythonCallbackId_) { - DebugLog("Renderer: V8FunctionHandler::Execute(): python callback"); + LOG(INFO) << "[Renderer process] V8FunctionHandler::Execute():" + " python callback"; CefRefPtr functionArguments = V8ValueListToCefListValue( v8Arguments); CefRefPtr processMessage = \ @@ -35,7 +36,8 @@ bool V8FunctionHandler::Execute(const CefString& functionName, returnValue = CefV8Value::CreateNull(); return true; } else { - DebugLog("Renderer: V8FunctionHandler::Execute(): js binding"); + LOG(INFO) << "[Renderer process] V8FunctionHandler::Execute():" + " js binding"; if (!(cefPythonApp_.get() \ && cefPythonApp_->BindedFunctionExists( \ browser, functionName))) { diff --git a/src/subprocess/v8utils.cpp b/src/subprocess/v8utils.cpp index e53d46a4..684f8c4e 100644 --- a/src/subprocess/v8utils.cpp +++ b/src/subprocess/v8utils.cpp @@ -9,7 +9,7 @@ #include "v8utils.h" #include "javascript_callback.h" -#include "DebugLog.h" +#include "include/base/cef_logging.h" #include "cefpython_app.h" #include @@ -33,12 +33,13 @@ void V8ValueAppendToCefListValue(CefRefPtr v8Value, CefRefPtr listValue, int nestingLevel) { if (!v8Value->IsValid()) { - DebugLog("V8ValueAppendToCefListValue(): IsValid() FAILED"); + LOG(ERROR) << "[Renderer process] V8ValueAppendToCefListValue():" + " IsValid() failed"; return; } if (nestingLevel > 8) { - DebugLog("V8ValueAppendToCefListValue(): WARNING: max nesting level (8) " \ - "exceeded"); + LOG(ERROR) << "[Renderer process] V8ValueAppendToCefListValue():" + " max nesting level (8) exceeded"; return; } if (v8Value->IsUndefined() || v8Value->IsNull()) { @@ -53,7 +54,8 @@ void V8ValueAppendToCefListValue(CefRefPtr v8Value, &uint32_value, sizeof(uint32_value)); listValue->SetBinary((int)listValue->GetSize(), binaryValue); } else if (v8Value->IsDouble()) { - listValue->SetDouble((int)listValue->GetSize(), v8Value->GetDoubleValue()); + listValue->SetDouble((int)listValue->GetSize(), + v8Value->GetDoubleValue()); } else if (v8Value->IsDate()) { // TODO: in time_utils.pyx there are already functions for // converting cef_time_t to python DateTime, we could easily @@ -86,8 +88,9 @@ void V8ValueAppendToCefListValue(CefRefPtr v8Value, listValue->SetString((int)listValue->GetSize(), strCallbackId); } else { listValue->SetNull((int)listValue->GetSize()); - DebugLog("V8ValueAppendToCefListValue() FAILED: not in V8 context" - " , FATAL ERROR!"); + LOG(ERROR) << "[Renderer process] V8ValueAppendToCefListValue():" + " not in V8 context"; + return; } } else if (v8Value->IsObject()) { // Check for IsObject() must happen after the IsArray() @@ -96,7 +99,8 @@ void V8ValueAppendToCefListValue(CefRefPtr v8Value, V8ObjectToCefDictionaryValue(v8Value, nestingLevel + 1)); } else { listValue->SetNull((int)listValue->GetSize()); - DebugLog("V8ValueAppendToCefListValue() FAILED: unknown V8 type"); + LOG(ERROR) << "[Renderer process] V8ValueAppendToCefListValue():" + " unknown V8 type"; } } @@ -104,22 +108,25 @@ CefRefPtr V8ObjectToCefDictionaryValue( CefRefPtr v8Object, int nestingLevel) { if (!v8Object->IsValid()) { - DebugLog("V8ObjectToCefDictionaryValue(): IsValid() FAILED"); + LOG(ERROR) << "[Renderer process] V8ObjectToCefDictionaryValue():" + " IsValid() failed"; return CefDictionaryValue::Create(); } if (nestingLevel > 8) { - DebugLog("V8ObjectToCefDictionaryValue(): WARNING: " \ - "max nesting level (8) exceeded"); + LOG(ERROR) << "[Renderer process] V8ObjectToCefDictionaryValue():" + " max nesting level (8) exceeded"; return CefDictionaryValue::Create(); } if (!v8Object->IsObject()) { - DebugLog("V8ObjectToCefDictionaryValue(): IsObject() FAILED"); + LOG(ERROR) << "[Renderer process] V8ObjectToCefDictionaryValue():" + " IsObject() failed"; return CefDictionaryValue::Create(); } CefRefPtr ret = CefDictionaryValue::Create(); std::vector keys; if (!v8Object->GetKeys(keys)) { - DebugLog("V8ObjectToCefDictionaryValue(): GetKeys() FAILED"); + LOG(ERROR) << "[Renderer process] V8ObjectToCefDictionaryValue():" + " GetKeys() failed"; return ret; } for (std::vector::iterator it = keys.begin(); \ @@ -172,8 +179,9 @@ CefRefPtr V8ObjectToCefDictionaryValue( ret->SetString(key, strCallbackId); } else { ret->SetNull(key); - DebugLog("V8ObjectToCefDictionaryValue() FAILED: " \ - "not in V8 context FATAL ERROR!"); + LOG(ERROR) << "[Renderer process]" + " V8ObjectToCefDictionaryValue():" + " not in V8 context"; } } else if (v8Value->IsObject()) { // Check for IsObject() must happen after the IsArray() @@ -182,7 +190,8 @@ CefRefPtr V8ObjectToCefDictionaryValue( V8ObjectToCefDictionaryValue(v8Value, nestingLevel + 1)); } else { ret->SetNull(key); - DebugLog("V8ObjectToCefDictionaryValue() FAILED: unknown V8 type"); + LOG(ERROR) << "[Renderer process] V8ObjectToCefDictionaryValue():" + " unknown V8 type"; } } return ret; @@ -223,13 +232,13 @@ CefRefPtr CefListValueToV8Value( CefRefPtr listValue, int nestingLevel) { if (!listValue->IsValid()) { - DebugLog("CefListValueToV8Value() FAILED: " \ - "CefDictionaryValue is invalid"); + LOG(ERROR) << "[Renderer process] CefListValueToV8Value():" + " CefDictionaryValue is invalid"; return CefV8Value::CreateNull(); } if (nestingLevel > 8) { - DebugLog("CefListValueToV8Value(): WARNING: " \ - "max nesting level (8) exceeded"); + LOG(ERROR) << "[Renderer process] CefListValueToV8Value():" + " max nesting level (8) exceeded"; return CefV8Value::CreateNull(); } int listSize = (int)listValue->GetSize(); @@ -269,8 +278,8 @@ CefRefPtr CefListValueToV8Value( CefV8Value::CreateFunction( callbackName, v8FunctionHandler)); } else { - DebugLog("CefListValueToV8Value(): WARNING: " \ - "unknown binary value, setting value to null"); + LOG(ERROR) << "[Renderer process] CefListValueToV8Value():" + " unknown binary value, setting value to null"; success = ret->SetValue(key, CefV8Value::CreateNull()); } } else if (valueType == VTYPE_DICTIONARY) { @@ -284,14 +293,14 @@ CefRefPtr CefListValueToV8Value( listValue->GetList(key), nestingLevel + 1)); } else { - DebugLog("CefListValueToV8Value(): WARNING: " \ - "unknown type, setting value to null"); + LOG(ERROR) << "[Renderer process] CefListValueToV8Value():" + " unknown type, setting value to null"; success = ret->SetValue(key, CefV8Value::CreateNull()); } if (!success) { - DebugLog("CefListValueToV8Value(): WARNING: " \ - "ret->SetValue() failed"); + LOG(ERROR) << "[Renderer process] CefListValueToV8Value():" + " ret->SetValue() failed"; } } return ret; @@ -301,19 +310,19 @@ CefRefPtr CefDictionaryValueToV8Value( CefRefPtr dictValue, int nestingLevel) { if (!dictValue->IsValid()) { - DebugLog("CefDictionaryValueToV8Value() FAILED: " \ - "CefDictionaryValue is invalid"); + LOG(ERROR) << "[Renderer process] CefDictionaryValueToV8Value():" + " CefDictionaryValue is invalid"; return CefV8Value::CreateNull(); } if (nestingLevel > 8) { - DebugLog("CefDictionaryValueToV8Value(): WARNING: " \ - "max nesting level (8) exceeded"); + LOG(ERROR) << "[Renderer process] CefDictionaryValueToV8Value():" + " max nesting level (8) exceeded"; return CefV8Value::CreateNull(); } std::vector keys; if (!dictValue->GetKeys(keys)) { - DebugLog("CefDictionaryValueToV8Value() FAILED: " \ - "dictValue->GetKeys() failed"); + LOG(ERROR) << "[Renderer process] CefDictionaryValueToV8Value():" + " dictValue->GetKeys() failed"; return CefV8Value::CreateNull(); } CefRefPtr ret = CefV8Value::CreateObject(NULL, NULL); @@ -360,8 +369,8 @@ CefRefPtr CefDictionaryValueToV8Value( callbackName, v8FunctionHandler), V8_PROPERTY_ATTRIBUTE_NONE); } else { - DebugLog("CefListValueToV8Value(): WARNING: " \ - "unknown binary value, setting value to null"); + LOG(ERROR) << "[Renderer process] CefListValueToV8Value():" + " unknown binary value, setting value to null"; success = ret->SetValue(key, CefV8Value::CreateNull(), V8_PROPERTY_ATTRIBUTE_NONE); @@ -379,15 +388,15 @@ CefRefPtr CefDictionaryValueToV8Value( nestingLevel + 1), V8_PROPERTY_ATTRIBUTE_NONE); } else { - DebugLog("CefDictionaryValueToV8Value(): WARNING: " \ - "unknown type, setting value to null"); + LOG(ERROR) << "[Renderer process] CefDictionaryValueToV8Value():" + " unknown type, setting value to null"; success = ret->SetValue(key, CefV8Value::CreateNull(), V8_PROPERTY_ATTRIBUTE_NONE); } if (!success) { - DebugLog("CefDictionaryValueToV8Value(): WARNING: " \ - "ret->SetValue() failed"); + LOG(ERROR) << "[Renderer process] CefDictionaryValueToV8Value():" + " ret->SetValue() failed"; } } return ret; diff --git a/src/utils.pyx b/src/utils.pyx index 3f51b25a..62781196 100644 --- a/src/utils.pyx +++ b/src/utils.pyx @@ -43,22 +43,17 @@ cpdef py_bool IsThread(int threadID): cpdef object Debug(py_string msg): """Print debug message. Will be shown only when settings.debug=True.""" - if not g_debug: - return # In Python 3 str or bytes may be passed if type(msg) != str and type(msg) == bytes: msg = msg.decode("utf-8", "replace") # Convert to str in case other kind of object was passed msg = str(msg) - msg = "[CEF Python] "+msg - print(msg) - if g_debugFile: - try: - with open(g_debugFile, "a") as file_: - file_.write(msg+"\n") - except: - print("[CEF Python] WARNING: failed writing to debug file: %s" % ( - g_debugFile)) + msg = "[Browser process] " + msg + # CEF logging is initialized only after CEF was initialized. + # Otherwise the default is LOGSEVERITY_INFO and log_file is + # none. + if g_cef_initialized or g_debug: + cef_log_info(msg) cdef void NonCriticalError(py_string msg) except *: """Notify about error gently. Does not terminate application.""" @@ -67,15 +62,8 @@ cdef void NonCriticalError(py_string msg) except *: msg = msg.decode("utf-8", "replace") # Convert to str in case other kind of object was passed msg = str(msg) - msg = "[CEF Python] ERROR: "+msg - print(msg) - if g_debugFile: - try: - with open(g_debugFile, "a") as file_: - file_.write(msg+"\n") - except: - print("[CEF Python] WARNING: failed writing to debug file: %s" % ( - g_debugFile)) + msg = "[Browser process] " + msg + cef_log_error(PyStringToChar(msg)) cpdef str GetSystemError(): IF UNAME_SYSNAME == "Windows": diff --git a/tools/cython_setup.py b/tools/cython_setup.py index 368d5ccc..29baa755 100644 --- a/tools/cython_setup.py +++ b/tools/cython_setup.py @@ -171,21 +171,21 @@ def set_compiler_options(options): if LINUX: os.environ["CC"] = "g++" os.environ["CXX"] = "g++" + extra_compile_args.extend(["-std=gnu++11"]) + + # Fix "ImportError ... undefined symbol ..." caused by CEF's + # include/base/ headers by adding the -flto flag (Issue #230). + # Unfortunately -flto prolongs compilation time significantly. + # More on the other flags: https://stackoverflow.com/questions/ + # 6687630/ . if FAST_FLAG: - extra_compile_args.extend(["-flto", - "-std=gnu++11"]) + extra_compile_args.extend(["-flto"]) extra_link_args.extend(["-flto"]) else: - # Fix "ImportError ... undefined symbol ..." caused by CEF's - # include/base/ headers by adding the -flto flag (Issue #230). - # Unfortunately -flto prolongs compilation time significantly. - # More on the other flags: https://stackoverflow.com/questions/ - # 6687630/ . extra_compile_args.extend(["-flto", "-fdata-sections", - "-ffunction-sections", - "-std=gnu++11"]) + "-ffunction-sections"]) extra_link_args.extend(["-flto", "-Wl,--gc-sections"])