Отправка информации из Chromium Embedded (Javascript) в содержащее приложение C++

После изучения примера Chromium Embedded Framework у меня возник вопрос. Мне нужно собственное взаимодействие со встроенной частью моего окна. Однако в примере с CEF все, что я видел, это то, что C++ отправляет сообщения в браузер, а не наоборот. Мне было интересно, есть ли способ отправить сообщение из JavaScript из С++, например, в виде функции.

То, что я ищу, это что-то вроде этого. У меня есть кнопка на моей веб-странице, которая при нажатии. Я хотел бы свернуть окно. Есть ли способ вызвать C++ из JavaScript в CEF?


person joshua-anderson    schedule 20.09.2013    source источник
comment
Взгляните на мои комментарии в этом сообщении (уже связанные)... stackoverflow.com/questions/18225261/ . Может быть, это полезно для вас...   -  person Moonwalker    schedule 14.08.2014


Ответы (3)


Самый простой способ: 1. В основном процессе (процессе пользовательского интерфейса) - вы можете создать собственный обработчик схемы (он также может быть привязан к протоколу http и отдельным обработчикам по домену). 2. Со стороны JS вы можете использовать XMLHttpRequest для вызова обработчика схемы. Это стандартный механизм IPC между JS‹>Main процессом.

Другой способ: используйте привязки V8, но в этом случае вам нужно будет сделать собственный IPC между рендерером и основным процессом. Или используйте встроенный IPC, но учтите, что он отправляет сообщения только асинхронно.

person Dmitry Azaraev    schedule 21.09.2013
comment
Спасибо! Знаете ли вы какие-либо примеры или руководства по встроенному IPC? Я мог бы найти примеры IPC в хроме, но понятия не имею, как это работает в CEF. Я предполагаю, что он поддерживает CEF типа 3, верно? - person joshua-anderson; 21.09.2013
comment
Хорошо, изучив варианты, регистрация обработчиков пользовательских схем выглядит хорошим выбором, однако, как и многие другие вещи в CEF, я не могу найти никаких примеров. groups.google.com/forum/#!msg/ cefglue/GmUdlO-qA-w/2Jcnxp75ynUJ — хороший пример, однако он написан на С# и использует несколько классов, недоступных в С++. Есть ли какой-нибудь сайт или пример, объясняющий процесс регистрации и чтения сообщений - person joshua-anderson; 21.09.2013
comment
Я не уверен, что правильно вас понял. Это все о CEF3. Встроенные IPC живут вокруг CefBrowser.SendProcessMessage, и вы можете обрабатывать их в CefClient.OnProcessMessageReceived и CefRenderProcessHandler.OnProcessMessageReceived. И C++, и Xilium.CefGlue содержат простые примеры, просто использование поиска. - person Dmitry Azaraev; 23.09.2013

Если кому-то нужен пример, вот один из способов, которым я это сделал:

  1. Определите пользовательский «протокол», который вы хотите использовать, вот пример в виде строки макроса #define PROTO_MYAPPCOMMAND «myapp://»

  2. В вашем пользовательском классе CefApp (тот, который наследуется от CefApp), также наследуйте от CefRenderProcessHandler.

  3. реализовать функцию OnBeforeNavigation():

    //declare (i.e. in header) 
    virtual bool OnBeforeNavigation(CefRefPtr<CefBrowser> browser, 
        CefRefPtr<CefFrame> frame, CefRefPtr<CefRequest> request, 
        NavigationType navigation_type, bool is_redirect)  OVERRIDE; 
    
    //implementation 
    bool CClientApp::OnBeforeNavigation(CefRefPtr<CefBrowser> browser, 
        CefRefPtr<CefFrame> frame, CefRefPtr<CefRequest> request, 
        NavigationType navigation_type, bool is_redirect)
    {
        CefString cefval = request->GetURL(); 
        CString csval = cefval.c_str(); 
    
        if (csval.Find(PROTO_MYAPPCOMMAND, 0) == 0)
        {
            //process the command here 
    
            //this is a command and not really intended for navigation 
            return true; 
        }
    
        return false; //true cancels navigation, false allows it 
    }
    

Вот пример добавления кнопки «выход» приложения:

в cpp

    #define STR_COMMANDAPPEXIT _T("command.appexit")
    bool CClientApp::OnBeforeNavigation(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefRequest> request, NavigationType navigation_type, bool is_redirect)
    {
        CefString cefval = request->GetURL(); 
        CString csval = cefval.c_str(); 

        if (csval.Find(PROTO_MYAPPCOMMAND, 0) == 0)
        {
            CString command = url; 
            command.Replace(PROTO_MYAPPCOMMAND, _T("")); 

            if (command.Find(STR_COMMANDAPPEXIT, 0) == 0) 
            {
                ::PostMessage(hwnd, WM_CLOSE, NULL, NULL); 
            }

            //this is a command and not really intended for navigation 
            return true; 
        }

        return false; //true cancels navigation, false allows it 
    }

также создал файл утилиты js для всех операций, чтобы упростить их вызов

    var MYHOST = MYHOST || {};
    /// Exit the Application (host app) 
    MYHOST.ExitApp = function() {
        window.location = 'myapp://command.appexit';
    };

на страницах js (т.е. при нажатии кнопки/div)

    <div class="exitbutton" onclick="MYHOST.ExitApp();">Exit</div>

Если вам нужно передать параметры, просто добавьте их в URL-адрес в js и проанализируйте строку в cpp, например:

    MYHOST.DoSomething = function() {
        window.location = 'myapp://command.dosomething?param1=' + value1 + "&param2=" + value2 + "&param3=" + value3;
    };

примечание: я упростил код, но, пожалуйста, добавьте проверки и т. д.

Надеюсь это поможет!

person mickeymicks    schedule 16.01.2014
comment
Спасибо! Это лучший пример того, как это сделать, который я когда-либо видел, хотя и не через обычный обработчик схемы URL. - person joshua-anderson; 16.01.2014
comment
Но это будет синхронно, остановит рендеринг вашего браузера до обработки события. - person Anil8753; 29.10.2014

Несерьезный способ сделать это, нужна одна строка кода:

Console.Log('. ...') с начальным символом ESC перед строкой/структурой данных, которую необходимо отправить в приложение. Просто реализуйте «OnConsoleMessage» и запустите точное задание в соответствии с ведущим или нет символом ESC.

PS: мне пришлось использовать это хитрое решение в 2015 году, поскольку выпуск DCEF3 содержал ошибки для использования обработчика схемы.

Для серьезной работы: зарегистрируйте обработчик пользовательской схемы.

person Gaëtan DELAVOIPIERE    schedule 21.07.2014
comment
Это одно из самых «хакерских» решений, которые я когда-либо видел в stackoverflow! - person Tim; 14.09.2015
comment
ахахахахах ахахахахах - person Researcher; 21.11.2017