QtWebengineView加载web网页过程分析

一、QtWebengineView使用要点:

向项目中添加相应模块:QT += webenginewidgets 

QWebChannel实现与网页Javascript交互:

  1. QWebChannel *channel = new QWebChannel(this);  
  2. channel->registerObject("bridge", (QObject*)bridge::instance());  
  3. m_webview->page()->setWebChannel(channel);  

网上有很多使用的例子,这里不做赘述,这里主要是针对QtWebengineView加载网页过程分析。

二、QtWebengineView加载网页

void QWebEngineView::load(const QUrl& url)
{
    page()->load(url);
}

这里page:

QWebEnginePage* QWebEngineView::page() const
{
    Q_D(const QWebEngineView);
    if (!d->page) {
        QWebEngineView *that = const_cast<QWebEngineView*>(this);
        that->setPage(new QWebEnginePage(that));
    }
    return d->page;
}

由此可知实际上调用的是QWebEnginePage的load函数。接着进入到QWebEnginePage中:

void QWebEnginePage::load(const QUrl& url)
{
    Q_D(QWebEnginePage);
    d->adapter->load(url);
}
而adapter这里代码如下:
QSharedPointer<QtWebEngineCore::WebContentsAdapter> adapter;

顺着WebContentsAdapter继续找:

void WebContentsAdapter::load(const QUrl &url)
{
    QWebEngineHttpRequest request(url);
    load(request);
}
void WebContentsAdapter::load(const QWebEngineHttpRequest &request)
{
    Q_D(WebContentsAdapter);

    GURL gurl = toGurl(request.url());
    if (!isInitialized()) {


        //注意这里:这里就是生成一个访问实例
        scoped_refptr<content::SiteInstance> site =
            content::SiteInstance::CreateForURL(d->browserContextAdapter->browserContext(), gurl);
        initialize(site.get());
    }

    CHECK_VALID_RENDER_WIDGET_HOST_VIEW(d->webContents->GetRenderViewHost());

    // The situation can occur when relying on the editingFinished signal in QML to set the url
    // of the WebView.
    // When enter is pressed, onEditingFinished fires and the url of the webview is set, which
    // calls into this and focuses the webview, taking the focus from the TextField/TextInput,
    // which in turn leads to editingFinished firing again. This scenario would cause a crash
    // down the line when unwinding as the first RenderWidgetHostViewQtDelegateQuick instance is
    // a dangling pointer by that time.

    if (LoadRecursionGuard::isGuarded(this))
        return;
    LoadRecursionGuard guard(this);
    Q_UNUSED(guard);

    // Add URL scheme if missing from view-source URL.
    if (request.url().scheme() == content::kViewSourceScheme) {
        QUrl pageUrl = QUrl(request.url().toString().remove(0,
                                                           strlen(content::kViewSourceScheme) + 1));
        if (pageUrl.scheme().isEmpty()) {
            QUrl extendedUrl = QUrl::fromUserInput(pageUrl.toString());
            extendedUrl = QUrl(QString("%1:%2").arg(content::kViewSourceScheme,
                                                    extendedUrl.toString()));
            gurl = toGurl(extendedUrl);
        }
    }

    //这个对象是请求的具体内容:包括请求方式、内容
    content::NavigationController::LoadURLParams params(gurl);
    params.transition_type = ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED
                                                     | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR);
    params.override_user_agent = content::NavigationController::UA_OVERRIDE_TRUE;

    switch (request.method()) {
    case QWebEngineHttpRequest::Get:
        params.load_type = content::NavigationController::LOAD_TYPE_DEFAULT;
        break;

    case QWebEngineHttpRequest::Post:
        params.load_type = content::NavigationController::LOAD_TYPE_HTTP_POST;
        // chromium accepts LOAD_TYPE_HTTP_POST only for the HTTP and HTTPS protocols
        if (!params.url.SchemeIsHTTPOrHTTPS()) {
            d->adapterClient->loadFinished(false, request.url(), false,
                                           net::ERR_DISALLOWED_URL_SCHEME,
                                           QCoreApplication::translate("WebContentsAdapter",
                                           "HTTP-POST data can only be sent over HTTP(S) protocol"));
            return;
        }
        break;
    }

    params.post_data = network::ResourceRequestBody::CreateFromBytes(
                (const char*)request.postData().constData(),
                request.postData().length());

    // convert the custom headers into the format that chromium expects
    QVector<QByteArray> headers = request.headers();
    for (QVector<QByteArray>::const_iterator it = headers.cbegin(); it != headers.cend(); ++it) {
        if (params.extra_headers.length() > 0)
            params.extra_headers += '\n';
        params.extra_headers += (*it).toStdString() + ": " + request.header(*it).toStdString();
    }

    bool resizeNeeded = false;
    if (request.url().hasFragment()) {
        if (content::RenderWidgetHostView *rwhv = webContents()->GetRenderWidgetHostView()) {
            const gfx::Size &viewportSize = rwhv->GetVisibleViewportSize();
            resizeNeeded = (viewportSize.width() == 0 || viewportSize.height() == 0);
        }
    }

    auto navigate = [this, params]() {
        Q_D(WebContentsAdapter);
        //发出请求
        webContents()->GetController().LoadURLWithParams(params);
        // Follow chrome::Navigate and invalidate the URL immediately.
        d->webContentsDelegate->NavigationStateChanged(webContents(), content::INVALIDATE_TYPE_URL);
        focusIfNecessary();
    };

    if (resizeNeeded) {
        // Schedule navigation on the event loop.
        QTimer::singleShot(0, navigate);
    } else {
        navigate();
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值