写点什么

CEF | CEF 浏览器客户端功能扩展:实现前进、后退、刷新、调用控制台、设置 cookie、网页自适应窗体大小

作者:YOLO.
  • 2022-10-19
    河北
  • 本文字数:3850 字

    阅读完需:约 1 分钟

CEF | CEF浏览器客户端功能扩展:实现前进、后退、刷新、调用控制台、设置cookie、网页自适应窗体大小

背景

想要完成一个浏览器客户端的基本功能,除了可以加载出网页页面,实现页面跳转意外,还需要很多其他的功能。例如网页的前进、后退、浏览器的刷新、调出控制台窗口、设置 cookie 等。后续还会尝试实现页面调用打印时,弹出自定义的打印窗口、支持视频播放等功能。


我们的程序是基于 cef.sln 中的 cefsimple 项目现有的功能基础上进行实现的。所以读者想进行测试,可以直接将功能代码注入到 cef.sln 中的 cefsimple 项目中进行测试。

具体实现

CefBrowser 类表示浏览器窗口,类中实现了 GoBack()、GoForward()、Reload()等方法。可以实现网页的后退、前进、刷新等功能。

获取浏览器窗口类

在 simple_handler.h 文件中有一个浏览器窗口列表变量,里面存储了所有创建了的 CefBrowser,所以我们想要获取浏览器窗口类,就需要在 simple_handler.h 文件中添加一个 getBrowser()函数,返回一个 CefBrowser。


//simple_handler.hCefRefPtr<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.hclass 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.cppbool 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 的大小。\


设置 cookie 之前要先设置 CefSettings,这个在 main 方法中,可以参考之前的文章。

    // Init CEF    CefSettings settings;    ……    settings.persist_session_cookies = true;    CefInitialize(main_args, settings, app.get(), nullptr);
复制代码


struct Coockie   // 示例{   QString name;            // 名称   QString value;           // 值   QString domain;          // 域名   QString path;            // 路径};
复制代码

自定义一个结构体用来传递 cookie 的参数。


void CefBrowserWidget::setCookie(QString url, Coockie cookie){    CefRefPtr<CefCookieManager> manager = CefCookieManager::GetGlobalManager(NULL);    CefCookie cefCookie;    CefString(&cefCookie.name).FromString(cookie.name.toStdString());    CefString(&cefCookie.value).FromString(cookie.value.toStdString());    CefString(&cefCookie.domain).FromString(cookie.domain.toStdString());    CefString(&cefCookie.path).FromString(cookie.path.toStdString());    cefCookie.has_expires = true;    std::wstring httpDomain = url.toStdWString();    manager->SetCookie(CefString(httpDomain.c_str()), cefCookie, NULL);}
复制代码


设置完 cookie 之后在调用加载。


设置多个 cookie 时,调用多次设置 cookie 的方法就可以了,只需修改每次的传参就行。


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());        }    }}
复制代码

8.实现浏览器窗口的大小随窗体变化(这种适用于将 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 是不支持视频播放的,需要自己做一些处理)。

发布于: 11 分钟前阅读数: 4
用户头像

YOLO.

关注

还未添加个人签名 2022-05-06 加入

还未添加个人简介

评论

发布
暂无评论
CEF | CEF浏览器客户端功能扩展:实现前进、后退、刷新、调用控制台、设置cookie、网页自适应窗体大小_qt_YOLO._InfoQ写作社区