CEF и вызов js функций из C++
От: RonWilson Россия  
Дата: 03.04.18 12:25
Оценка:
Привет всем,

погугли сабж, но внятных примеров как вызвать уже существующую в загруженной странице, передать параметры и получить результат. Везде какие-то примеры с ExecuteJavascript, но это явно не то. Кто-нибудь сталкивался?
Re: CEF и вызов js функций из C++
От: Temnikov Россия  
Дата: 03.04.18 12:32
Оценка:
RW>погугли сабж, но внятных примеров как вызвать уже существующую в загруженной странице, передать параметры и получить результат. Везде какие-то примеры с ExecuteJavascript, но это явно не то. Кто-нибудь сталкивался?
Условно, страница должна открываться в любом браузере или в твоем приложении? Если второе, то через IWebBrowser2 компонент мы такое делали.
Re[2]: CEF и вызов js функций из C++
От: RonWilson Россия  
Дата: 03.04.18 12:35
Оценка:
Здравствуйте, Temnikov, Вы писали:

RW>>погугли сабж, но внятных примеров как вызвать уже существующую в загруженной странице, передать параметры и получить результат. Везде какие-то примеры с ExecuteJavascript, но это явно не то. Кто-нибудь сталкивался?

T>Условно, страница должна открываться в любом браузере или в твоем приложении? Если второе, то через IWebBrowser2 компонент мы такое делали.

интересует только CEF, для IWebBrowser2 давно как-то делал — к счасть, отказались от IE.
Re[3]: CEF и вызов js функций из C++
От: Temnikov Россия  
Дата: 03.04.18 12:43
Оценка:
На вскидку SignalR из готового. Или можно просто на веб-сокетах сделать обмен, а там уже полет фантазии ничем не ограничен.
Re[4]: CEF и вызов js функций из C++
От: RonWilson Россия  
Дата: 03.04.18 12:45
Оценка:
Здравствуйте, Temnikov, Вы писали:

T>На вскидку SignalR из готового. Или можно просто на веб-сокетах сделать обмен, а там уже полет фантазии ничем не ограничен.


какие, извиняюсь, нафиг веб сокеты? мне просто нужно вызвать из C++ существующие функции js, это отлично делает ExecuteJavascript, но получить результат непонятно как и форматировать строчку с аргументами для вызова js функции не хочу
Re[5]: CEF и вызов js функций из C++
От: Temnikov Россия  
Дата: 03.04.18 12:49
Оценка:
RW>какие, извиняюсь, нафиг веб сокеты? мне просто нужно вызвать из C++ существующие функции js, это отлично делает ExecuteJavascript, но получить результат непонятно как и форматировать строчку с аргументами для вызова js функции не хочу

RW>>как вызвать уже существующую в загруженной странице

Распарсил как, то что у тебя есть страница и тебе надо вызвать C++ функцию из какой-нибудь библиотеки.
Re[6]: CEF и вызов js функций из C++
От: RonWilson Россия  
Дата: 03.04.18 12:50
Оценка:
Здравствуйте, Temnikov, Вы писали:

RW>>какие, извиняюсь, нафиг веб сокеты? мне просто нужно вызвать из C++ существующие функции js, это отлично делает ExecuteJavascript, но получить результат непонятно как и форматировать строчку с аргументами для вызова js функции не хочу


T>Распарсил как, то что у тебя есть страница и тебе надо вызвать C++ функцию из какой-нибудь библиотеки.


да вроде так написал
Re: CEF и вызов js функций из C++
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 03.04.18 13:15
Оценка:
Здравствуйте, RonWilson, Вы писали:

RW>Привет всем,


RW>погугли сабж, но внятных примеров как вызвать уже существующую в загруженной странице, передать параметры и получить результат. Везде какие-то примеры с ExecuteJavascript, но это явно не то. Кто-нибудь сталкивался?


https://bitbucket.org/chromiumembedded/cef/wiki/JavaScriptIntegration.md

Посмотри исходники к статьям
CEF, ES6, Angular 2, TypeScript использование классов .Net Core. Создание кроссплатформенного GUI для .Net с помощью CEF

CEF, Angular 2 использование событий классов .Net Core


Там используются асинхронные вызовы и подписка на события.

Посмотри SetCallBacks ("RegisterCallBacks"), AsyncCalBack

То есть ты должен зарегистрировать функцию window.RegisterCallBacks(AsyncCallBack,EventCall);

