[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/2php/cefpython/cefpython51/src/client_handler/client_handler.cpp [Back]  [Original]

// Copyright (c) 2012-2014 The CEF Python authors. All rights reserved.
// License: New BSD License.
// Website: http://code.google.com/p/cefpython/

// NOTE: clienthandler code is running only in the BROWSER PROCESS.
//       cefpythonapp code is running in both BROWSER PROCESS and subprocess
//       (see the subprocess/ directory).

#include "client_handler.h"
#include "cefpython_public_api.h"
#include "DebugLog.h"
#include "LOG_DEBUG.h"

#if defined(OS_WIN)
#include 
#pragma comment(lib, "Shell32.lib")
#include "dpi_aware.h"
#elif defined(OS_LINUX)
#include 
#include 
#endif

// ----------------------------------------------------------------------------
// Linux equivalent of ShellExecute
// ----------------------------------------------------------------------------

#if defined(OS_LINUX)
void OpenInExternalBrowser(const std::string& url)
{
    if (url.empty()) {
        DebugLog("Browser: OpenInExternalBrowser() FAILED: url is empty");
        return;
    }
    std::string msg = "Browser: OpenInExternalBrowser(): url=";
    msg.append(url.c_str());
    DebugLog(msg.c_str());

    // xdg-open is a desktop-independent tool for running
    // default applications. Installed by default on Ubuntu.
    // xdg-open process is running in the backround until
    // cefpython app closes.
    std::string prog = "xdg-open";

    // Using system() opens up for bugs and exploits, not
    // recommended.

    // Fork yourself and run in parallel, do not block the
    // current proces.
    char *args[3];
    args[0] = (char*) prog.c_str();
    args[1] = (char*) url.c_str();
    args[2] = 0;
    pid_t pid = fork();
    if (!pid) {
        execvp(prog.c_str(), args);
    }
}
#endif

// ----------------------------------------------------------------------------
// CefClient
// ----------------------------------------------------------------------------

bool ClientHandler::OnProcessMessageReceived(CefRefPtr browser,
                                        CefProcessId source_process,
                                        CefRefPtr message) {
    if (source_process != PID_RENDERER) {
        return false;
    }
    std::string messageName = message->GetName().ToString();
    std::string logMessage = "Browser: OnProcessMessageReceived(): ";
    logMessage.append(messageName.c_str());
    DebugLog(logMessage.c_str());
    if (messageName == "OnContextCreated") {
        CefRefPtr arguments = message->GetArgumentList();
        if (arguments->GetSize() == 1 && arguments->GetType(0) == VTYPE_INT) {
            int64 frameId = arguments->GetInt(0);
            CefRefPtr frame = browser->GetFrame(frameId);
            V8ContextHandler_OnContextCreated(browser, frame);
            return true;
        } else {
            DebugLog("Browser: OnProcessMessageReceived(): invalid arguments" \
                    ", messageName = OnContextCreated");
            return false;
        }
    } else if (messageName == "OnContextReleased") {
        CefRefPtr arguments = message->GetArgumentList();
        if (arguments->GetSize() == 2 \
                && arguments->GetType(0) == VTYPE_INT \
                && arguments->GetType(1) == VTYPE_INT) {
            int browserId = arguments->GetInt(0);
            int64 frameId = arguments->GetInt(1);
            V8ContextHandler_OnContextReleased(browserId, frameId);
            return true;
        } else {
            DebugLog("Browser: OnProcessMessageReceived(): invalid arguments" \
                    ", messageName = OnContextReleased");
            return false;
        }
    } else if (messageName == "V8FunctionHandler::Execute") {
        CefRefPtr arguments = message->GetArgumentList();
        if (arguments->GetSize() == 3
                && arguments->GetType(0) == VTYPE_INT // frameId
                && arguments->GetType(1) == VTYPE_STRING // functionName
                && arguments->GetType(2) == VTYPE_LIST) { // functionArguments
            int64 frameId = arguments->GetInt(0);
            CefString functionName = arguments->GetString(1);
            CefRefPtr functionArguments = arguments->GetList(2);
            CefRefPtr frame = browser->GetFrame(frameId);
            V8FunctionHandler_Execute(browser, frame, functionName, functionArguments);
            return true;
        } else {
            DebugLog("Browser: OnProcessMessageReceived(): invalid arguments" \
                    ", messageName = V8FunctionHandler::Execute");
            return false;
        }
    } else if (messageName == "ExecutePythonCallback") {
        CefRefPtr arguments = message->GetArgumentList();
        if (arguments->GetSize() == 2
                && arguments->GetType(0) == VTYPE_INT // callbackId
                && arguments->GetType(1) == VTYPE_LIST) { // functionArguments
            int callbackId = arguments->GetInt(0);
            CefRefPtr functionArguments = arguments->GetList(1);
            ExecutePythonCallback(browser, callbackId, functionArguments);
            return true;
        } else {
            DebugLog("Browser: OnProcessMessageReceived(): invalid arguments" \
                    ", messageName = ExecutePythonCallback");
            return false;
        }
    } else if (messageName == "RemovePythonCallbacksForFrame") {
        CefRefPtr arguments = message->GetArgumentList();
        if (arguments->GetSize() == 1 && arguments->GetType(0) == VTYPE_INT) {
            int frameId = arguments->GetInt(0);
            RemovePythonCallbacksForFrame(frameId);
            return true;
        } else {
            DebugLog("Browser: OnProcessMessageReceived(): invalid arguments" \
                    ", messageName = ExecutePythonCallback");
            return false;
        }
    }
    return false;
}

// ----------------------------------------------------------------------------
// CefLifeSpanHandler
// ----------------------------------------------------------------------------

bool ClientHandler::OnBeforePopup(CefRefPtr browser,
                         CefRefPtr frame,
                         const CefString& target_url,
                         const CefString& target_frame_name,
                         WindowOpenDisposition target_disposition,
                         bool user_gesture,
                         const CefPopupFeatures& popupFeatures,
                         CefWindowInfo& windowInfo,
                         CefRefPtr& client,
                         CefBrowserSettings& settings,
                         bool* no_javascript_access) {
    REQUIRE_IO_THREAD();
    // Note: passing popupFeatures is not yet supported.
    const int popupFeaturesNotImpl = 0;
    return LifespanHandler_OnBeforePopup(browser, frame, target_url,
            target_frame_name, target_disposition, user_gesture,
            popupFeaturesNotImpl, windowInfo, client, settings,
            no_javascript_access);
}

void ClientHandler::OnAfterCreated(CefRefPtr browser) {
    REQUIRE_UI_THREAD();
#if defined(OS_WIN)
    // High DPI support.
    CefString auto_zooming = ApplicationSettings_GetString("auto_zooming");
    if (!auto_zooming.empty()) {
        LOG_DEBUG Continue(suggested_name, true);
    } else {
        DebugLog("Browser: Tried to download file, but downloads are disabled");
    }
}

void ClientHandler::OnDownloadUpdated(
        CefRefPtr browser,
        CefRefPtr download_item,
        CefRefPtr callback) {
    REQUIRE_UI_THREAD();
    if (download_item->IsComplete()) {
        std::string msg = "Browser: Download completed, saved to: ";
        msg.append(download_item->GetFullPath().ToString().c_str());
        DebugLog(msg.c_str());
    } else if (download_item->IsCanceled()) {
        DebugLog("Browser: Download was cancelled");
    }
}

// ----------------------------------------------------------------------------
// CefContextMenuHandler
// ----------------------------------------------------------------------------

#define _MENU_ID_DEVTOOLS                         MENU_ID_USER_FIRST + 1
#define _MENU_ID_RELOAD_PAGE                      MENU_ID_USER_FIRST + 2
#define _MENU_ID_OPEN_PAGE_IN_EXTERNAL_BROWSER    MENU_ID_USER_FIRST + 3
#define _MENU_ID_OPEN_FRAME_IN_EXTERNAL_BROWSER   MENU_ID_USER_FIRST + 4

void ClientHandler::OnBeforeContextMenu(CefRefPtr browser,
                                CefRefPtr frame,
                                CefRefPtr params,
                                CefRefPtr model) {
    bool enabled = ApplicationSettings_GetBoolFromDict(\
            "context_menu", "enabled");
    bool navigation = ApplicationSettings_GetBoolFromDict(\
            "context_menu", "navigation");
    bool print = ApplicationSettings_GetBoolFromDict(\
            "context_menu", "print");
    bool view_source = ApplicationSettings_GetBoolFromDict(\
            "context_menu", "view_source");
    bool external_browser = ApplicationSettings_GetBoolFromDict(\
            "context_menu", "external_browser");
    bool devtools = ApplicationSettings_GetBoolFromDict(\
            "context_menu", "devtools");

    if (!enabled) {
        model->Clear();
        return;
    }
    if (!navigation) {
        model->Remove(MENU_ID_BACK);
        model->Remove(MENU_ID_FORWARD);
        // Remove 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 (external_browser) {
            model->AddItem(_MENU_ID_OPEN_PAGE_IN_EXTERNAL_BROWSER,
                    "Open in external browser");
            if (params->GetFrameUrl().length()
                    && params->GetPageUrl() != params->GetFrameUrl()) {
                model->AddItem(_MENU_ID_OPEN_FRAME_IN_EXTERNAL_BROWSER,
                        "Open frame in external browser");
            }
        }
        if (navigation) {
            model->InsertItemAt(2, _MENU_ID_RELOAD_PAGE, "Reload");
        }
        if (devtools) {
            model->AddSeparator();
            model->AddItem(_MENU_ID_DEVTOOLS, "Developer Tools");
        }
    }
}

