CEF浏览器客户端能扩展(实现前进、后退、刷新、调用控制台、设置cookie等功能)
背景
想要完成一个浏览器客户端的基本功能,除了可以加载出网页页面,实现页面跳转意外,还需要很多其他的功能。例如网页的前进、后退、浏览器的刷新、调出控制台窗口、设置cookie等。后续还会尝试实现页面调用打印时,弹出自定义的打印窗口、支持视频播放等功能。
我们的程序是基于cef.sln中的cefsimple项目现有的功能基础上进行实现的。所以读者想进行测试,可以直接将功能代码注入到cef.sln中的cefsimple项目中进行测试。
具体实现
CefBrowser类表示浏览器窗口,类中实现了GoBack()、GoForward()、Reload()等方法。可以实现网页的后退、前进、刷新等功能。
获取浏览器窗口类
在simple_handler.h文件中有一个浏览器窗口列表变量,里面存储了所有创建了的CefBrowser,所以我们想要获取浏览器窗口类,就需要在simple_handler.h文件中添加一个getBrowser()函数,返回一个CefBrowser。
//simple_handler.h
CefRefPtr<CefBrowser> getBrowser();
//simple_handler.cpp
//如果集合不为空,获取集合中的第一个CefBrowser元素。
CefRefPtr<CefBrowser> SimpleHandler::getBrowser()
{
if(!browser_list_.empty())
{
return browser_list_.front();
}
return NULL;
}
1.前进
直接通过浏览器窗口的SimpleHandler调用我们创建好的getBrowser(),判断指针是否为空,不为空调用GoForward()函数即可。
void CefBrowserWidget::forward()
{
if(m_cefHandler->getBrowser())
{
m_cefHandler->getBrowser()->GoForward();
}
}
2.后退
同前进。方法改为调用GoBack()函数。
void CefBrowserWidget::back()
{
if(m_cefHandler->getBrowser())
{
m_cefHandler->getBrowser()->GoBack();
}
}
3.刷新
同前进。方法改为调用Reload()函数。还可以调用StopLoad()函数停止刷新,调用IsLoading()函数判断是否正在刷新。
void CefBrowserWidget::back()
{
if(m_cefHandler->getBrowser())
{
m_cefHandler->getBrowser()->Reload();
}
}
还可以实现通过按下快捷键F5实现页面刷新。
4.显示控制台窗口
这个功能是用来支持网页开发程序员来调试页面用的,所以也是一个必不可少的功能。
void CefBrowserWidget::back()
{
if(m_cefHandler->getBrowser())
{
CefWindowInfo windowInfo;
CefBrowserSettings settings;
windowInfo.SetAsPopup(NULL, "Dev Tools");
m_cefHandler->getBrowser()->GetHost()
->ShowDevTools(windowInfo, m_cefHandler, settings, CefPoint());
}
}
5.响应快捷键
响应快捷键首先要修改SimpleHandler类,让SimpleHandler继承CefKeyboardHandler类,并重新实现OnPreKeyEvent方法。
除了可以响应单个快捷键,还可以响应组合按键。
//simple_handler.h
class SimpleHandler : public QObject,
public CefClient,
public CefDisplayHandler,
public CefLifeSpanHandler,
public CefLoadHandler,
public CefKeyboardHandler //继承CefKeyboardHandler类
{
……
virtual CefRefPtr<CefKeyboardHandler> GetKeyboardHandler() OVERRIDE{return this;} //一定要有
……
// CefKeyboardHandler methods:
// 重载OnPreKeyEvent
virtual bool OnPreKeyEvent(CefRefPtr<CefBrowser> browser,
const CefKeyEvent &event,
MSG *os_event,
bool *is_keyboard_shortcut) override;
……
}
//simple_handler.cpp
bool SimpleHandler::OnPreKeyEvent(CefRefPtr<CefBrowser> browser, const CefKeyEvent &event,
MSG *os_event, bool *is_keyboard_shortcut)
{
if (event.type == KEYEVENT_RAWKEYDOWN)
{
switch (event.windows_key_code)
{
case VK_F5: //按下按键F5刷新页面
browser->Reload();
return true;
```
case 'H': //按下Ctrl+Alt+H组合按键调用控制台窗口
if(event.modifiers == (EVENTFLAG_CONTROL_DOWN|EVENTFLAG_ALT_DOWN))
{
CefWindowInfo windowInfo;
CefBrowserSettings settings;
windowInfo.SetAsPopup(NULL, "Dev Tools");
browser->GetHost()->ShowDevTools(windowInfo, this, settings, CefPoint());
return true;
}
}
}
return false;
}
6.设置cookie
在这一步时,很多没有开发过浏览器相关功能的小伙伴,可能不是很理解cookie这个东西是干什么的,那就更谈不上知道怎么用它了。
- 首先cookie是什么?cookie的中文翻译是曲奇,小甜饼的意思。但是我们这里说的cookie是一个代名词,跟饼干没什么关系,它其实就是一些数据信息,类型为“小型文本文件”,存储于电脑上的文本文件中。
- 其次,我们为什么要用到cookie?想象一个场景,当我们打开一个网站时,首先需要进行注册或登录。当我们登录过这个网站后,那么我们再次打开网站时,发现就不需要再次登录了,而是直接进入了首页,并且登录信息保留的是我们之前登录过的账号。例如掘金,csdn,知乎等网站都是这样。那浏览器是如何记得这些信息的,就是通过cookie。这些cookie是服务器创建后返回给游览器的。游览器只进行了保存。
- 一般情况下,cookie是以键值对进行表示的(key-value),例如name=test,这个就表示cookie的名字是name,cookie携带的值是test。
- cookie的时效性。cookie是有时效性的,通过设置,可以控制cookie多久之后失效,失效之后的cookie值就不能再自动进入网站首页了。
- 在控制台弹出的窗口中,我们可以看到当前页面的cookie信息。
- cookie中包含name、value、domain、path、expires等信息。这些信息就是我们设置cookie时需要设置的。
- cookie中常用属性的含义:
Name:这个代表这一条cookie的名字。
Value:这个代表这一条cooke的值。
Path:这个定义了Web站点上可以访问该Cookie的目录。
Expires:这个值表示cookie的过期时间,也就是有效期的值,cookie在这个有效期之前都是有效的。
Size:这个表示cookie的大小。\
void CefBrowserWidget::setCookie(QString name, QString value, QString domain, QString path)
{
CefRefPtr<CefCookieManager> manager = CefCookieManager::GetGlobalManager(NULL);
CefCookie cookie;
CefString(&cookie.name).FromString(name.toStdString());
CefString(&cookie.value).FromString(value.toStdString());
CefString(&cookie.domain).FromString(domain.toStdString());
CefString(&cookie.path).FromString(path.toStdString());
cookie.has_expires = true; //设置cookie默认具有时效性
std::wstring httpDomain = m_url.toStdWString();
manager->SetCookie(CefString(httpDomain.c_str()), cookie, NULL);
//需要在设置完cookie之后刷新页面
m_cefHandler->getBrowser()->Reload();
}
CefCookie是一个结构体,创建CefCookie结构体并存入对应变量的值。
CefCookieManager是CEF管理cookie的类。
- 可以调用setCookie()函数设置cookie。
- DeleteCookies()函数可以删除与指定参数匹配的所有cookie。
- FlushStore()函数可以将备份存储(如果有)刷新到磁盘。
7.加载为指定url
当我们通过某一个url创建了一个browser之后,想要在这个browser中显示一个新的url。
void CefBrowserWidget::load(QString url)
{
if(m_cefHandler->getBrowser())
{
CefRefPtr<CefFrame> frame = m_cefHandler->getBrowser()->GetMainFrame();
if (frame)
{
frame->LoadURL(url.toStdWString());
}
}
}
实现浏览器窗口的大小随窗体变化(这种适用于将cef浏览器窗口作为child嵌入到QWidget中显示的情况)。
重写QWidget的resizeEvent()函数,当QWidget大小发生变化时就会响应这个消息。在函数中获取浏览器窗口的HWND,然后获取当前QWidget窗体的大小,通过调用系统函数::MoveWindow()更新浏览器窗口的大小。
void CefBrowserWidget::resizeEvent(QResizeEvent *event)
{
if(m_cefHandler->GetInstance())
{
HWND wnd = m_cefHandler->getBrowserWindowHandle();
if(wnd)
{
QRect qtRect = this->rect();
::MoveWindow(wnd, qtRect.x(), qtRect.y(), qtRect.width(), qtRect.height(), true);
}
}
return QWidget::resizeEvent(event);
}
后续还可以在这些功能的基础上开发浏览器的下载功能(接口类是有的,可以重载下载接口类做操作),还可以实现cef支持视频播放的功能(现在编译好的cef是不支持视频播放的,需要自己做一些处理)。
- 点赞
- 收藏
- 关注作者
评论(0)