bool ClientApp::OnProcessMessageReceived( CefRefPtr<CefBrowser> browser, CefProcessId source_process, CefRefPtr<CefProcessMessage> message) { ASSERT(source_process == PID_BROWSER); bool handled = false; RenderDelegateSet::iterator it = render_delegates_.begin(); for (; it != render_delegates_.end() && !handled; ++it) { handled = (*it)->OnProcessMessageReceived(this, browser, source_process, message); } if (handled) return true; // Execute the registered JavaScript callback if any. if (!callback_map_.empty()) { CefString message_name = message->GetName(); CallbackMap::const_iterator it = callback_map_.find( std::make_pair(message_name.ToString(), browser->GetIdentifier())); if (it != callback_map_.end()) { // Keep a local reference to the objects. The callback may remove itself // from the callback map. CefRefPtr<CefV8Context> context = it->second.first; CefRefPtr<CefV8Value> callback = it->second.second; // Enter the context. context->Enter(); CefV8ValueList arguments; // First argument is the message name. arguments.push_back(CefV8Value::CreateString(message_name)); // Second argument is the list of message arguments. CefRefPtr<CefListValue> list = message->GetArgumentList(); CefRefPtr<CefV8Value> args = CefV8Value::CreateArray(static_cast<int>(list->GetSize())); SetList(list, args); arguments.push_back(args); // Execute the callback. CefRefPtr<CefV8Value> retval = callback->ExecuteFunction(NULL, arguments); if (retval.get()) { if (retval->IsBool()) handled = retval->GetBoolValue(); } // Exit the context. context->Exit(); } } return handled; }
// synchronously send a string from Node to browser, then return string result from browser to Node Handle<Value> Window::SendSync(const Arguments& args) { HandleScope scope; NativeWindow *window = ObjectWrap::Unwrap<NativeWindow> (args.This()); if (window->GetBrowser()) { // find browser's v8 context CefRefPtr<CefV8Context> context = window->GetBrowser()->GetMainFrame()->GetV8Context(); // ensure it's usable and enter if (context.get() && context->Enter()) { // try to get "appjs.onmessage" function CefRefPtr<CefV8Value> appjsObject = context->GetGlobal()->GetValue("appjs"); CefRefPtr<CefV8Value> callback = appjsObject->GetValue("onmessage"); if (callback.get()) { // convert Node V8 string to Cef V8 string CefV8ValueList argsOut; argsOut.push_back(CefV8Value::CreateString(V8StringToChar(args[0]->ToString()))); // execute window.appjs fuction, passing in the string, // then convert the return value from a CefValue to a Node V8 string Handle<String> ret = CefStringToV8(callback->ExecuteFunction(appjsObject, argsOut)->GetStringValue()); // exit browser v8 context, return string result to Node caller context->Exit(); return scope.Close(ret); } } } // likely error condition return scope.Close(Undefined()); }
void FUnrealCEFSubProcessRemoteScripting::CefToV8Arglist(CefRefPtr<CefListValue> List, CefV8ValueList& Values) { for (size_t i = 0; i < List->GetSize(); ++i) { Values.push_back(CefToV8(List, i)); } }
void CaffeineClientApp::NonBlockingSocketWrite(SOCKET s) { auto wb = wbMap.find(s); // s should exist auto& data_list = wb->second; // What if an error happens in the middle of draining the list while(data_list.size()) { auto data = data_list.front(); CaffeineSocketClient sc = scMap.find(s)->second; // Write the data and call the callback auto bytes_sent = sc.send(data.first.data(), data.first.size(), 0); if(bytes_sent>=0 && static_cast<int>(data.first.size())>bytes_sent) { data.first.erase(bytes_sent); } else { // Call the callback auto ctx = data.second.first; ctx->Enter(); CefRefPtr<CefV8Value> CallbackArg1; CefRefPtr<CefV8Value> CallbackArg2 = CefV8Value::CreateObject(NULL); if(bytes_sent == SOCKET_ERROR) { int error_code = WSAGetLastError(); if (WSAEWOULDBLOCK != error_code && 0 != error_code) { CallbackArg1 = CefV8Value::CreateBool(true); CallbackArg2->SetValue("status", CefV8Value::CreateString("error"), V8_PROPERTY_ATTRIBUTE_NONE); CallbackArg2->SetValue("errorCode", CefV8Value::CreateInt(::WSAGetLastError()), V8_PROPERTY_ATTRIBUTE_NONE); CallbackArg2->SetValue("handle", CefV8Value::CreateInt(s), V8_PROPERTY_ATTRIBUTE_NONE); } else { // The socket can't write anymore. ctx->Exit(); break; } } else { CallbackArg1 = CefV8Value::CreateNull(); CallbackArg2->SetValue("status", CefV8Value::CreateString("success"), V8_PROPERTY_ATTRIBUTE_NONE); } data_list.pop_front(); CefV8ValueList args; args.push_back(CallbackArg1); args.push_back(CallbackArg2); data.second.second->ExecuteFunction(NULL, args); ctx->Exit(); } } }
ChromiumDLL::JSObjHandle JavaScriptObject::executeFunction(ChromiumDLL::JavaScriptFunctionArgs *args) { if (!isFunction()) return GetJSFactory()->CreateException("Not a function!"); if (!args) return GetJSFactory()->CreateException("Args are null for function call"); JavaScriptContext* context = (JavaScriptContext*)args->context; JavaScriptObject* jso = (JavaScriptObject*)args->object.get(); CefV8ValueList argList; for (int x=0; x<args->argc; x++) { JavaScriptObject* jsoa = (JavaScriptObject*)args->argv[x].get(); if (jsoa) argList.push_back(jsoa->getCefV8()); else argList.push_back(NULL); } CefRefPtr<CefV8Value> retval; CefString exception; bool res = m_pObject->ExecuteFunctionWithContext(context->getCefV8(), jso?jso->getCefV8():NULL, argList, retval, exception); if (!res) { if (exception.c_str()) return GetJSFactory()->CreateException(exception.c_str()); return GetJSFactory()->CreateException("failed to run function"); } if (!retval) return NULL; return new JavaScriptObject(retval); }
void CallbackTask::Execute() { m_v8Ctx->Enter(); if (m_Func&&m_Func->IsFunction()) { CefRefPtr<CefV8Value> jsonRet; jsonRet=CefV8Value::CreateString(CefString(m_strJson)); CefV8ValueList retList; retList.push_back(jsonRet); m_Func->ExecuteFunction(m_Object,retList); } m_v8Ctx->Exit(); }
void CSJsSocket::OnRead(int fd, short ev) { char buffer[1024]; int len = Read(buffer, sizeof(buffer)); if (len == 0 || len == -1) { if (len == -1 && mErrorCallback) { CefV8ValueList args; CefRefPtr<CefV8Value> retval; CefRefPtr<CefV8Exception> exception; mErrorCallback->ExecuteFunctionWithContext(mErrorContext, NULL, args, retval, exception, false); } Close(); event_del(&mEventRead); return; } else { // we read something if (mReadCallback) { CefV8ValueList args; CefRefPtr<CefV8Value> retval; CefRefPtr<CefV8Exception> exception; std::string data(buffer, len); args.push_back(CefV8Value::CreateString(data)); mReadCallback->ExecuteFunctionWithContext(mReadContext, NULL, args, retval, exception, false); } } }
bool Application::OnProcessMessageReceived( CefRefPtr<CefBrowser> InBrowser, CefProcessId InSourceProcess, CefRefPtr<CefProcessMessage> InMessage) { ASSERT(InSourceProcess == PID_BROWSER); // call should have come from browser process. if (!Hooks.empty()) { CefString MessageName = InMessage->GetName(); JSHookMap::iterator it = Hooks.find(std::make_pair(MessageName, InBrowser->GetIdentifier())); if (it != Hooks.end()) { // invoke JS callback JSHook Hook(it->second); Hook.Context->Enter(); CefRefPtr<CefListValue> MessageArguments = InMessage->GetArgumentList(); const int NumMessageArguments = (int)MessageArguments->GetSize(); // convert message arguments CefV8ValueList Arguments; for (int i = 0; i < NumMessageArguments; ++i) { Arguments.push_back(ListItemToV8Value_RenderThread(MessageArguments, i)); } Hook.Function->ExecuteFunction(nullptr, Arguments); Hook.Context->Exit(); return true; } } return false; }
bool ClientApp::OnProcessMessageReceived( CefRefPtr<CefBrowser> browser, CefProcessId source_process, CefRefPtr<CefProcessMessage> message) { ASSERT(source_process == PID_BROWSER); bool handled = false; // Execute delegate callbacks. RenderDelegateSet::iterator it = render_delegates_.begin(); for (; it != render_delegates_.end() && !handled; ++it) { handled = (*it)->OnProcessMessageReceived(this, browser, source_process, message); } if (!handled) { if (message->GetName() == "invokeCallback") { // This is called by the appshell extension handler to invoke the asynchronous // callback function CefRefPtr<CefListValue> messageArgs = message->GetArgumentList(); int32 callbackId = messageArgs->GetInt(0); CefRefPtr<CefV8Context> context = callback_map_[callbackId].first; CefRefPtr<CefV8Value> callbackFunction = callback_map_[callbackId].second; CefV8ValueList arguments; context->Enter(); // Sanity check to make sure the context is still attched to a browser. // Async callbacks could be initiated after a browser instance has been deleted, // which can lead to bad things. If the browser instance has been deleted, don't // invoke this callback. if (context->GetBrowser()) { for (size_t i = 1; i < messageArgs->GetSize(); i++) { arguments.push_back(ListValueToV8Value(messageArgs, i)); } callbackFunction->ExecuteFunction(NULL, arguments); } context->Exit(); callback_map_.erase(callbackId); } else if (message->GetName() == "executeCommand") { // This is called by the browser process to execute a command via JavaScript // // The first argument is the command name. This is required. // The second argument is a message id. This is optional. If set, a response // message will be sent back to the browser process. CefRefPtr<CefListValue> messageArgs = message->GetArgumentList(); CefString commandName = messageArgs->GetString(0); int messageId = messageArgs->GetSize() > 1 ? messageArgs->GetInt(1) : -1; bool handled = false; StContextScope ctx(browser->GetMainFrame()->GetV8Context()); CefRefPtr<CefV8Value> global = ctx.GetContext()->GetGlobal(); if (global->HasValue("brackets")) { CefRefPtr<CefV8Value> brackets = global->GetValue("brackets"); if (brackets->HasValue("shellAPI")) { CefRefPtr<CefV8Value> shellAPI = brackets->GetValue("shellAPI"); if (shellAPI->HasValue("executeCommand")) { CefRefPtr<CefV8Value> executeCommand = shellAPI->GetValue("executeCommand"); if (executeCommand->IsFunction()) { CefRefPtr<CefV8Value> retval; CefV8ValueList args; args.push_back(CefV8Value::CreateString(commandName)); retval = executeCommand->ExecuteFunction(global, args); if (retval) { handled = retval->GetBoolValue(); } } } } } // Return a message saying whether or not the command was handled if (messageId != -1) { CefRefPtr<CefProcessMessage> result = CefProcessMessage::Create("executeCommandCallback"); result->GetArgumentList()->SetInt(0, messageId); result->GetArgumentList()->SetBool(1, handled); browser->SendProcessMessage(PID_BROWSER, result); } } } return handled; }
JNIEXPORT jboolean JNICALL Java_org_limewire_cef_CefV8Value_1N_N_1ExecuteFunction (JNIEnv *env, jobject obj, jobject params) { CefRefPtr<CefV8Value> value( (CefV8Value*)GetCefBaseFromJNIObject(env, obj)); if(!value.get()) return JNI_FALSE; jclass params_cls = env->GetObjectClass(params); // Retrieve the object member. jobject object_obj = NULL; { jfieldID fieldID = env->GetFieldID(params_cls, "object", "Lorg/limewire/cef/CefV8Value;"); if(fieldID != 0) object_obj = env->GetObjectField(params, fieldID); else env->ExceptionClear(); } if(!object_obj) return JNI_FALSE; CefRefPtr<CefV8Value> object( (CefV8Value*)GetCefBaseFromJNIObject(env, object_obj)); if(!object.get()) return JNI_FALSE; // Retrieve the argument member. jobjectArray arg_arr = NULL; { jfieldID fieldID = env->GetFieldID(params_cls, "owner", "[Lorg/limewire/cef/CefV8Value;"); if(fieldID != 0) arg_arr = (jobjectArray)env->GetObjectField(params, fieldID); else env->ExceptionClear(); } if(!arg_arr) return JNI_FALSE; CefV8ValueList argList; int len = env->GetArrayLength(arg_arr); for(int i = 0; i < len; i++) { jobject cobj = env->GetObjectArrayElement(arg_arr, i); if(!cobj) continue; CefRefPtr<CefV8Value> argobj( (CefV8Value*)GetCefBaseFromJNIObject(env, cobj)); if(!argobj.get()) continue; argList.push_back(argobj); } CefString exception; // Execute the function. CefRefPtr<CefV8Value> retVal = value->ExecuteFunction(object, argList); // Set the return value member. { jfieldID fieldID = env->GetFieldID(params_cls, "retval", "Lorg/limewire/cef/CefV8Value;"); if(fieldID != 0) { jobject robj = NULL; if(retVal.get()) { robj = CreateJNIObject(env, "org/limewire/cef/CefV8Value_N", retVal.get(), (long)retVal.get()); } env->SetObjectField(params, fieldID, robj); } else { env->ExceptionClear(); } } // Set the exception member. { jfieldID fieldID = env->GetFieldID(params_cls, "exception", "Ljava/lang/String;"); if(fieldID != 0) { env->SetObjectField(params, fieldID, CreateJNIString(env, exception)); } else { env->ExceptionClear(); } } return JNI_TRUE; }
bool CaffeineClientApp::InvokeSocketMethod(SOCKET s, CefString state, int32 error_code) { bool retval = false; auto i = sMap.find(s); if(i!=sMap.end()) { // First, try looking up the callback in the socket callback map. auto cb = i->second.find(state); if(cb!=i->second.end()) { auto ctx = (cb->second).first; ctx->Enter(); CefV8ValueList args; CefRefPtr<CefV8Value> CallbackArg = CefV8Value::CreateObject(NULL); CallbackArg->SetValue("handle", CefV8Value::CreateInt(s), V8_PROPERTY_ATTRIBUTE_NONE); // If it's an error, it's handled a little differently. if (state == "error") { CallbackArg->SetValue("errorCode", CefV8Value::CreateInt(error_code), V8_PROPERTY_ATTRIBUTE_NONE); } // The other cases have two arguments. else if (state != "close") // "read" or "connect" cases { args.push_back(CefV8Value::CreateNull()); CallbackArg->SetValue("status", CefV8Value::CreateString("success"), V8_PROPERTY_ATTRIBUTE_NONE); if (state == "read") { CaffeineSocketClient sc = scMap.find(s)->second; vector<char> buffer(4096); int bytes_recvd = sc.recv(&buffer.front(), buffer.size()-1, 0); // TODO: Handle real errors on a read. if(bytes_recvd<=0 /*&& (WSAEWOULDBLOCK == error_code || 0 == error_code)*/) { bytes_recvd = 0; NonBlockingSocketWrite(s); ctx->Exit(); return true; } buffer[bytes_recvd] = 0; CallbackArg->SetValue("nBytes", CefV8Value::CreateInt(bytes_recvd), V8_PROPERTY_ATTRIBUTE_NONE); CallbackArg->SetValue("data", CefV8Value::CreateString(buffer.data()), V8_PROPERTY_ATTRIBUTE_NONE); } } args.push_back(CallbackArg); (cb->second).second->ExecuteFunction(NULL, args); ctx->Exit(); // TODO: We should actually call read to make sure we've read all of the data before // TODO: cleaning up. Probably should do the same thing for the error case too. if (state == "error" || state == "close") { closesocket(s); // Clean up the sockets maps RemoveSocketCallback(s); wbMap.erase(s); scMap.erase(s); } retval = true; } // Otherwise, if we can write handle it. else if (state == "write") { NonBlockingSocketWrite(s); retval = true; } } return retval; }