bool ClientHandler::OnContextMenuCommand(CefRefPtr browser,
                                CefRefPtr frame,
                                CefRefPtr params,
                                int command_id,
                                EventFlags event_flags) {
    if (command_id == _MENU_ID_OPEN_PAGE_IN_EXTERNAL_BROWSER) {
#if defined(OS_WIN)
        ShellExecuteA(0, "open", params->GetPageUrl().ToString().c_str(),
                0, 0, SW_SHOWNORMAL);
#elif defined(OS_LINUX)
        OpenInExternalBrowser(params->GetPageUrl().ToString());
#endif
        return true;
    } else if (command_id == _MENU_ID_OPEN_FRAME_IN_EXTERNAL_BROWSER) {
#if defined(OS_WIN)
        ShellExecuteA(0, "open", params->GetFrameUrl().ToString().c_str(),
                0, 0, SW_SHOWNORMAL);
#elif defined(OS_LINUX)
        OpenInExternalBrowser(params->GetFrameUrl().ToString());
#endif
        return true;
    } else if (command_id == _MENU_ID_RELOAD_PAGE) {
        browser->ReloadIgnoreCache();
        return true;
    } else if (command_id == _MENU_ID_DEVTOOLS) {
        PyBrowser_ShowDevTools(browser);
        return true;
    }
    return false;
}

void ClientHandler::OnContextMenuDismissed(CefRefPtr browser,
                                    CefRefPtr frame) {
}


Web Proxy Viewer  |  New URL  |  Original Page