标题:CEF3中如何截获XMLHttpRequest(HDR)请求和返回数据!
Title: How to intercept XMLHttpRequest in CEF3!
阅读对象:主要是给自己看的,免得以后忘记。
环境:[1]VS2013SP3 [2]cef_binary_3.1916.1804_windows32
第一次更新日期:2014-11-4
最近更新日期:2014-11-4
正文:
总共分为四步步骤:
第一步:
- extern UINT WM_XMLHttpRequest;
- CefRefPtr<CefResourceHandler> ClientHandler::GetResourceHandler(CefRefPtr<CefBrowser> browser,
- CefRefPtr<CefFrame> frame, CefRefPtr<CefRequest> request)
- {
- //http://www.magpcss.org/ceforum/viewtopic.php?f=6&t=10794
- if (request->GetResourceType() == RT_XHR)
- {
- //Second?
- CefRefPtr<KagulaResourceHandler> resHandler = new KagulaResourceHandler();
- resHandler->_browser = browser;
- resHandler->_frame = frame;
- resHandler->_clientHandler = this;
- return resHandler;
- }
- return NULL;
- }
第二步:
KagulaResourceHandler.h清单
- #pragma once
- #include <include/cef_app.h>
- #include <include/cef_urlrequest.h>
- class ClientHandler;
- class KagulaUrlRequestClient;
- class KagulaResourceHandler : public CefResourceHandler
- {
- public:
- KagulaResourceHandler() :
- _offset(0)
- {}
- virtual bool ProcessRequest(CefRefPtr<CefRequest> request,
- CefRefPtr<CefCallback> callback)
- OVERRIDE;
- virtual void GetResponseHeaders(CefRefPtr<CefResponse> response,
- int64& response_length,
- CefString& redirectUrl) OVERRIDE;
- virtual void Cancel() OVERRIDE;
- virtual bool ReadResponse(void* data_out, int bytes_to_read,
- int& bytes_read,
- CefRefPtr<CefCallback> callback)
- OVERRIDE;
- public:
- CefRefPtr<ClientHandler> _clientHandler;
- CefRefPtr<CefBrowser> _browser;
- CefRefPtr<CefFrame> _frame;
- CefRefPtr<CefCallback> _responseHeadersReadyCallback;
- CefRefPtr<KagulaUrlRequestClient> _webRequestClient;
- CefRefPtr<CefURLRequest> _webRequest;
- std::string _content;
- private:
- size_t _offset;
- IMPLEMENT_REFCOUNTING(KagulaResourceHandler);
- IMPLEMENT_LOCKING(KagulaResourceHandler);
- };
KagulaResourceHandler.cpp清单
- #include <assert.h>
- #include "KagulaResourceHandler.h"
- #include "client_handler.h"
- #include "KagulaUrlRequestClient.h"
- bool KagulaResourceHandler::ProcessRequest(CefRefPtr<CefRequest> request,
- CefRefPtr<CefCallback> callback)
- {
- //1. Start the request using WebRequest
- //2. Return True to handle the request
- //3. Once response headers are ready call
- // callback.Continue()
- _responseHeadersReadyCallback = callback;
- _webRequestClient = new KagulaUrlRequestClient(_frame);
- _webRequestClient->_resourceHandler = this;
- request->SetFlags(UR_FLAG_ALLOW_CACHED_CREDENTIALS | UR_FLAG_ALLOW_COOKIES);
- //To skip cache :
- //| request.SetFlags(cefpython.Request.Flags["SkipCache"])
- //Must keep a strong reference to the WebRequest() object.
- _webRequest = CefURLRequest::Create(request, _webRequestClient.get());
- return true;
- }
- void KagulaResourceHandler::GetResponseHeaders(CefRefPtr<CefResponse> response,
- int64& response_length, CefString& redirectUrl)
- {
- assert(CefCurrentlyOn(TID_IO));
- //if (this->mimeType)
- //{
- // response->SetMimeType(CefString(this->mimeType));
- // response->SetStatus(200);
- //}
- //else
- //{
- // response->SetStatus(500);
- //}
- CefRefPtr<CefResponse> webResponse = _webRequestClient->_response;
- if (webResponse!=nullptr)
- {
- CefResponse::HeaderMap headerMap;
- webResponse->GetHeaderMap(headerMap);
- response->SetHeaderMap(headerMap);
- response->SetStatus(webResponse->GetStatus());
- response->SetStatusText(webResponse->GetStatusText());
- CefString cefstr = webResponse->GetMimeType();
- if (!cefstr.empty())
- {
- response->SetMimeType(webResponse->GetMimeType());
- }
- }
- response_length = _content.size();
- _offset = 0;
- }
- void KagulaResourceHandler::Cancel()
- {
- }
- bool KagulaResourceHandler::ReadResponse(void* data_out, int bytes_to_read,
- int& bytes_read, CefRefPtr<CefCallback> callback)
- {
- //here fill what response data will be return!
- size_t size = _content.size();
- if (_offset < size) {
- int transfer_size = min(bytes_to_read, static_cast<int>(size - _offset));
- memcpy(data_out, _content.c_str() + _offset, transfer_size);
- _offset += transfer_size;
- bytes_read = transfer_size;//output
- char *pDataOut = (char*)data_out;
- return true;
- }
- return false;
- }
KagulaUrlRequestClient.h清单
- #pragma once
- #include <include/cef_app.h>
- #include <include/cef_urlrequest.h>
- #include "KagulaResourceHandler.h"
- #include <string>
- #include <map>
- class KagulaUrlRequestClient : public CefURLRequestClient
- {
- public:
- KagulaUrlRequestClient(CefRefPtr<CefFrame> _frame):_dataLength(0)
- {}
- // CefURLRequestClient methods
- virtual void OnRequestComplete(CefRefPtr<CefURLRequest> request) OVERRIDE;
- virtual void OnUploadProgress(CefRefPtr<CefURLRequest> request, uint64 current, uint64 total) OVERRIDE;
- virtual void OnDownloadData(CefRefPtr<CefURLRequest> request, const void* data, size_t data_length) OVERRIDE;
- virtual void OnDownloadProgress(CefRefPtr<CefURLRequest> request, uint64 current, uint64 total) OVERRIDE;
- virtual bool GetAuthCredentials(bool isProxy, const CefString& host, int port, const CefString& realm, const CefString& scheme, CefRefPtr<CefAuthCallback> callback) OVERRIDE;
- public:
- CefRefPtr<CefResponse> _response;
- CefRefPtr<KagulaResourceHandler> _resourceHandler;
- std::string _data;
- size_t _dataLength;
- private:
- IMPLEMENT_REFCOUNTING(KagulaUrlRequestClient);
- };
KagulaUrlRequestClient.cpp清单
- #include "KagulaUrlRequestClient.h"
- #include "client_handler.h"
- void KagulaUrlRequestClient::OnRequestComplete(CefRefPtr<CefURLRequest> request)
- {
- std::string statusText = "Unknown";
- std::map<int,std::string> mqpReqStatus;
- mqpReqStatus[0]="Unknown";
- mqpReqStatus[1]="Success";
- mqpReqStatus[2]="Pending";
- mqpReqStatus[3]="Canceled";
- mqpReqStatus[4]="Failed";
- if (mqpReqStatus.find(request->GetRequestStatus()) != mqpReqStatus.end())
- statusText = mqpReqStatus[request->GetRequestStatus()];
- _response = request->GetResponse();
- _data = _resourceHandler->_clientHandler->_OnResourceResponse(
- _resourceHandler->_browser,
- _resourceHandler->_frame,
- request->GetRequest(),
- request->GetRequestStatus(),
- request->GetRequestError(),
- request->GetResponse(),
- _data);
- _dataLength = _data.length();
- //ResourceHandler.GetResponseHeaders() will get called
- //after _responseHeadersReadyCallback.Continue() is called.
- _resourceHandler->_content = _data;
- _resourceHandler->_responseHeadersReadyCallback->Continue();
- }
- void KagulaUrlRequestClient::OnUploadProgress(CefRefPtr<CefURLRequest> request, uint64 current, uint64 total)
- {
- }
- void KagulaUrlRequestClient::OnDownloadData(CefRefPtr<CefURLRequest> request, const void* data, size_t data_length)
- {
- char* buf = new char[data_length + 1];
- if (buf!=nullptr)
- {
- memset(buf, 0, data_length + 1);
- memcpy(buf, data, data_length);
- _data += buf;
- delete buf;
- }
- }
- void KagulaUrlRequestClient::OnDownloadProgress(CefRefPtr<CefURLRequest> request, uint64 current, uint64 total)
- {
- }
- bool KagulaUrlRequestClient::GetAuthCredentials(bool isProxy, const CefString& host, int port, const CefString& realm, const CefString& scheme, CefRefPtr<CefAuthCallback> callback)
- {
- return true;
- }
第三步:
- std::string ClientHandler::_OnResourceResponse(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefRequest> request,
- CefURLRequest::Status status, CefURLRequest::ErrorCode errorCode, CefRefPtr<CefResponse> response, std::string data)
- {
- std::string _data = data;
- std::string strPostData;
- std::wstring wsR = L"url=>";
- wsR.append(frame->GetURL().ToWString());
- wsR.append(L"post data=>");
- {
- CefRefPtr<CefPostData> postData = request->GetPostData();
- if (postData != NULL) {
- CefPostData::ElementVector elements;
- postData->GetElements(elements);
- if (elements.size() > 0) {
- std::wstring queryString;
- // it looks like the whole query string is in this first post data element?
- CefRefPtr<CefPostDataElement> query = elements[0];
- if (query->GetType() == PDE_TYPE_BYTES || query->GetType() == PDE_TYPE_FILE) {
- const unsigned int buffSize = query->GetBytesCount() >= 1024 ? 1024 : query->GetBytesCount() + 1;
- char *buff = new char[buffSize];
- if (buff!=nullptr)
- {
- //Get Post Data
- memset(buff, 0, buffSize);
- query->GetBytes(query->GetBytesCount() >= buffSize ? buffSize-1 : query->GetBytesCount(), buff);
- strPostData = buff;
- wsR.append(kagula::s2ws_FromUTF8(strPostData));
- delete[] buff;
- }
- }
- }
- }
- }
- wsR.append(L"content=>");
- wsR.append(kagula::s2ws_FromUTF8(data));
- LOG_TRACE(wsR.c_str());
- //
- CefString url = frame->GetURL();
- //send to my main window!
- std::vector<std::string> vecStr;
- vecStr.push_back(url.ToString());
- vecStr.push_back(strPostData);
- vecStr.push_back(data);
- CIPCData::SetVecStr(vecStr);
- HWND hwnd = (HWND)(CIPCData::GetMainHWND());
- SendMessage(hwnd, WM_XMLHttpRequest, NULL, NULL);
- return _data;
- }
第四步:
- LRESULT Ccat8637_BrandDlg::OnXMLHttpRequest(WPARAM wParam, LPARAM lParam)
- {
- std::vector<std::string> vecS;
- CIPCData::GetVecStr(vecS);
- if (vecS.size() == 3)
- {
- #ifdef _DEBUG
- std::wstring strMsg = L"OnXMLHttpRequest=>";
- strMsg.append(kagula::s2ws_FromUTF8(vecS[2]));
- LOG_TRACE(strMsg);
- #endif
- }
- return S_OK;
- }