А затем её вызывать

например

function EventCall(EventKey,result)
{
alert("EventKey="+EventKey+" result="+result);

}

window.RegisterCallBacks(AsyncCallBack,EventCall);


RegisterCallBacks это твоя зарегистрированнная функция в CEF. Передаешь ссылки на методы. В CEF запоминаешь, а затем вызываешь по надобности
и солнце б утром не вставало, когда бы не было меня
Отредактировано 03.04.2018 16:48 Serginio1 . Предыдущая версия . Еще …
Отредактировано 03.04.2018 13:28 Serginio1 . Предыдущая версия .
Отредактировано 03.04.2018 13:23 Serginio1 . Предыдущая версия .
Отредактировано 03.04.2018 13:18 Serginio1 . Предыдущая версия .
Re: CEF и вызов js функций из C++
От: c-smile Канада http://terrainformatica.com
Дата: 03.04.18 18:07
Оценка:
Здравствуйте, RonWilson, Вы писали:

RW>и получить результат


ExecuteFunctionWithContext ?
Re[5]: CEF и вызов js функций из C++
От: goto Россия  
Дата: 05.04.18 02:29
Оценка:
Здравствуйте, RonWilson, Вы писали:

RW>какие, извиняюсь, нафиг веб сокеты? мне просто нужно вызвать из C++ существующие функции js, это отлично делает ExecuteJavascript, но получить результат непонятно как и форматировать строчку с аргументами для вызова js функции не хочу


Твой код и скрипт исполняются, вообще говоря, в разных процессах. Если нужно решить побыстрее, можешь попробовать поместить параметры в глобальный объект (window.MyObject), вызвать ф-ю, которая поместит возвращаемое значение примерно туда же. Немного коряво, конечно. Я сам не пробовал.
Re[6]: CEF и вызов js функций из C++
От: RonWilson Россия  
Дата: 05.04.18 08:03
Оценка:
Здравствуйте, goto, Вы писали:

G>Твой код и скрипт исполняются, вообще говоря, в разных процессах. Если нужно решить побыстрее, можешь попробовать поместить параметры в глобальный объект (window.MyObject), вызвать ф-ю, которая поместит возвращаемое значение примерно туда же. Немного коряво, конечно. Я сам не пробовал.


так-то работает:

void CefViewApp::OnContextCreated(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefV8Context> context)
{
    CefRefPtr<CefV8Value> object = context->GetGlobal();

    CefRefPtr<CefV8Value> str = CefV8Value::CreateString("HehHHH");
    object->SetValue("testVal", str, V8_PROPERTY_ATTRIBUTE_NONE);
}


function test() {
  alert(window.testVal);
}


CefRefPtr<CefFrame> frame = cefHandler->GetBrowser()->GetMainFrame();

if( !frame.get() )
    return (LRESULT)FALSE;

frame->ExecuteJavaScript(CefString("test();"), frame->GetURL(), 0);


но, насколько я понял, ExecuteJavaScript тоже асинхронный, как же тогда получить результат сразу после ExecuteJavaScript? в CefFrame вызов GetV8Context возвращает ноль, оно и понятно — доступно только при рендере, а мне нужно в произвольный момент

P.S. и почему такой изврат с доступом к DOM, как обратится к DOMDocument тоже из произвольного места?
Re[7]: CEF и вызов js функций из C++
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 05.04.18 09:05
Оценка: 6 (1)
Здравствуйте, RonWilson, Вы писали:

Попробуй использовать
ExecuteFunctionWithContext


CefV8ValueList args;
CefRefPtr<CefV8Value> retval;
CefRefPtr<CefV8Exception> exception;
if (callback_func_->ExecuteFunctionWithContext(callback_context_, NULL, args, retval, exception, false)) {
  if (exception.get()) {
    // Execution threw an exception.
  } else {
    // Execution succeeded.
  }
}


retval и есть твоя функция.
Можешь зарегистрировать универсальную функцию которая будет принимать название метода, параметры, а внутри вызывать eval и возвращать результат
и солнце б утром не вставало, когда бы не было меня
Re[8]: CEF и вызов js функций из C++
От: RonWilson Россия  
Дата: 05.04.18 09:35
Оценка:
Здравствуйте, Serginio1, Вы писали:

S> Можешь зарегистрировать универсальную функцию которая будет принимать название метода, параметры, а внутри вызывать eval и возвращать результат


