Chromium Embedded Framework. Асинхронный AJAX

В прошлый раз я писал о том, как в CEF можно преопределить функцию OnBeforeResourceLoad для того чтобы сформировать собственный ответ на запрос отправленный со станицы. У этого метода есть один существенный недостаток - он синхронный и не вернет управление браузеру до тех пор пока вы не покинете функцию.

Для огранизации асинхронной обработки AJAX на C++ необходимо реализовать собственный класс унаследованный от CEFSchemeHandler

В проекте cefclient есть подробный пример того, как сделать собственный обработчик для схемы. Чтобы сделать его асинхронным надо провести небольшие изменения.

Приведу код класса для обработки схемы, разбавив его комментариями

  1. class ClientSchemeHandler : public CefSchemeHandler
  2. {
  3. public:
  4. ClientSchemeHandler() : offset_(0) {}
  5.  
  6. //Функция обработчик, которую мы хотим запустить в отдельном потоке
  7. UINT BeginThread(LPVOID lParam)
  8. {
  9. HANDLE h = CreateEvent(0, false, false, L"DUMMY_EVENT");
  10. //Сообщения мы никогда не дождемся, так что просто подождем 10 секунд
  11. WaitForSingleObject(h, 10000);
  12. //После того, как ответ сфорирован мы должны сказать об этом CEF
  13. callback_->HeadersAvailable();
  14. return 0;
  15. }
  16.  
  17. //Статический метод для использования в AfxBeginThread
  18. static UINT InitThread(LPVOID lParam)
  19. {
  20. ClientSchemeHandler *handler = static_cast<ClientSchemeHandler*>(lParam);
  21. handler->BeginThread(lParam);
  22. return 0;
  23. }
  24.  
  25. virtual bool ProcessRequest(CefRefPtr<CefRequest> request,
  26. CefRefPtr<CefSchemeHandlerCallback> callback)
  27. OVERRIDE
  28. {
  29. REQUIRE_IO_THREAD();
  30.  
  31. AutoLock lock_scope(this);
  32.  
  33. //Формируем ответ. На самом деле мы можем делать это в рамках запущенного потока
  34. mime_type_ = "text/html";
  35. data_ = "{\"content\": \"replaced by scheme handler\"}";
  36. //Сохраняем callback, который понадобится нам, чтобы уведомить CEF о готовности данных
  37. callback_ = callback;
  38. //Запускаем поток
  39. CWinThread *pThread = AfxBeginThread(ClientSchemeHandler::InitThread, static_cast<LPVOID>(this));
  40. return true;
  41. }
  42.  
  43. virtual void GetResponseHeaders(CefRefPtr<CefResponse> response,
  44. int64& response_length,
  45. CefString& redirectUrl) OVERRIDE
  46. {
  47. REQUIRE_IO_THREAD();
  48.  
  49. ...
  50. //Эта функция полностью соответствует примеру в cefclient
  51. //Она вызывается CEF после вызова метода CefSchemeHandlerCallback::HeadersAvailable()
  52. }
  53.  
  54. virtual void Cancel() OVERRIDE
  55. {
  56. REQUIRE_IO_THREAD();
  57. }
  58.  
  59. virtual bool ReadResponse(void* data_out,
  60. int bytes_to_read,
  61. int& bytes_read,
  62. CefRefPtr<CefSchemeHandlerCallback> callback)
  63. OVERRIDE
  64. {
  65. REQUIRE_IO_THREAD();
  66.  
  67. ...
  68. //Функция так же соответствует примеру
  69. //Будет вызываться многократно, до тех пор, пока из функции возвращается true
  70. }
  71.  
  72. private:
  73. std::string data_;
  74. std::string mime_type_;
  75. size_t offset_;
  76. CefRefPtr<CefSchemeHandlerCallback> callback_;
  77.  
  78. IMPLEMENT_REFCOUNTING(ClientSchemeHandler);
  79. IMPLEMENT_LOCKING(ClientSchemeHandler);
  80. };
  81.  

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

  1. class ClientSchemeHandlerFactory : public CefSchemeHandlerFactory
  2. {
  3. public:
  4. // Return a new scheme handler instance to handle the request.
  5. virtual CefRefPtr<CefSchemeHandler> Create(CefRefPtr<CefBrowser> browser,
  6. const CefString& scheme_name,
  7. CefRefPtr<CefRequest> request)
  8. OVERRIDE
  9. {
  10. REQUIRE_IO_THREAD();
  11. return new ClientSchemeHandler();
  12. }
  13.  
  14. IMPLEMENT_REFCOUNTING(ClientSchemeHandlerFactory);
  15. };
  16.  

и зарегестрировать её в качестве обработчика для схемы

  1.  
  2. void InitSchemeHandler()
  3. {
  4. CefRegisterSchemeHandlerFactory("http", "server", new ClientSchemeHandlerFactory());
  5. }
  6.  

В данном случае обработчик будет запущен для тех запросов, у которых в качестве схемы указан http, а host имеет значение server

Напомню, что все исходники можно найти на GitHub

Читайте в блоге

Chromium Embedded Framework. Взаимодействие с Javascript
Chromium Embedded Framework. Интеграция с MFC
Использование \K в регулярных выражениях. Игнорирование начальной части совпадения.

Комментарии:

Войдите на сайт, чтобы оставить комментарий