cef3框架以zip格式加载资源

构建windows桌面应用程序,使用cef3框架,其中实现加载本地资源方式为zip压缩包的形式(同样的方式也可以做成动态库形式,或者直接以win32资源加载的形式)。

具体实现如下:

实现自己的provider

class PcmBinaryResourceProvider : public CefResourceManager::Provider {

public:

explicit PcmBinaryResourceProvider(const std::string& url_path)

: url_path_(url_path) {

DCHECK(!url_path.empty());

}

 

bool OnRequest(scoped_refptr request) OVERRIDE

{

CEF_REQUIRE_IO_THREAD();

 

const std::string& url = request->url();

if (url.find(url_path_) != 0L) {

// Not handled by this provider.

return false;

}

 

CefRefPtr handler;

 

const std::string& relative_path = url.substr(url_path_.length());

if (!relative_path.empty()) {

CefRefPtr stream =

GetBinaryResourceReader(relative_path.data());

if (stream.get()) {

handler = new CefStreamResourceHandler(

request->mime_type_resolver().Run(url),

stream);

}

}

 

request->Continue(handler);

return true;

}

 

private:

std::string url_path_;

 

DISALLOW_COPY_AND_ASSIGN(PcmBinaryResourceProvider);

};

 

 

CefResourceManager::Provider* CreatePcmBinaryResourceProvider(

const std::string& url_path)

{

return new PcmBinaryResourceProvider(url_path);

}

 

最后在test_runner.cc中添加(标红字段):

void SetupResourceManager(CefRefPtr resource_manager) {

if (!CefCurrentlyOn(TID_IO)) {

// Execute on the browser IO thread.

CefPostTask(TID_IO, base::Bind(SetupResourceManager, resource_manager));

return;

}

 

const std::string& test_origin = kTestOrigin;

 

// Add the URL filter.

resource_manager->SetUrlFilter(base::Bind(RequestUrlFilter));

 

// Add provider for resource dumps.

resource_manager->AddProvider(

new RequestDumpResourceProvider(test_origin + "request.html"), 0,

std::string());

 

// Add provider for bundled resource files.

#if defined(OS_WIN)

// Read resources from the binary.

//resource_manager->AddProvider(

// CreateBinaryResourceProvider(test_origin, std::string()), 100,

// std::string());

 

 

const std::string& pcm_origin = kPcmOrigin;

resource_manager->AddProvider(CreatePcmBinaryResourceProvider(pcm_origin),

100, std::string());

 

#elif defined(OS_POSIX)

// Read resources from a directory on disk.

std::string resource_dir;

if (GetResourceDir(resource_dir)) {

resource_manager->AddDirectoryProvider(test_origin, resource_dir, 100,

std::string());

}

#endif

}

 

 

完整如下

CuiResRequest.cpp

 

#include "stdafx.h"

#include "CuiResRequest.h"

#include "include/base/cef_logging.h"

#include "include/cef_stream.h"

#include "include/wrapper/cef_byte_read_handler.h"

#include "include/wrapper/cef_stream_resource_handler.h"

#include "XUnzip.cpp"

#include

 

#define CUI_RESTYPE_FILE

#define ZIP_REALATIVE_PATH L"skin\\dist\\dist.pak"

#define LOCALFILEFLAG "file:///"

 

typedef struct {

DWORD dwsize;

LPBYTE pBytes;

}ResouseInfo;

 

std::map map_resource;

 

static char CharToInt(char ch)

{

if (ch >= '0' && ch <= '9')return (char)(ch - '0');

if (ch >= 'a' && ch <= 'f')return (char)(ch - 'a' + 10);

if (ch >= 'A' && ch <= 'F')return (char)(ch - 'A' + 10);

return -1;

}

static char StrToBin(char *str)

{

char tempWord[2];

char chn;

 

tempWord[0] = CharToInt(str[0]); //make the B to 11 -- 00001011

tempWord[1] = CharToInt(str[1]); //make the 0 to 0 -- 00000000

 

chn = (tempWord[0] << 4) | tempWord[1]; //to change the BO to 10110000

 

return chn;

}

 

std::string URLDecodeToAscii(const std::string str)