к сожалению — получилось, остался только вопрос с тем, где лучше хранить полученные funct и ctx, чтобы можно было использовать в нужный момент. Можно ли в реализации своего CefApp как поля класса?:

bool GeneralCefV8Handler::Execute(const CefString& name, CefRefPtr<CefV8Value> object, const CefV8ValueList& arguments, CefRefPtr<CefV8Value>& retval, CefString& exception)
{
    if(name == NATIVECALLBACKREGISTER)
    {
        if (arguments.size() == 1 && arguments[0]->IsFunction()) {
            CefRefPtr<CefV8Value> funct = arguments[0];
            CefRefPtr<CefV8Context> ctx  = CefV8Context::GetCurrentContext();

            // test
            CefV8ValueList args;
            CefRefPtr<CefV8Value> retval = funct->ExecuteFunctionWithContext(ctx, 0, args);

            return true;
        }
    }
    // Function does not exist.
    return false;
}
Re[9]: CEF и вызов js функций из C++
От: RonWilson Россия  
Дата: 05.04.18 13:45
Оценка:
разобрался, то, что мне нужно, а именно — синхронный вызов js делается так — вдруг кому пригодится:

тут идет вызов js функции function SetContent(content) { ... return true; }, прибиндинной в CefV8Handler::Execute

void SignalEvent(CefRefPtr<CefWaitableEvent> event) 
{
    event->Signal();
}

void RunOnThread(CefThreadId cefTID, const base::Callback<void(void)>& functImpl, CefRefPtr<CefWaitableEvent> event) 
{
    if (!CefCurrentlyOn(cefTID)) {
        CefPostTask(cefTID,
            base::Bind(RunOnThread, cefTID, functImpl, event));
        return;
    }

    functImpl.Run();
    SignalEvent(event);
}

static void OnLoadHTMLData_Worker(const char * content, bool * retVal)
{
    REQUIRE_RENDERER_THREAD();

    if(!content || !retVal)
        return;

    *retVal= false;

    CefRefPtr<CefV8Value> setContent = g_cefApp->Get_js_SetContent();
    CefRefPtr<CefV8Context> setContent_Ctx  = g_cefApp->Get_js_SetContent_Ctx();

    CefV8ValueList args;

    args.push_back(CefV8Value::CreateString(content));
    CefRefPtr<CefV8Value> retval = setContent->ExecuteFunctionWithContext(setContent_Ctx, 0, args);

    if(retval.get() && retval->IsBool())
        *retVal = retval->GetBoolValue();
}

LRESULT CefViewJSEditorCtrl::OnLoadHTMLData(HWND hWindow, UINT /*message*/, WPARAM /*wParam*/, LPARAM lParam)
{
    if( !lParam || !cefHandler.get() || !cefHandler->GetBrowser().get() )
        return (LRESULT)FALSE;

    CefRefPtr<CefFrame> frame = cefHandler->GetBrowser()->GetMainFrame();

    if( !frame.get() )
        return (LRESULT)FALSE;

    bool retVal = false;
    CefRefPtr<CefWaitableEvent> event = CefWaitableEvent::CreateWaitableEvent(true, false);
    RunOnThread(TID_RENDERER, base::Bind(OnLoadHTMLData_Worker, (const char *)lParam, &retVal), event);
    event->Wait();

    return retVal ? (LRESULT)TRUE : (LRESULT)FALSE;
}
Re[7]: CEF и вызов js функций из C++
От: goto Россия  
Дата: 05.04.18 15:22
Оценка:
Здравствуйте, RonWilson, Вы писали:

RW>но, насколько я понял, ExecuteJavaScript тоже асинхронный, как же тогда получить результат сразу после ExecuteJavaScript? в CefFrame вызов GetV8Context возвращает ноль, оно и понятно — доступно только при рендере, а мне нужно в произвольный момент


Да, мысль насчет асинхронности у меня как раз мелькнула накануне. Можно отдавать результат js ф-ии, вызывая из нее нативный коллбэк. Это тоже похоже на извращение для большинства ситуаций. Лучше, конечно, посмотреть ExecuteFunctionWithContext, как посоветовали c-smile и Serginio1.

У меня когда-то был небольшой стремительный проект с использованием CEF. Помню, упростило ситуацию переключение в режим single_process и отключение песочницы. Но детали, увы, не помню, там был перманентный цейтнот и безумие.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.