CEF浏览器客户端能扩展(实现前进、后退、刷新、调用控制台、设置cookie等功能)

举报
黑兔子 发表于 2022/09/15 13:23:34 2022/09/15
【摘要】 想要完成一个浏览器客户端的基本功能,除了可以加载出网页页面,实现页面跳转意外,还需要很多其他的功能。例如网页的前进、后退、浏览器的刷新、调出控制台窗口、设置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.显示控制台窗口

image.png

这个功能是用来支持网页开发程序员来调试页面用的,所以也是一个必不可少的功能。

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信息。
    image.png
  • 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是不支持视频播放的,需要自己做一些处理)。

【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。