{

std::string inputstr = str;

std::string output = "";

char tmp[2];

int i = 0, idx = 0, len = inputstr.length();

 

while (i < len) {

if (inputstr[i] == '%') {

tmp[0] = inputstr[i + 1];

tmp[1] = inputstr[i + 2];

output += StrToBin(tmp);

i = i + 3;

}

else if (inputstr[i] == '+') {

output += ' ';

i++;

}

else {

output += inputstr[i];

i++;

}

}

if (!output.empty())

{

//utf-8 ---> unicode

int unicodeLen = MultiByteToWideChar(CP_UTF8, 0, output.c_str(), -1, nullptr, 0);

wchar_t *pUnicode = (wchar_t*)malloc(sizeof(wchar_t)*unicodeLen);

MultiByteToWideChar(CP_UTF8, 0, output.c_str(), -1, pUnicode, unicodeLen);

 

//unicode ---> ascii

int ansiiLen = WideCharToMultiByte(CP_ACP, 0, pUnicode, -1, nullptr, 0, nullptr, nullptr);

std::string filepath(ansiiLen, 0);

WideCharToMultiByte(CP_ACP, 0, pUnicode, -1, &filepath[0], ansiiLen, nullptr, nullptr);

 

return filepath;

}

 

return output;

}

 

class PcmBinaryResourceProvider : public CefResourceManager::Provider {

public:

explicit PcmBinaryResourceProvider(const std::string& url_path)

: url_path_(url_path) {

DCHECK(!url_path.empty());

}

 

bool OnRequest(scoped_refptr request) OVERRIDE

{

CEF_REQUIRE_IO_THREAD();

 

const std::string& url = request->url();

if (url.find(url_path_) != 0L) {

// Not handled by this provider.

return false;

}

 

CefRefPtr handler;

 

const std::string& relative_path = url.substr(url_path_.length());

if (!relative_path.empty()) {

CefRefPtr stream =

GetBinaryResourceReader(relative_path.data());

if (stream.get()) {

handler = new CefStreamResourceHandler(

request->mime_type_resolver().Run(url),

stream);

}

}

 

request->Continue(handler);

return true;

}

 

private:

std::string url_path_;

 

DISALLOW_COPY_AND_ASSIGN(PcmBinaryResourceProvider);

};

 

std::string GetAppPathA()

{

std::string strPath;

char szBuffer[MAX_PATH] = { 0 };

::GetModuleFileNameA(NULL, szBuffer, MAX_PATH);

strPath = szBuffer;

int nFind = strPath.find_last_of('\\');

return strPath.substr(0, nFind + 1);

}

 

std::wstring GetAppPathW()

{

std::wstring strPath;

wchar_t szBuffer[MAX_PATH] = { 0 };

::GetModuleFileNameW(NULL, szBuffer, MAX_PATH);

strPath = szBuffer;

int nFind = strPath.find_last_of('\\');

return strPath.substr(0, nFind + 1);

}

 

bool LoadResourceFromMemory(const char* resource_name, DWORD &dwSize, LPBYTE &pBytes)

{

if (map_resource.empty())

{

return false;

}

 

std::map::iterator it = map_resource.begin();

for (; it != map_resource.end(); ++it)

{

if (0 == strcmp(resource_name, it->first.c_str()))

{

dwSize = it->second.dwsize;

pBytes = it->second.pBytes;

 

return true;

}

}

return false;

}

 

bool LoadResourceFromFile(const char* resource_name, bool isfullpath, DWORD &dwSize, LPBYTE &pBytes)

{

FILE* fp = nullptr;

std::string urlPath;

if (!isfullpath)

{

urlPath = GetAppPathA();

urlPath += resource_name;

}

else

{

urlPath = resource_name;

}

fopen_s(&fp, urlPath.c_str(), "rb");

 

if (nullptr == fp)

{

return false;

}

 

fseek(fp, 0, SEEK_END);

long filesize = ftell(fp);

rewind(fp);

 

pBytes = (LPBYTE)malloc(sizeof(char) * (filesize + 1));

ZeroMemory(pBytes, sizeof(char) * (filesize + 1));

size_t count = fread(pBytes, 1, filesize, fp);

dwSize = count;

 

ResouseInfo ResInfo;

ResInfo.dwsize = dwSize;

ResInfo.pBytes = pBytes;

map_resource.insert(std::pair(resource_name, ResInfo));

 

return true;

}

 

bool LoadResourceFromZip(const char* resource_name, DWORD &dwSize, LPBYTE &pBytes)

