// Copyright (c) 2013 CEF Python, see the Authors file. // All rights reserved. Licensed under BSD 3-clause license. // Project website: https://github.com/cztomczak/cefpython #include "javascript_callback.h" #include #include #include "v8utils.h" #include "cefpython_app.h" #include "include/base/cef_logging.h" template inline std::string AnyToString(const T& value) { std::ostringstream oss; oss , CefRefPtr > > JavascriptCallbackMap; JavascriptCallbackMap g_jsCallbackMap; int g_jsCallbackMaxId = 0; CefString PutJavascriptCallback( CefRefPtr frame, CefRefPtr jsCallback) { // Returns a "####cefpython####" string followed by json encoded data. // {"what":"javascript-callback","callbackId":123, // "frameId":123,"functionName":"xx"} int callbackId = ++g_jsCallbackMaxId; int64 frameId = frame->GetIdentifier(); CefString functionName = jsCallback->GetFunctionName(); std::string strCallbackId = "####cefpython####"; strCallbackId.append("{"); // JSON format allows only for double quotes. strCallbackId.append("\"what\":\"javascript-callback\""); strCallbackId.append(",\"callbackId\":").append(AnyToString(callbackId)); strCallbackId.append(",\"frameId\":").append(AnyToString(frameId)); strCallbackId.append(",\"functionName\":\"").append(functionName) \ .append("\""); strCallbackId.append("}"); g_jsCallbackMap.insert(std::make_pair( callbackId, std::make_pair(frame, jsCallback))); return strCallbackId; } bool ExecuteJavascriptCallback(int callbackId, CefRefPtr args) { if (g_jsCallbackMap.empty()) { LOG(ERROR) frame = it->second.first; CefRefPtr callback = it->second.second; CefRefPtr context = frame->GetV8Context(); context->Enter(); CefV8ValueList v8Arguments = CefListValueToCefV8ValueList(args); CefRefPtr v8ReturnValue = callback->ExecuteFunction( NULL, v8Arguments); if (v8ReturnValue.get()) { context->Exit(); return true; } else { context->Exit(); LOG(ERROR) ExecuteFunction() failed"; return false; } } void RemoveJavascriptCallbacksForFrame(CefRefPtr frame) { if (g_jsCallbackMap.empty()) { return; } JavascriptCallbackMap::iterator it = g_jsCallbackMap.begin(); int64 frameId = frame->GetIdentifier(); while (it != g_jsCallbackMap.end()) { if (it->second.first->GetIdentifier() == frameId) { // Pass current iterator and increment it after passing // to the function, but before erase() is called, this // is important for it to work in a loop. You can't do this: // | if (..) erase(it); // | ++it; // This would cause an infinite loop. g_jsCallbackMap.erase(it++); LOG(INFO)