{

std::wstring ZipPath = GetAppPathW();

ZipPath += ZIP_REALATIVE_PATH;

static HZIP hZip = nullptr;

if (nullptr == hZip)

{

hZip = OpenZipU((void*)ZipPath.c_str(), 0, ZIP_FILENAME);

}

 

if (nullptr == hZip)

{

return false;

}

 

int unicodeLen = MultiByteToWideChar(CP_UTF8, 0, resource_name, -1, nullptr, 0);

wchar_t *pUnicode = (wchar_t*)malloc(sizeof(wchar_t)*unicodeLen);

MultiByteToWideChar(CP_UTF8, 0, resource_name, -1, pUnicode, unicodeLen);

 

int index;

ZIPENTRYW ze;

ZRESULT zRet = FindZipItemW(hZip, pUnicode, true, &index, &ze);

if (zRet != ZR_OK)

{

return false;

}

 

zRet = GetZipItemW(hZip, index, &ze);

if (zRet != ZR_OK)

{

return false;

}

 

pBytes = (LPBYTE)malloc(ze.unc_size);

ZeroMemory(pBytes, ze.unc_size);

zRet = UnzipItem(hZip, index, pBytes, ze.unc_size, ZIP_MEMORY);

if (zRet != 0x00000000 && zRet != 0x00000600) {

free(pUnicode);

return false;

}

dwSize = ze.unc_size;

 

ResouseInfo ResInfo;

ResInfo.dwsize = dwSize;

ResInfo.pBytes = pBytes;

map_resource.insert(std::pair(resource_name, ResInfo));

 

free(pUnicode);

return true;

}

#if 0

bool LoadResourceFromFileEx(std::string resource_name, DWORD &dwSize, LPBYTE &pBytes)

{

FILE* fp = nullptr;

fopen_s(&fp, resource_name.c_str(), "rb");

if (nullptr == fp)

{

int num = GetLastError();

return false;

}

 

fseek(fp, 0, SEEK_END);

long filesize = ftell(fp);

rewind(fp);

 

pBytes = (LPBYTE)malloc(sizeof(char) * (filesize + 1));

ZeroMemory(pBytes, sizeof(char) * (filesize + 1));

size_t count = fread(pBytes, 1, filesize, fp);

dwSize = count;

 

ResouseInfo ResInfo;

ResInfo.dwsize = dwSize;

ResInfo.pBytes = pBytes;

map_resource.insert(std::pair(resource_name, ResInfo));

 

return true;

}

#endif

 

bool LoadBinaryResource(const char* resource_name, DWORD &dwSize, LPBYTE &pBytes)

{

if (LoadResourceFromMemory(resource_name, dwSize, pBytes))

{

return true;

}

std::string strFileFlag = resource_name;

std::string temp = strFileFlag.substr(0, 8);

std::string flag = LOCALFILEFLAG;

if (strcmp(temp.c_str(), flag.c_str()) == 0)

{

strFileFlag = strFileFlag.substr(8);

return LoadResourceFromFile(strFileFlag.c_str(), true, dwSize, pBytes);

}

 

#ifdef CUI_RESTYPE_FILE

return LoadResourceFromFile(resource_name, false, dwSize, pBytes);

#else

return LoadResourceFromZip(resource_name, dwSize, pBytes);

#endif

}

 

CefRefPtr GetBinaryResourceReader(const char* resource_name) {

if (nullptr == resource_name)

{

return nullptr;

}

 

DWORD dwSize;

LPBYTE pBytes;

std::string filepath = URLDecodeToAscii(resource_name);

if (LoadBinaryResource(filepath.c_str(), dwSize, pBytes)) {

return CefStreamReader::CreateForHandler(

new CefByteReadHandler(pBytes, dwSize, NULL));

}

 

//TODO:如果资源没找到,不做任何处理

//NOTREACHED(); // The resource should be found.

return NULL;

}

 

CefResourceManager::Provider* CreatePcmBinaryResourceProvider(

const std::string& url_path)

{

return new PcmBinaryResourceProvider(url_path);

}

 

bool LoadBinaryResource(const char* resource_name, std::string& resource_data)

{

DWORD dwSize;

LPBYTE pBytes;

if (!LoadBinaryResource(resource_name, dwSize, pBytes))

{

return false;

}

 

std::string strTemp(dwSize, 0);

memcpy_s(&strTemp[0], dwSize, pBytes, dwSize);

resource_data = strTemp;

 

return true;

}

 

CuiResRequest.h

 

#pragma once

 

#include

#include "include/wrapper/cef_resource_manager.h"

 

bool LoadBinaryResource(const char* resource_name, std::string& resource_data);

CefRefPtr GetBinaryResourceReader(const char* resource_name);

CefResourceManager::Provider* CreatePcmBinaryResourceProvider(

const std::string& url_path);

你可能感兴趣的:(c/c++)