diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp index 26ae9e3c5c0e5ce78074567f73cf936d17e34c6c..95bdaba535d5b690a8eeaeeac703e33cd921aeb0 100644 --- a/src/core/web_contents_adapter.cpp +++ b/src/core/web_contents_adapter.cpp @@ -104,6 +104,10 @@ namespace QtWebEngineCore { +#define CHECK_INITIALIZED(return_value) \ + if (!isInitialized()) \ + return return_value + #define CHECK_VALID_RENDER_WIDGET_HOST_VIEW(render_view_host) \ if (!render_view_host->IsRenderViewLive() && render_view_host->GetWidget()->GetView()) { \ qWarning("Ignore navigation due to terminated render process with invalid RenderWidgetHostView."); \ @@ -406,21 +410,39 @@ WebContentsAdapter::~WebContentsAdapter() { } -void WebContentsAdapter::initialize(WebContentsAdapterClient *adapterClient) +void WebContentsAdapter::setClient(WebContentsAdapterClient *adapterClient) { Q_D(WebContentsAdapter); + Q_ASSERT(!isInitialized()); d->adapterClient = adapterClient; // We keep a reference to browserContextAdapter to keep it alive as long as we use it. // This is needed in case the QML WebEngineProfile is garbage collected before the WebEnginePage. d->browserContextAdapter = adapterClient->browserContextAdapter(); Q_ASSERT(d->browserContextAdapter); - // Create our own if a WebContents wasn't provided at construction. - if (!d->webContents) - d->webContents.reset(createBlankWebContents(adapterClient, d->browserContextAdapter->browserContext())); - // This might replace any adapter that has been initialized with this WebEngineSettings. adapterClient->webEngineSettings()->setWebContentsAdapter(this); +} + +bool WebContentsAdapter::isInitialized() const +{ + Q_D(const WebContentsAdapter); + return bool(d->webContentsDelegate); +} + +void WebContentsAdapter::initialize(content::SiteInstance *site) +{ + Q_D(WebContentsAdapter); + Q_ASSERT(d->adapterClient); + Q_ASSERT(!isInitialized()); + + // Create our own if a WebContents wasn't provided at construction. + if (!d->webContents) { + content::WebContents::CreateParams create_params(d->browserContextAdapter->browserContext(), site); + create_params.initial_size = gfx::Size(kTestWindowWidth, kTestWindowHeight); + create_params.context = reinterpret_cast<gfx::NativeView>(d->adapterClient); + d->webContents.reset(content::WebContents::Create(create_params)); + } content::RendererPreferences* rendererPrefs = d->webContents->GetMutableRendererPrefs(); rendererPrefs->use_custom_colors = true; @@ -434,7 +456,7 @@ void WebContentsAdapter::initialize(WebContentsAdapterClient *adapterClient) if (commandLine->HasSwitch(switches::kForceWebRtcIPHandlingPolicy)) rendererPrefs->webrtc_ip_handling_policy = commandLine->GetSwitchValueASCII(switches::kForceWebRtcIPHandlingPolicy); else - rendererPrefs->webrtc_ip_handling_policy = adapterClient->webEngineSettings()->testAttribute(WebEngineSettings::WebRTCPublicInterfacesOnly) + rendererPrefs->webrtc_ip_handling_policy = d->adapterClient->webEngineSettings()->testAttribute(WebEngineSettings::WebRTCPublicInterfacesOnly) ? content::kWebRTCIPHandlingDefaultPublicInterfaceOnly : content::kWebRTCIPHandlingDefault; #endif @@ -450,12 +472,12 @@ void WebContentsAdapter::initialize(WebContentsAdapterClient *adapterClient) d->webContents->GetRenderViewHost()->SyncRendererPrefs(); // Create and attach observers to the WebContents. - d->webContentsDelegate.reset(new WebContentsDelegateQt(d->webContents.get(), adapterClient)); - d->renderViewObserverHost.reset(new RenderViewObserverHostQt(d->webContents.get(), adapterClient)); + d->webContentsDelegate.reset(new WebContentsDelegateQt(d->webContents.get(), d->adapterClient)); + d->renderViewObserverHost.reset(new RenderViewObserverHostQt(d->webContents.get(), d->adapterClient)); // Let the WebContent's view know about the WebContentsAdapterClient. WebContentsViewQt* contentsView = static_cast<WebContentsViewQt*>(static_cast<content::WebContentsImpl*>(d->webContents.get())->GetView()); - contentsView->initialize(adapterClient); + contentsView->initialize(d->adapterClient); // This should only be necessary after having restored the history to a new WebContentsAdapter. d->webContents->GetController().LoadIfNecessary(); @@ -475,11 +497,14 @@ void WebContentsAdapter::initialize(WebContentsAdapterClient *adapterClient) Q_ASSERT(rvh); if (!rvh->IsRenderViewLive()) static_cast<content::WebContentsImpl*>(d->webContents.get())->CreateRenderViewForRenderManager(rvh, MSG_ROUTING_NONE, MSG_ROUTING_NONE, base::UnguessableToken::Create(), content::FrameReplicationState()); + + d->adapterClient->initializationFinished(); } void WebContentsAdapter::reattachRWHV() { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(); if (content::RenderWidgetHostView *rwhv = d->webContents->GetRenderWidgetHostView()) rwhv->InitAsChild(0); } @@ -487,18 +512,21 @@ void WebContentsAdapter::reattachRWHV() bool WebContentsAdapter::canGoBack() const { Q_D(const WebContentsAdapter); + CHECK_INITIALIZED(false); return d->webContents->GetController().CanGoBack(); } bool WebContentsAdapter::canGoForward() const { Q_D(const WebContentsAdapter); + CHECK_INITIALIZED(false); return d->webContents->GetController().CanGoForward(); } void WebContentsAdapter::stop() { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(); content::NavigationController& controller = d->webContents->GetController(); int index = controller.GetPendingEntryIndex(); @@ -512,6 +540,7 @@ void WebContentsAdapter::stop() void WebContentsAdapter::reload() { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(); CHECK_VALID_RENDER_WIDGET_HOST_VIEW(d->webContents->GetRenderViewHost()); d->webContents->GetController().Reload(content::ReloadType::NORMAL, /*checkRepost = */false); focusIfNecessary(); @@ -520,11 +549,18 @@ void WebContentsAdapter::reload() void WebContentsAdapter::reloadAndBypassCache() { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(); CHECK_VALID_RENDER_WIDGET_HOST_VIEW(d->webContents->GetRenderViewHost()); d->webContents->GetController().Reload(content::ReloadType::BYPASSING_CACHE, /*checkRepost = */false); focusIfNecessary(); } +void WebContentsAdapter::loadDefault() +{ + Q_ASSERT(!isInitialized()); + initialize(nullptr); +} + void WebContentsAdapter::load(const QUrl &url) { QWebEngineHttpRequest request(url); @@ -534,6 +570,14 @@ void WebContentsAdapter::load(const QUrl &url) 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 @@ -549,8 +593,6 @@ void WebContentsAdapter::load(const QWebEngineHttpRequest &request) LoadRecursionGuard guard(this); Q_UNUSED(guard); - GURL gurl = toGurl(request.url()); - // Add URL scheme if missing from view-source URL. if (request.url().scheme() == content::kViewSourceScheme) { QUrl pageUrl = QUrl(request.url().toString().remove(0, @@ -625,6 +667,10 @@ void WebContentsAdapter::load(const QWebEngineHttpRequest &request) void WebContentsAdapter::setContent(const QByteArray &data, const QString &mimeType, const QUrl &baseUrl) { Q_D(WebContentsAdapter); + + if (!isInitialized()) + loadDefault(); + CHECK_VALID_RENDER_WIDGET_HOST_VIEW(d->webContents->GetRenderViewHost()); QByteArray encodedData = data.toPercentEncoding(); @@ -655,6 +701,7 @@ void WebContentsAdapter::setContent(const QByteArray &data, const QString &mimeT void WebContentsAdapter::save(const QString &filePath, int savePageFormat) { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(); d->webContentsDelegate->setSavePageInfo(SavePageInfo(filePath, savePageFormat)); d->webContents->OnSavePage(); } @@ -662,23 +709,23 @@ void WebContentsAdapter::save(const QString &filePath, int savePageFormat) QUrl WebContentsAdapter::activeUrl() const { Q_D(const WebContentsAdapter); + CHECK_INITIALIZED(QUrl()); return d->webContentsDelegate->url(); } QUrl WebContentsAdapter::requestedUrl() const { Q_D(const WebContentsAdapter); - if (d->webContents) { - content::NavigationEntry* entry = d->webContents->GetController().GetVisibleEntry(); - content::NavigationEntry* pendingEntry = d->webContents->GetController().GetPendingEntry(); + CHECK_INITIALIZED(QUrl()); + content::NavigationEntry* entry = d->webContents->GetController().GetVisibleEntry(); + content::NavigationEntry* pendingEntry = d->webContents->GetController().GetPendingEntry(); - if (entry) { - if (!entry->GetOriginalRequestURL().is_empty()) - return toQt(entry->GetOriginalRequestURL()); + if (entry) { + if (!entry->GetOriginalRequestURL().is_empty()) + return toQt(entry->GetOriginalRequestURL()); - if (pendingEntry && pendingEntry == entry) - return toQt(entry->GetURL()); - } + if (pendingEntry && pendingEntry == entry) + return toQt(entry->GetURL()); } return QUrl(); } @@ -686,6 +733,7 @@ QUrl WebContentsAdapter::requestedUrl() const QUrl WebContentsAdapter::iconUrl() const { Q_D(const WebContentsAdapter); + CHECK_INITIALIZED(QUrl()); if (content::NavigationEntry* entry = d->webContents->GetController().GetVisibleEntry()) { content::FaviconStatus favicon = entry->GetFavicon(); if (favicon.valid) @@ -697,12 +745,14 @@ QUrl WebContentsAdapter::iconUrl() const QString WebContentsAdapter::pageTitle() const { Q_D(const WebContentsAdapter); + CHECK_INITIALIZED(QString()); return d->webContentsDelegate->title(); } QString WebContentsAdapter::selectedText() const { Q_D(const WebContentsAdapter); + CHECK_INITIALIZED(QString()); if (auto *rwhv = d->webContents->GetRenderWidgetHostView()) return toQt(rwhv->GetSelectedText()); return QString(); @@ -711,60 +761,70 @@ QString WebContentsAdapter::selectedText() const void WebContentsAdapter::undo() { Q_D(const WebContentsAdapter); + CHECK_INITIALIZED(); d->webContents->Undo(); } void WebContentsAdapter::redo() { Q_D(const WebContentsAdapter); + CHECK_INITIALIZED(); d->webContents->Redo(); } void WebContentsAdapter::cut() { Q_D(const WebContentsAdapter); + CHECK_INITIALIZED(); d->webContents->Cut(); } void WebContentsAdapter::copy() { Q_D(const WebContentsAdapter); + CHECK_INITIALIZED(); d->webContents->Copy(); } void WebContentsAdapter::paste() { Q_D(const WebContentsAdapter); + CHECK_INITIALIZED(); d->webContents->Paste(); } void WebContentsAdapter::pasteAndMatchStyle() { Q_D(const WebContentsAdapter); + CHECK_INITIALIZED(); d->webContents->PasteAndMatchStyle(); } void WebContentsAdapter::selectAll() { Q_D(const WebContentsAdapter); + CHECK_INITIALIZED(); d->webContents->SelectAll(); } void WebContentsAdapter::requestClose() { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(); d->webContents->DispatchBeforeUnload(); } void WebContentsAdapter::unselect() { Q_D(const WebContentsAdapter); + CHECK_INITIALIZED(); d->webContents->CollapseSelection(); } void WebContentsAdapter::navigateToIndex(int offset) { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(); CHECK_VALID_RENDER_WIDGET_HOST_VIEW(d->webContents->GetRenderViewHost()); d->webContents->GetController().GoToIndex(offset); focusIfNecessary(); @@ -773,6 +833,7 @@ void WebContentsAdapter::navigateToIndex(int offset) void WebContentsAdapter::navigateToOffset(int offset) { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(); CHECK_VALID_RENDER_WIDGET_HOST_VIEW(d->webContents->GetRenderViewHost()); d->webContents->GetController().GoToOffset(offset); focusIfNecessary(); @@ -781,18 +842,21 @@ void WebContentsAdapter::navigateToOffset(int offset) int WebContentsAdapter::navigationEntryCount() { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(0); return d->webContents->GetController().GetEntryCount(); } int WebContentsAdapter::currentNavigationEntryIndex() { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(0); return d->webContents->GetController().GetCurrentEntryIndex(); } QUrl WebContentsAdapter::getNavigationEntryOriginalUrl(int index) { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(QUrl()); content::NavigationEntry *entry = d->webContents->GetController().GetEntryAtIndex(index); return entry ? toQt(entry->GetOriginalRequestURL()) : QUrl(); } @@ -800,6 +864,7 @@ QUrl WebContentsAdapter::getNavigationEntryOriginalUrl(int index) QUrl WebContentsAdapter::getNavigationEntryUrl(int index) { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(QUrl()); content::NavigationEntry *entry = d->webContents->GetController().GetEntryAtIndex(index); return entry ? toQt(entry->GetURL()) : QUrl(); } @@ -807,6 +872,7 @@ QUrl WebContentsAdapter::getNavigationEntryUrl(int index) QString WebContentsAdapter::getNavigationEntryTitle(int index) { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(QString()); content::NavigationEntry *entry = d->webContents->GetController().GetEntryAtIndex(index); return entry ? toQt(entry->GetTitle()) : QString(); } @@ -814,6 +880,7 @@ QString WebContentsAdapter::getNavigationEntryTitle(int index) QDateTime WebContentsAdapter::getNavigationEntryTimestamp(int index) { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(QDateTime()); content::NavigationEntry *entry = d->webContents->GetController().GetEntryAtIndex(index); return entry ? toQt(entry->GetTimestamp()) : QDateTime(); } @@ -821,6 +888,7 @@ QDateTime WebContentsAdapter::getNavigationEntryTimestamp(int index) QUrl WebContentsAdapter::getNavigationEntryIconUrl(int index) { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(QUrl()); content::NavigationEntry *entry = d->webContents->GetController().GetEntryAtIndex(index); if (!entry) return QUrl(); @@ -831,6 +899,7 @@ QUrl WebContentsAdapter::getNavigationEntryIconUrl(int index) void WebContentsAdapter::clearNavigationHistory() { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(); if (d->webContents->GetController().CanPruneAllButLastCommitted()) d->webContents->GetController().PruneAllButLastCommitted(); } @@ -838,12 +907,14 @@ void WebContentsAdapter::clearNavigationHistory() void WebContentsAdapter::serializeNavigationHistory(QDataStream &output) { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(); QtWebEngineCore::serializeNavigationHistory(d->webContents->GetController(), output); } void WebContentsAdapter::setZoomFactor(qreal factor) { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(); if (factor < content::kMinimumZoomFactor || factor > content::kMaximumZoomFactor) return; @@ -860,6 +931,7 @@ void WebContentsAdapter::setZoomFactor(qreal factor) qreal WebContentsAdapter::currentZoomFactor() const { Q_D(const WebContentsAdapter); + CHECK_INITIALIZED(1); return content::ZoomLevelToZoomFactor(content::HostZoomMap::GetZoomLevel(d->webContents.get())); } @@ -879,6 +951,7 @@ BrowserContextAdapter* WebContentsAdapter::browserContextAdapter() QAccessibleInterface *WebContentsAdapter::browserAccessible() { Q_D(const WebContentsAdapter); + CHECK_INITIALIZED(nullptr); content::RenderViewHost *rvh = d->webContents->GetRenderViewHost(); Q_ASSERT(rvh); content::BrowserAccessibilityManager *manager = static_cast<content::RenderFrameHostImpl*>(rvh->GetMainFrame())->GetOrCreateBrowserAccessibilityManager(); @@ -893,6 +966,7 @@ QAccessibleInterface *WebContentsAdapter::browserAccessible() void WebContentsAdapter::runJavaScript(const QString &javaScript, quint32 worldId) { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(); content::RenderViewHost *rvh = d->webContents->GetRenderViewHost(); Q_ASSERT(rvh); if (worldId == 0) { @@ -907,6 +981,7 @@ void WebContentsAdapter::runJavaScript(const QString &javaScript, quint32 worldI quint64 WebContentsAdapter::runJavaScriptCallbackResult(const QString &javaScript, quint32 worldId) { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(0); content::RenderViewHost *rvh = d->webContents->GetRenderViewHost(); Q_ASSERT(rvh); content::RenderFrameHost::JavaScriptResultCallback callback = base::Bind(&callbackOnEvaluateJS, d->adapterClient, d->nextRequestId); @@ -920,6 +995,7 @@ quint64 WebContentsAdapter::runJavaScriptCallbackResult(const QString &javaScrip quint64 WebContentsAdapter::fetchDocumentMarkup() { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(0); d->renderViewObserverHost->fetchDocumentMarkup(d->nextRequestId); return d->nextRequestId++; } @@ -927,6 +1003,7 @@ quint64 WebContentsAdapter::fetchDocumentMarkup() quint64 WebContentsAdapter::fetchDocumentInnerText() { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(0); d->renderViewObserverHost->fetchDocumentInnerText(d->nextRequestId); return d->nextRequestId++; } @@ -934,6 +1011,7 @@ quint64 WebContentsAdapter::fetchDocumentInnerText() quint64 WebContentsAdapter::findText(const QString &subString, bool caseSensitively, bool findBackward) { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(0); if (d->lastFindRequestId > d->webContentsDelegate->lastReceivedFindReply()) { // There are cases where the render process will overwrite a previous request // with the new search and we'll have a dangling callback, leaving the application @@ -960,6 +1038,7 @@ quint64 WebContentsAdapter::findText(const QString &subString, bool caseSensitiv void WebContentsAdapter::stopFinding() { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(); d->webContentsDelegate->setLastSearchedString(QString()); d->webContents->StopFinding(content::STOP_FIND_ACTION_KEEP_SELECTION); } @@ -967,6 +1046,7 @@ void WebContentsAdapter::stopFinding() void WebContentsAdapter::updateWebPreferences(const content::WebPreferences & webPreferences) { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(); d->webContents->GetRenderViewHost()->UpdateWebkitPreferences(webPreferences); } @@ -975,6 +1055,7 @@ void WebContentsAdapter::download(const QUrl &url, const QString &suggestedFileN ReferrerPolicy referrerPolicy) { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(); content::BrowserContext *bctx = webContents()->GetBrowserContext(); content::DownloadManager *dlm = content::BrowserContext::GetDownloadManager(bctx); DownloadManagerDelegateQt *dlmd = d->browserContextAdapter->downloadManagerDelegate(); @@ -1021,24 +1102,28 @@ void WebContentsAdapter::download(const QUrl &url, const QString &suggestedFileN bool WebContentsAdapter::isAudioMuted() const { const Q_D(WebContentsAdapter); + CHECK_INITIALIZED(false); return d->webContents->IsAudioMuted(); } void WebContentsAdapter::setAudioMuted(bool muted) { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(); d->webContents->SetAudioMuted(muted); } bool WebContentsAdapter::recentlyAudible() { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(false); return d->webContents->WasRecentlyAudible(); } void WebContentsAdapter::copyImageAt(const QPoint &location) { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(); d->webContents->GetRenderViewHost()->GetMainFrame()->CopyImageAt(location.x(), location.y()); } @@ -1051,6 +1136,7 @@ ASSERT_ENUMS_MATCH(WebContentsAdapter::MediaPlayerControls, blink::WebMediaPlay void WebContentsAdapter::executeMediaPlayerActionAt(const QPoint &location, MediaPlayerAction action, bool enable) { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(); blink::WebMediaPlayerAction blinkAction((blink::WebMediaPlayerAction::Type)action, enable); d->webContents->GetRenderViewHost()->ExecuteMediaPlayerActionAtLocation(toGfx(location), blinkAction); } @@ -1058,6 +1144,7 @@ void WebContentsAdapter::executeMediaPlayerActionAt(const QPoint &location, Medi void WebContentsAdapter::inspectElementAt(const QPoint &location) { Q_D(WebContentsAdapter); + Q_ASSERT(isInitialized()); if (d->devToolsFrontend) { d->devToolsFrontend->InspectElementAt(location.x(), location.y()); return; @@ -1069,6 +1156,7 @@ void WebContentsAdapter::inspectElementAt(const QPoint &location) bool WebContentsAdapter::hasInspector() const { Q_D(const WebContentsAdapter); + CHECK_INITIALIZED(false); if (d->devToolsFrontend) return true; if (content::DevToolsAgentHost::HasFor(d->webContents.get())) @@ -1079,6 +1167,7 @@ bool WebContentsAdapter::hasInspector() const void WebContentsAdapter::openDevToolsFrontend(QSharedPointer<WebContentsAdapter> frontendAdapter) { Q_D(WebContentsAdapter); + Q_ASSERT(isInitialized()); if (d->devToolsFrontend && d->devToolsFrontend->frontendDelegate() == frontendAdapter->webContents()->GetDelegate()) return; @@ -1094,6 +1183,7 @@ void WebContentsAdapter::openDevToolsFrontend(QSharedPointer<WebContentsAdapter> void WebContentsAdapter::closeDevToolsFrontend() { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(); if (d->devToolsFrontend) { d->devToolsFrontend->DisconnectFromTarget(); d->devToolsFrontend->Close(); @@ -1103,6 +1193,7 @@ void WebContentsAdapter::closeDevToolsFrontend() void WebContentsAdapter::devToolsFrontendDestroyed(DevToolsFrontendQt *frontend) { Q_D(WebContentsAdapter); + Q_ASSERT(isInitialized()); Q_ASSERT(frontend == d->devToolsFrontend); Q_UNUSED(frontend); d->devToolsFrontend = nullptr; @@ -1111,24 +1202,28 @@ void WebContentsAdapter::devToolsFrontendDestroyed(DevToolsFrontendQt *frontend) void WebContentsAdapter::exitFullScreen() { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(); d->webContents->ExitFullscreen(false); } void WebContentsAdapter::changedFullScreen() { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(); d->webContents->NotifyFullscreenChanged(false); } void WebContentsAdapter::wasShown() { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(); d->webContents->WasShown(); } void WebContentsAdapter::wasHidden() { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(); d->webContents->WasHidden(); } @@ -1136,6 +1231,7 @@ void WebContentsAdapter::printToPDF(const QPageLayout &pageLayout, const QString { #if BUILDFLAG(ENABLE_BASIC_PRINTING) Q_D(WebContentsAdapter); + CHECK_INITIALIZED(); PrintViewManagerQt::PrintToPDFFileCallback callback = base::Bind(&callbackOnPdfSavingFinished, d->adapterClient, filePath); @@ -1152,6 +1248,7 @@ quint64 WebContentsAdapter::printToPDFCallbackResult(const QPageLayout &pageLayo { #if BUILDFLAG(ENABLE_BASIC_PRINTING) Q_D(WebContentsAdapter); + CHECK_INITIALIZED(0); PrintViewManagerQt::PrintToPDFCallback callback = base::Bind(&callbackOnPrintingFinished, d->adapterClient, d->nextRequestId); @@ -1170,6 +1267,7 @@ quint64 WebContentsAdapter::printToPDFCallbackResult(const QPageLayout &pageLayo QPointF WebContentsAdapter::lastScrollOffset() const { Q_D(const WebContentsAdapter); + CHECK_INITIALIZED(QPointF()); if (content::RenderWidgetHostView *rwhv = d->webContents->GetRenderWidgetHostView()) return toQt(rwhv->GetLastScrollOffset()); return QPointF(); @@ -1178,6 +1276,7 @@ QPointF WebContentsAdapter::lastScrollOffset() const QSizeF WebContentsAdapter::lastContentsSize() const { Q_D(const WebContentsAdapter); + CHECK_INITIALIZED(QSizeF()); if (RenderWidgetHostViewQt *rwhv = static_cast<RenderWidgetHostViewQt *>(d->webContents->GetRenderWidgetHostView())) return toQt(rwhv->lastContentsSize()); return QSizeF(); @@ -1186,6 +1285,7 @@ QSizeF WebContentsAdapter::lastContentsSize() const void WebContentsAdapter::grantMediaAccessPermission(const QUrl &securityOrigin, WebContentsAdapterClient::MediaRequestFlags flags) { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(); // Let the permission manager remember the reply. if (flags & WebContentsAdapterClient::MediaAudioCapture) d->browserContextAdapter->permissionRequestReply(securityOrigin, BrowserContextAdapter::AudioCapturePermission, true); @@ -1197,12 +1297,14 @@ void WebContentsAdapter::grantMediaAccessPermission(const QUrl &securityOrigin, void WebContentsAdapter::runGeolocationRequestCallback(const QUrl &securityOrigin, bool allowed) { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(); d->browserContextAdapter->permissionRequestReply(securityOrigin, BrowserContextAdapter::GeolocationPermission, allowed); } void WebContentsAdapter::grantMouseLockPermission(bool granted) { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(); if (granted) { if (RenderWidgetHostViewQt *rwhv = static_cast<RenderWidgetHostViewQt *>(d->webContents->GetRenderWidgetHostView())) @@ -1217,6 +1319,7 @@ void WebContentsAdapter::grantMouseLockPermission(bool granted) void WebContentsAdapter::dpiScaleChanged() { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(); content::RenderWidgetHostImpl* impl = NULL; if (d->webContents->GetRenderViewHost()) impl = content::RenderWidgetHostImpl::From(d->webContents->GetRenderViewHost()->GetWidget()); @@ -1227,6 +1330,7 @@ void WebContentsAdapter::dpiScaleChanged() void WebContentsAdapter::backgroundColorChanged() { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(); if (content::RenderWidgetHostView *rwhv = d->webContents->GetRenderWidgetHostView()) rwhv->SetBackgroundColor(toSk(d->adapterClient->backgroundColor())); } @@ -1246,6 +1350,7 @@ QWebChannel *WebContentsAdapter::webChannel() const void WebContentsAdapter::setWebChannel(QWebChannel *channel, uint worldId) { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(); if (d->webChannel == channel && d->webChannelWorld == worldId) return; @@ -1260,6 +1365,7 @@ void WebContentsAdapter::setWebChannel(QWebChannel *channel, uint worldId) d->webChannel = channel; d->webChannelWorld = worldId; + if (!channel) { d->webChannelTransport.reset(); return; @@ -1301,6 +1407,7 @@ void WebContentsAdapter::startDragging(QObject *dragSource, const content::DropD const QPoint &offset) { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(); if (d->currentDropData) return; @@ -1353,6 +1460,7 @@ void WebContentsAdapter::startDragging(QObject *dragSource, const content::DropD bool WebContentsAdapter::handleDropDataFileContents(const content::DropData &dropData, QMimeData *mimeData) { + CHECK_INITIALIZED(false); if (dropData.file_contents.empty()) return false; @@ -1409,6 +1517,7 @@ static void fillDropDataFromMimeData(content::DropData *dropData, const QMimeDat void WebContentsAdapter::enterDrag(QDragEnterEvent *e, const QPointF &screenPos) { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(); if (!d->currentDropData) { // The drag originated outside the WebEngineView. @@ -1463,6 +1572,7 @@ static int toWeb(Qt::KeyboardModifiers modifiers) Qt::DropAction WebContentsAdapter::updateDragPosition(QDragMoveEvent *e, const QPointF &screenPos) { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(Qt::DropAction()); content::RenderViewHost *rvh = d->webContents->GetRenderViewHost(); d->lastDragClientPos = toGfx(e->posF()); d->lastDragScreenPos = toGfx(screenPos); @@ -1475,6 +1585,7 @@ Qt::DropAction WebContentsAdapter::updateDragPosition(QDragMoveEvent *e, const Q void WebContentsAdapter::waitForUpdateDragActionCalled() { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(); const qint64 timeout = 3000; QElapsedTimer t; t.start(); @@ -1497,6 +1608,7 @@ void WebContentsAdapter::waitForUpdateDragActionCalled() void WebContentsAdapter::updateDragAction(int action) { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(); d->updateDragActionCalled = true; d->currentDropAction = static_cast<blink::WebDragOperation>(action); } @@ -1504,6 +1616,7 @@ void WebContentsAdapter::updateDragAction(int action) void WebContentsAdapter::endDragging(const QPointF &clientPos, const QPointF &screenPos) { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(); content::RenderViewHost *rvh = d->webContents->GetRenderViewHost(); rvh->GetWidget()->FilterDropData(d->currentDropData.get()); d->lastDragClientPos = toGfx(clientPos); @@ -1515,6 +1628,7 @@ void WebContentsAdapter::endDragging(const QPointF &clientPos, const QPointF &sc void WebContentsAdapter::leaveDrag() { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(); content::RenderViewHost *rvh = d->webContents->GetRenderViewHost(); rvh->GetWidget()->DragTargetDragLeave(d->lastDragClientPos, d->lastDragScreenPos); d->currentDropData.reset(); @@ -1524,6 +1638,7 @@ void WebContentsAdapter::replaceMisspelling(const QString &word) { #if BUILDFLAG(ENABLE_SPELLCHECK) Q_D(WebContentsAdapter); + CHECK_INITIALIZED(); d->webContents->ReplaceMisspelling(toString16(word)); #endif } @@ -1531,6 +1646,7 @@ void WebContentsAdapter::replaceMisspelling(const QString &word) void WebContentsAdapter::focusIfNecessary() { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(); const WebEngineSettings *settings = d->adapterClient->webEngineSettings(); bool focusOnNavigation = settings->testAttribute(WebEngineSettings::FocusOnNavigationEnabled); if (focusOnNavigation) @@ -1540,6 +1656,7 @@ void WebContentsAdapter::focusIfNecessary() bool WebContentsAdapter::isFindTextInProgress() const { Q_D(const WebContentsAdapter); + CHECK_INITIALIZED(false); return d->lastFindRequestId != d->webContentsDelegate->lastReceivedFindReply(); } @@ -1578,18 +1695,21 @@ WebContentsAdapterClient::renderProcessExitStatus(int terminationStatus) { FaviconManager *WebContentsAdapter::faviconManager() { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(nullptr); return d->webContentsDelegate->faviconManager(); } void WebContentsAdapter::viewSource() { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(); d->webContents->GetMainFrame()->ViewSource(); } bool WebContentsAdapter::canViewSource() { Q_D(WebContentsAdapter); + CHECK_INITIALIZED(false); return d->webContents->GetController().CanViewSource(); } diff --git a/src/core/web_contents_adapter.h b/src/core/web_contents_adapter.h index 54b07b4ff375156f968a7d9a246623e3afa4555b..f42dea394330a17cd9ab1435ff12a2719ca4ab9b 100644 --- a/src/core/web_contents_adapter.h +++ b/src/core/web_contents_adapter.h @@ -52,6 +52,8 @@ namespace content { class WebContents; struct WebPreferences; +struct OpenURLParams; +class SiteInstance; } QT_BEGIN_NAMESPACE @@ -78,7 +80,18 @@ public: // Takes ownership of the WebContents. WebContentsAdapter(content::WebContents *webContents = 0); ~WebContentsAdapter(); - void initialize(WebContentsAdapterClient *adapterClient); + + void setClient(WebContentsAdapterClient *adapterClient); + + bool isInitialized() const; + + // These and only these methods will initialize the WebContentsAdapter. All + // other methods below will do nothing until one of these has been called. + void loadDefault(); + void load(const QUrl &url); + void load(const QWebEngineHttpRequest &request); + void setContent(const QByteArray &data, const QString &mimeType, const QUrl &baseUrl); + void reattachRWHV(); bool canGoBack() const; @@ -86,9 +99,6 @@ public: void stop(); void reload(); void reloadAndBypassCache(); - void load(const QUrl &url); - void load(const QWebEngineHttpRequest &request); - void setContent(const QByteArray &data, const QString &mimeType, const QUrl &baseUrl); void save(const QString &filePath = QString(), int savePageFormat = -1); QUrl activeUrl() const; QUrl requestedUrl() const; @@ -183,15 +193,15 @@ public: bool colorMode = true, bool useCustomMargins = true); - // meant to be used within WebEngineCore only - content::WebContents *webContents() const; void replaceMisspelling(const QString &word); - void viewSource(); bool canViewSource(); void focusIfNecessary(); bool isFindTextInProgress() const; + // meant to be used within WebEngineCore only + void initialize(content::SiteInstance *site); + content::WebContents *webContents() const; private: Q_DISABLE_COPY(WebContentsAdapter) diff --git a/src/core/web_contents_adapter_client.h b/src/core/web_contents_adapter_client.h index 899678e560a442ffb016cd2d4a940c46ec7cfcc8..248a963b14e1b2bc62552fe0e6a0b5df133d74cc 100644 --- a/src/core/web_contents_adapter_client.h +++ b/src/core/web_contents_adapter_client.h @@ -395,6 +395,7 @@ public: virtual RenderWidgetHostViewQtDelegate* CreateRenderWidgetHostViewQtDelegate(RenderWidgetHostViewQtDelegateClient *client) = 0; virtual RenderWidgetHostViewQtDelegate* CreateRenderWidgetHostViewQtDelegateForPopup(RenderWidgetHostViewQtDelegateClient *client) = 0; + virtual void initializationFinished() = 0; virtual void titleChanged(const QString&) = 0; virtual void urlChanged(const QUrl&) = 0; virtual void iconChanged(const QUrl&) = 0; diff --git a/src/core/web_contents_delegate_qt.cpp b/src/core/web_contents_delegate_qt.cpp index 4afbbe4367142eafb6688388944afaf1c8703caf..61aeda7bd9fe1f73cbeb01953f06b4ce5f1dcbd3 100644 --- a/src/core/web_contents_delegate_qt.cpp +++ b/src/core/web_contents_delegate_qt.cpp @@ -117,8 +117,11 @@ content::WebContents *WebContentsDelegateQt::OpenURLFromTab(content::WebContents content::WebContents *target = source; if (params.disposition != WindowOpenDisposition::CURRENT_TAB) { QSharedPointer<WebContentsAdapter> targetAdapter = createWindow(0, params.disposition, gfx::Rect(), params.user_gesture); - if (targetAdapter) + if (targetAdapter) { + if (!targetAdapter->isInitialized()) + targetAdapter->initialize(params.source_site_instance.get()); target = targetAdapter->webContents(); + } } Q_ASSERT(target); @@ -211,7 +214,9 @@ void WebContentsDelegateQt::NavigationStateChanged(content::WebContents* source, void WebContentsDelegateQt::AddNewContents(content::WebContents* source, content::WebContents* new_contents, WindowOpenDisposition disposition, const gfx::Rect& initial_pos, bool user_gesture, bool* was_blocked) { Q_UNUSED(source) - QWeakPointer<WebContentsAdapter> newAdapter = createWindow(new_contents, disposition, initial_pos, user_gesture); + QSharedPointer<WebContentsAdapter> newAdapter = createWindow(new_contents, disposition, initial_pos, user_gesture); + if (newAdapter && !newAdapter->isInitialized()) + newAdapter->loadDefault(); if (was_blocked) *was_blocked = !newAdapter; } diff --git a/src/webengine/api/qquickwebenginehistory.cpp b/src/webengine/api/qquickwebenginehistory.cpp index 970bfb22d22107e51a048d1349f457f397874b30..d3c4a0026a710a7196c171fcad61a7b61d6e2e9e 100644 --- a/src/webengine/api/qquickwebenginehistory.cpp +++ b/src/webengine/api/qquickwebenginehistory.cpp @@ -58,8 +58,6 @@ QQuickWebEngineHistoryListModelPrivate::~QQuickWebEngineHistoryListModelPrivate( int QQuickWebEngineHistoryListModelPrivate::count() const { - if (!adapter()) - return 0; return adapter()->navigationEntryCount(); } @@ -70,8 +68,6 @@ int QQuickWebEngineHistoryListModelPrivate::index(int index) const int QQuickWebEngineHistoryListModelPrivate::offsetForIndex(int index) const { - if (!adapter()) - return index; return index - adapter()->currentNavigationEntryIndex(); } @@ -87,8 +83,6 @@ QQuickWebEngineBackHistoryListModelPrivate::QQuickWebEngineBackHistoryListModelP int QQuickWebEngineBackHistoryListModelPrivate::count() const { - if (!adapter()) - return 0; return adapter()->currentNavigationEntryIndex(); } @@ -110,15 +104,13 @@ QQuickWebEngineForwardHistoryListModelPrivate::QQuickWebEngineForwardHistoryList int QQuickWebEngineForwardHistoryListModelPrivate::count() const { - if (!adapter()) + if (!adapter()->isInitialized()) return 0; return adapter()->navigationEntryCount() - adapter()->currentNavigationEntryIndex() - 1; } int QQuickWebEngineForwardHistoryListModelPrivate::index(int i) const { - if (!adapter()) - return i + 1; return adapter()->currentNavigationEntryIndex() + i + 1; } diff --git a/src/webengine/api/qquickwebengineview.cpp b/src/webengine/api/qquickwebengineview.cpp index 2fe146d4cf0db7618725cdf007278e1f5be1badb..18c54c26368df439fff6a11e2ee4380da847c1f0 100644 --- a/src/webengine/api/qquickwebengineview.cpp +++ b/src/webengine/api/qquickwebengineview.cpp @@ -103,7 +103,7 @@ static QAccessibleInterface *webAccessibleFactory(const QString &, QObject *obje #endif // QT_NO_ACCESSIBILITY QQuickWebEngineViewPrivate::QQuickWebEngineViewPrivate() - : adapter(0) + : adapter(QSharedPointer<WebContentsAdapter>::create()) , m_history(new QQuickWebEngineHistory(this)) , m_profile(QQuickWebEngineProfile::defaultProfile()) , m_settings(new QQuickWebEngineSettings(m_profile->settings())) @@ -119,6 +119,7 @@ QQuickWebEngineViewPrivate::QQuickWebEngineViewPrivate() , devicePixelRatio(QGuiApplication::primaryScreen()->devicePixelRatio()) , m_webChannel(0) , m_webChannelWorld(0) + , m_isBeingAdopted(false) , m_dpiScale(1.0) , m_backgroundColor(Qt::white) , m_defaultZoomFactor(1.0) @@ -226,7 +227,7 @@ void QQuickWebEngineViewPrivate::navigationRequested(int navigationType, const Q Q_EMIT q->navigationRequested(&navigationRequest); navigationRequestAction = navigationRequest.action(); - if ((navigationRequestAction == WebContentsAdapterClient::AcceptRequest) && adapter && adapter->isFindTextInProgress()) + if ((navigationRequestAction == WebContentsAdapterClient::AcceptRequest) && adapter->isFindTextInProgress()) adapter->stopFinding(); } @@ -705,47 +706,15 @@ void QQuickWebEngineViewPrivate::adoptWebContents(WebContentsAdapter *webContent return; } - Q_Q(QQuickWebEngineView); + m_isBeingAdopted = true; // This throws away the WebContentsAdapter that has been used until now. // All its states, particularly the loading URL, are replaced by the adopted WebContentsAdapter. - if (adapter) { - WebContentsAdapterOwner *adapterOwner = new WebContentsAdapterOwner(adapter->sharedFromThis()); - adapterOwner->deleteLater(); - } - adapter = webContents->sharedFromThis(); - adapter->initialize(this); - - // associate the webChannel with the new adapter - if (m_webChannel) - adapter->setWebChannel(m_webChannel, m_webChannelWorld); - - if (devToolsView && devToolsView->d_ptr->adapter) - adapter->openDevToolsFrontend(devToolsView->d_ptr->adapter); - else if (inspectedView && inspectedView->d_ptr->adapter) - inspectedView->d_ptr->adapter->openDevToolsFrontend(adapter); - - // set initial background color if non-default - if (m_backgroundColor != Qt::white) - adapter->backgroundColorChanged(); - - // re-bind the userscrips to the new adapter - Q_FOREACH (QQuickWebEngineScript *script, m_userScripts) - script->d_func()->bind(browserContextAdapter()->userResourceController(), adapter.data()); - - // set the zoomFactor if it had been changed on the old adapter. - if (!qFuzzyCompare(adapter->currentZoomFactor(), m_defaultZoomFactor)) - q->setZoomFactor(m_defaultZoomFactor); + WebContentsAdapterOwner *adapterOwner = new WebContentsAdapterOwner(adapter->sharedFromThis()); + adapterOwner->deleteLater(); - // Emit signals for values that might be different from the previous WebContentsAdapter. - emit q->titleChanged(); - emit q->urlChanged(); - emit q->iconChanged(); - // FIXME: The current loading state should be stored in the WebContentAdapter - // and it should be checked here if the signal emission is really necessary. - QQuickWebEngineLoadRequest loadRequest(adapter->activeUrl(), QQuickWebEngineView::LoadSucceededStatus); - emit q->loadingChanged(&loadRequest); - emit q->loadProgressChanged(); + adapter = webContents->sharedFromThis(); + adapter->setClient(this); } QQuickWebEngineView::QQuickWebEngineView(QQuickItem *parent) @@ -754,6 +723,8 @@ QQuickWebEngineView::QQuickWebEngineView(QQuickItem *parent) { Q_D(QQuickWebEngineView); d->q_ptr = this; + d->adapter->setClient(d); + this->setActiveFocusOnTab(true); this->setFlags(QQuickItem::ItemIsFocusScope | QQuickItem::ItemAcceptsDrops); } @@ -761,36 +732,53 @@ QQuickWebEngineView::QQuickWebEngineView(QQuickItem *parent) QQuickWebEngineView::~QQuickWebEngineView() { Q_D(QQuickWebEngineView); - if (d->adapter) - d->adapter->stopFinding(); + d->adapter->stopFinding(); if (d->faviconProvider) d->faviconProvider->detach(this); } void QQuickWebEngineViewPrivate::ensureContentsAdapter() { - Q_Q(QQuickWebEngineView); - if (!adapter) { - adapter = QSharedPointer<WebContentsAdapter>::create(); - adapter->initialize(this); - if (m_backgroundColor != Qt::white) - adapter->backgroundColorChanged(); - if (m_webChannel) - adapter->setWebChannel(m_webChannel, m_webChannelWorld); + if (!adapter->isInitialized()) { if (explicitUrl.isValid()) adapter->load(explicitUrl); - if (inspectedView) - inspectedView->d_ptr->adapter->openDevToolsFrontend(adapter); - // push down the page's user scripts - Q_FOREACH (QQuickWebEngineScript *script, m_userScripts) - script->d_func()->bind(browserContextAdapter()->userResourceController(), adapter.data()); - // set the zoomFactor if it had been changed on the old adapter. - if (!qFuzzyCompare(adapter->currentZoomFactor(), m_defaultZoomFactor)) - q->setZoomFactor(m_defaultZoomFactor); - + else + adapter->loadDefault(); } } +void QQuickWebEngineViewPrivate::initializationFinished() +{ + Q_Q(QQuickWebEngineView); + + if (m_backgroundColor != Qt::white) + adapter->backgroundColorChanged(); + if (m_webChannel) + adapter->setWebChannel(m_webChannel, m_webChannelWorld); + if (!qFuzzyCompare(adapter->currentZoomFactor(), m_defaultZoomFactor)) + q->setZoomFactor(m_defaultZoomFactor); + if (devToolsView && devToolsView->d_ptr->adapter) + adapter->openDevToolsFrontend(devToolsView->d_ptr->adapter); + else if (inspectedView && inspectedView->d_ptr->adapter) + inspectedView->d_ptr->adapter->openDevToolsFrontend(adapter); + + Q_FOREACH (QQuickWebEngineScript *script, m_userScripts) + script->d_func()->bind(browserContextAdapter()->userResourceController(), adapter.data()); + + if (!m_isBeingAdopted) + return; + + // Ideally these would only be emitted if something actually changed. + emit q->titleChanged(); + emit q->urlChanged(); + emit q->iconChanged(); + QQuickWebEngineLoadRequest loadRequest(adapter->activeUrl(), QQuickWebEngineView::LoadSucceededStatus); + emit q->loadingChanged(&loadRequest); + emit q->loadProgressChanged(); + + m_isBeingAdopted = false; +} + void QQuickWebEngineViewPrivate::setFullScreenMode(bool fullscreen) { Q_Q(QQuickWebEngineView); @@ -804,7 +792,7 @@ void QQuickWebEngineViewPrivate::setFullScreenMode(bool fullscreen) QUrl QQuickWebEngineView::url() const { Q_D(const QQuickWebEngineView); - return d->explicitUrl.isValid() ? d->explicitUrl : (d->adapter ? d->adapter->activeUrl() : QUrl()); + return d->explicitUrl.isValid() ? d->explicitUrl : d->adapter->activeUrl(); } void QQuickWebEngineView::setUrl(const QUrl& url) @@ -814,7 +802,7 @@ void QQuickWebEngineView::setUrl(const QUrl& url) Q_D(QQuickWebEngineView); d->explicitUrl = url; - if (d->adapter) + if (d->adapter->isInitialized()) d->adapter->load(url); if (!qmlEngine(this) || isComponentComplete()) d->ensureContentsAdapter(); @@ -832,47 +820,37 @@ void QQuickWebEngineView::loadHtml(const QString &html, const QUrl &baseUrl) d->explicitUrl = QUrl(); if (!qmlEngine(this) || isComponentComplete()) d->ensureContentsAdapter(); - if (d->adapter) + if (d->adapter->isInitialized()) d->adapter->setContent(html.toUtf8(), QStringLiteral("text/html;charset=UTF-8"), baseUrl); } void QQuickWebEngineView::goBack() { Q_D(QQuickWebEngineView); - if (!d->adapter) - return; d->adapter->navigateToOffset(-1); } void QQuickWebEngineView::goForward() { Q_D(QQuickWebEngineView); - if (!d->adapter) - return; d->adapter->navigateToOffset(1); } void QQuickWebEngineView::reload() { Q_D(QQuickWebEngineView); - if (!d->adapter) - return; d->adapter->reload(); } void QQuickWebEngineView::reloadAndBypassCache() { Q_D(QQuickWebEngineView); - if (!d->adapter) - return; d->adapter->reloadAndBypassCache(); } void QQuickWebEngineView::stop() { Q_D(QQuickWebEngineView); - if (!d->adapter) - return; d->adapter->stop(); } @@ -881,9 +859,6 @@ void QQuickWebEngineView::setZoomFactor(qreal arg) Q_D(QQuickWebEngineView); d->m_defaultZoomFactor = arg; - if (!d->adapter) - return; - qreal oldFactor = d->adapter->currentZoomFactor(); d->adapter->setZoomFactor(arg); if (qFuzzyCompare(oldFactor, d->adapter->currentZoomFactor())) @@ -930,14 +905,20 @@ void QQuickWebEngineViewPrivate::setProfile(QQuickWebEngineProfile *profile) Q_EMIT q->profileChanged(); m_settings->setParentSettings(profile->settings()); - if (adapter && adapter->browserContext() != browserContextAdapter()->browserContext()) { + if (adapter->browserContext() != browserContextAdapter()->browserContext()) { // When the profile changes we need to create a new WebContentAdapter and reload the active URL. + bool wasInitialized = adapter->isInitialized(); QUrl activeUrl = adapter->activeUrl(); - adapter.reset(); - ensureContentsAdapter(); - - if (!explicitUrl.isValid() && activeUrl.isValid()) - adapter->load(activeUrl); + adapter = QSharedPointer<WebContentsAdapter>::create(); + adapter->setClient(this); + if (wasInitialized) { + if (explicitUrl.isValid()) + adapter->load(explicitUrl); + else if (activeUrl.isValid()) + adapter->load(activeUrl); + else + adapter->loadDefault(); + } } } @@ -1053,43 +1034,30 @@ int QQuickWebEngineView::loadProgress() const QString QQuickWebEngineView::title() const { Q_D(const QQuickWebEngineView); - if (!d->adapter) - return QString(); return d->adapter->pageTitle(); } bool QQuickWebEngineView::canGoBack() const { Q_D(const QQuickWebEngineView); - if (!d->adapter) - return false; return d->adapter->canGoBack(); } bool QQuickWebEngineView::canGoForward() const { Q_D(const QQuickWebEngineView); - if (!d->adapter) - return false; return d->adapter->canGoForward(); } void QQuickWebEngineView::runJavaScript(const QString &script, const QJSValue &callback) { - Q_D(QQuickWebEngineView); - d->ensureContentsAdapter(); - if (!callback.isUndefined()) { - quint64 requestId = d_ptr->adapter->runJavaScriptCallbackResult(script, QQuickWebEngineScript::MainWorld); - d->m_callbacks.insert(requestId, callback); - } else - d->adapter->runJavaScript(script, QQuickWebEngineScript::MainWorld); + runJavaScript(script, QQuickWebEngineScript::MainWorld, callback); } void QQuickWebEngineView::runJavaScript(const QString &script, quint32 worldId, const QJSValue &callback) { Q_D(QQuickWebEngineView); - if (!d->adapter) - return; + d->ensureContentsAdapter(); if (!callback.isUndefined()) { quint64 requestId = d_ptr->adapter->runJavaScriptCallbackResult(script, worldId); d->m_callbacks.insert(requestId, callback); @@ -1100,7 +1068,7 @@ void QQuickWebEngineView::runJavaScript(const QString &script, quint32 worldId, qreal QQuickWebEngineView::zoomFactor() const { Q_D(const QQuickWebEngineView); - if (!d->adapter) + if (!d->adapter->isInitialized()) return d->m_defaultZoomFactor; return d->adapter->currentZoomFactor(); } @@ -1117,8 +1085,7 @@ void QQuickWebEngineView::setBackgroundColor(const QColor &color) if (color == d->m_backgroundColor) return; d->m_backgroundColor = color; - if (d->adapter) - d->adapter->backgroundColorChanged(); + d->adapter->backgroundColorChanged(); emit backgroundColorChanged(); } @@ -1132,39 +1099,32 @@ void QQuickWebEngineView::setBackgroundColor(const QColor &color) bool QQuickWebEngineView::isAudioMuted() const { const Q_D(QQuickWebEngineView); - if (d->adapter) - return d->adapter->isAudioMuted(); - return false; + return d->adapter->isAudioMuted(); } void QQuickWebEngineView::setAudioMuted(bool muted) { Q_D(QQuickWebEngineView); - bool _isAudioMuted = isAudioMuted(); - if (d->adapter) { - d->adapter->setAudioMuted(muted); - if (_isAudioMuted != muted) { - Q_EMIT audioMutedChanged(muted); - } - } + bool wasAudioMuted = d->adapter->isAudioMuted(); + d->adapter->setAudioMuted(muted); + if (wasAudioMuted != d->adapter->isAudioMuted()) + Q_EMIT audioMutedChanged(muted); } bool QQuickWebEngineView::recentlyAudible() const { const Q_D(QQuickWebEngineView); - if (d->adapter) - return d->adapter->recentlyAudible(); - return false; + return d->adapter->recentlyAudible(); } void QQuickWebEngineView::printToPdf(const QString& filePath, PrintedPageSizeId pageSizeId, PrintedPageOrientation orientation) { #if defined(ENABLE_PDF) - Q_D(const QQuickWebEngineView); + Q_D(QQuickWebEngineView); QPageSize layoutSize(static_cast<QPageSize::PageSizeId>(pageSizeId)); QPageLayout::Orientation layoutOrientation = static_cast<QPageLayout::Orientation>(orientation); QPageLayout pageLayout(layoutSize, layoutOrientation, QMarginsF(0.0, 0.0, 0.0, 0.0)); - + d->ensureContentsAdapter(); d->adapter->printToPDF(pageLayout, filePath); #else Q_UNUSED(filePath); @@ -1184,6 +1144,7 @@ void QQuickWebEngineView::printToPdf(const QJSValue &callback, PrintedPageSizeId if (callback.isUndefined()) return; + d->ensureContentsAdapter(); quint64 requestId = d->adapter->printToPDFCallbackResult(pageLayout); d->m_callbacks.insert(requestId, callback); #else @@ -1213,7 +1174,7 @@ bool QQuickWebEngineView::isFullScreen() const void QQuickWebEngineView::findText(const QString &subString, FindFlags options, const QJSValue &callback) { Q_D(QQuickWebEngineView); - if (!d->adapter) + if (!d->adapter->isInitialized()) return; if (subString.isEmpty()) { d->adapter->stopFinding(); @@ -1240,8 +1201,7 @@ QQmlWebChannel *QQuickWebEngineView::webChannel() Q_D(QQuickWebEngineView); if (!d->m_webChannel) { d->m_webChannel = new QQmlWebChannel(this); - if (d->adapter) - d->adapter->setWebChannel(d->m_webChannel, d->m_webChannelWorld); + d->adapter->setWebChannel(d->m_webChannel, d->m_webChannelWorld); } return d->m_webChannel; @@ -1253,8 +1213,7 @@ void QQuickWebEngineView::setWebChannel(QQmlWebChannel *webChannel) if (d->m_webChannel == webChannel) return; d->m_webChannel = webChannel; - if (d->adapter) - d->adapter->setWebChannel(webChannel, d->m_webChannelWorld); + d->adapter->setWebChannel(webChannel, d->m_webChannelWorld); Q_EMIT webChannelChanged(); } @@ -1270,8 +1229,7 @@ void QQuickWebEngineView::setWebChannelWorld(uint webChannelWorld) if (d->m_webChannelWorld == webChannelWorld) return; d->m_webChannelWorld = webChannelWorld; - if (d->adapter) - d->adapter->setWebChannel(d->m_webChannel, d->m_webChannelWorld); + d->adapter->setWebChannel(d->m_webChannel, d->m_webChannelWorld); Q_EMIT webChannelWorldChanged(webChannelWorld); } @@ -1314,19 +1272,15 @@ void QQuickWebEngineView::setDevToolsView(QQuickWebEngineView *devToolsView) d->devToolsView = devToolsView; if (devToolsView) devToolsView->setInspectedView(this); - if (d->adapter) { - if (devToolsView) - d->adapter->openDevToolsFrontend(devToolsView->d_ptr->adapter); - else - d->adapter->closeDevToolsFrontend(); - } + if (devToolsView) + d->adapter->openDevToolsFrontend(devToolsView->d_ptr->adapter); + else + d->adapter->closeDevToolsFrontend(); Q_EMIT devToolsViewChanged(); } void QQuickWebEngineView::grantFeaturePermission(const QUrl &securityOrigin, QQuickWebEngineView::Feature feature, bool granted) { - if (!d_ptr->adapter) - return; if (!granted && ((feature >= MediaAudioCapture && feature <= MediaAudioVideoCapture) || (feature >= DesktopVideoCapture && feature <= DesktopAudioVideoCapture))) { d_ptr->adapter->grantMediaAccessPermission(securityOrigin, WebContentsAdapterClient::MediaNone); @@ -1374,8 +1328,6 @@ void QQuickWebEngineView::setActiveFocusOnPress(bool arg) void QQuickWebEngineView::goBackOrForward(int offset) { Q_D(QQuickWebEngineView); - if (!d->adapter) - return; const int current = d->adapter->currentNavigationEntryIndex(); const int count = d->adapter->navigationEntryCount(); const int index = current + offset; @@ -1404,7 +1356,7 @@ void QQuickWebEngineView::geometryChanged(const QRectF &newGeometry, const QRect void QQuickWebEngineView::itemChange(ItemChange change, const ItemChangeData &value) { Q_D(QQuickWebEngineView); - if (d->adapter && (change == ItemSceneChange || change == ItemVisibleHasChanged)) { + if (d->adapter->isInitialized() && (change == ItemSceneChange || change == ItemVisibleHasChanged)) { if (window() && isVisible()) d->adapter->wasShown(); else @@ -1666,16 +1618,12 @@ void QQuickWebEngineView::triggerWebAction(WebAction action) QSizeF QQuickWebEngineView::contentsSize() const { Q_D(const QQuickWebEngineView); - if (!d->adapter) - return QSizeF(); return d->adapter->lastContentsSize(); } QPointF QQuickWebEngineView::scrollPosition() const { Q_D(const QQuickWebEngineView); - if (!d->adapter) - return QPointF(); return d->adapter->lastScrollOffset(); } @@ -1683,11 +1631,11 @@ void QQuickWebEngineViewPrivate::userScripts_append(QQmlListProperty<QQuickWebEn { Q_ASSERT(p && p->data); QQuickWebEngineViewPrivate *d = static_cast<QQuickWebEngineViewPrivate*>(p->data); - UserResourceControllerHost *resourceController = d->browserContextAdapter()->userResourceController(); d->m_userScripts.append(script); - // If the adapter hasn't been instantiated, we'll bind the scripts in ensureContentsAdapter() - if (!d->adapter) + // If the adapter hasn't been initialized, we'll bind the scripts in initializationFinished() + if (!d->adapter->isInitialized()) return; + UserResourceControllerHost *resourceController = d->browserContextAdapter()->userResourceController(); script->d_func()->bind(resourceController, d->adapter.data()); } @@ -1709,9 +1657,11 @@ void QQuickWebEngineViewPrivate::userScripts_clear(QQmlListProperty<QQuickWebEng { Q_ASSERT(p && p->data); QQuickWebEngineViewPrivate *d = static_cast<QQuickWebEngineViewPrivate*>(p->data); + d->m_userScripts.clear(); + if (!d->adapter->isInitialized()) + return; UserResourceControllerHost *resourceController = d->browserContextAdapter()->userResourceController(); resourceController->clearAllScripts(d->adapter.data()); - d->m_userScripts.clear(); } void QQuickWebEngineView::componentComplete() diff --git a/src/webengine/api/qquickwebengineview_p_p.h b/src/webengine/api/qquickwebengineview_p_p.h index 4b8617749dbcbad78ded5366f458330e23904a2f..7369a63be2b5fcfe9f63c5acbea509a6378c99b8 100644 --- a/src/webengine/api/qquickwebengineview_p_p.h +++ b/src/webengine/api/qquickwebengineview_p_p.h @@ -93,6 +93,7 @@ public: QtWebEngineCore::RenderWidgetHostViewQtDelegate* CreateRenderWidgetHostViewQtDelegate(QtWebEngineCore::RenderWidgetHostViewQtDelegateClient *client) override; QtWebEngineCore::RenderWidgetHostViewQtDelegate* CreateRenderWidgetHostViewQtDelegateForPopup(QtWebEngineCore::RenderWidgetHostViewQtDelegateClient *client) override; + void initializationFinished() override; void titleChanged(const QString&) override; void urlChanged(const QUrl&) override; void iconChanged(const QUrl&) override; @@ -185,6 +186,7 @@ public: QPointer<QQuickWebEngineView> inspectedView; QPointer<QQuickWebEngineView> devToolsView; uint m_webChannelWorld; + bool m_isBeingAdopted; private: QScopedPointer<QtWebEngineCore::UIDelegatesManager> m_uIDelegatesManager; diff --git a/src/webenginewidgets/api/qwebenginehistory.cpp b/src/webenginewidgets/api/qwebenginehistory.cpp index 48ddbc48e9d68d4771e1c43369650def6e095eb3..34279b0169007489dbe8bbd630c7423e97c650db 100644 --- a/src/webenginewidgets/api/qwebenginehistory.cpp +++ b/src/webenginewidgets/api/qwebenginehistory.cpp @@ -257,12 +257,17 @@ int QWebEngineHistory::currentItemIndex() const int QWebEngineHistory::count() const { Q_D(const QWebEngineHistory); + if (!d->page->webContents()->isInitialized()) + return 0; return d->page->webContents()->navigationEntryCount(); } QDataStream& operator<<(QDataStream& stream, const QWebEngineHistory& history) { - history.d_func()->page->webContents()->serializeNavigationHistory(stream); + QtWebEngineCore::WebContentsAdapter *adapter = history.d_func()->page->webContents(); + if (!adapter->isInitialized()) + adapter->loadDefault(); + adapter->serializeNavigationHistory(stream); return stream; } diff --git a/src/webenginewidgets/api/qwebenginepage.cpp b/src/webenginewidgets/api/qwebenginepage.cpp index 6b91bd22161e4adb78850836d34190d55aad54d4..1c42628eec8a7077422c320795b0c86801156f83 100644 --- a/src/webenginewidgets/api/qwebenginepage.cpp +++ b/src/webenginewidgets/api/qwebenginepage.cpp @@ -226,6 +226,8 @@ QWebEnginePagePrivate::QWebEnginePagePrivate(QWebEngineProfile *_profile) , fullscreenMode(false) , webChannel(nullptr) , webChannelWorldId(QWebEngineScript::MainWorld) + , defaultAudioMuted(false) + , defaultZoomFactor(1.0) #if defined(ENABLE_PRINTING) , currentPrinter(nullptr) #endif @@ -234,6 +236,13 @@ QWebEnginePagePrivate::QWebEnginePagePrivate(QWebEngineProfile *_profile) qRegisterMetaType<QWebEngineQuotaPermissionRequest>(); qRegisterMetaType<QWebEngineRegisterProtocolHandlerPermissionRequest>(); + + // See wasShown() and wasHidden(). + wasShownTimer.setSingleShot(true); + QObject::connect(&wasShownTimer, &QTimer::timeout, [this](){ + ensureInitialized(); + wasShown(); + }); } QWebEnginePagePrivate::~QWebEnginePagePrivate() @@ -256,6 +265,22 @@ RenderWidgetHostViewQtDelegate *QWebEnginePagePrivate::CreateRenderWidgetHostVie return new RenderWidgetHostViewQtDelegateWidget(client, this->view); } +void QWebEnginePagePrivate::initializationFinished() +{ + if (m_backgroundColor != Qt::white) + adapter->backgroundColorChanged(); + if (webChannel) + adapter->setWebChannel(webChannel, webChannelWorldId); + if (defaultAudioMuted != adapter->isAudioMuted()) + adapter->setAudioMuted(defaultAudioMuted); + if (!qFuzzyCompare(adapter->currentZoomFactor(), defaultZoomFactor)) + adapter->setZoomFactor(defaultZoomFactor); + + scriptCollection.d->initializationFinished(adapter); + + m_isBeingAdopted = false; +} + void QWebEnginePagePrivate::titleChanged(const QString &title) { Q_Q(QWebEnginePage); @@ -426,18 +451,10 @@ void QWebEnginePagePrivate::adoptNewWindowImpl(QWebEnginePage *newPage, // Overwrite the new page's WebContents with ours. newPage->d_func()->adapter = newWebContents; - newWebContents->initialize(newPage->d_func()); - newPage->d_func()->scriptCollection.d->rebindToContents(newWebContents); + newWebContents->setClient(newPage->d_func()); + if (!initialGeometry.isEmpty()) emit newPage->geometryChangeRequested(initialGeometry); - - // If the constructor of the QWebEnginePage descendant set a web channel, - // set it on the new adapter. - newWebContents->setWebChannel(newPage->d_func()->webChannel - , newPage->d_func()->webChannelWorldId); - - // Page has finished the adoption process. - newPage->d_func()->m_isBeingAdopted = false; } bool QWebEnginePagePrivate::isBeingAdopted() @@ -599,6 +616,11 @@ void QWebEnginePagePrivate::updateAction(QWebEnginePage::WebAction action) const if (!a) return; + if (!adapter->isInitialized()) { + a->setEnabled(false); + return; + } + bool enabled = true; switch (action) { @@ -653,10 +675,8 @@ void QWebEnginePagePrivate::recreateFromSerializedHistory(QDataStream &input) QSharedPointer<WebContentsAdapter> newWebContents = WebContentsAdapter::createFromSerializedNavigationHistory(input, this); if (newWebContents) { adapter = std::move(newWebContents); - adapter->initialize(this); - if (webChannel) - adapter->setWebChannel(webChannel, webChannelWorldId); - scriptCollection.d->rebindToContents(adapter); + adapter->setClient(this); + adapter->loadDefault(); } } @@ -687,6 +707,7 @@ QSharedPointer<BrowserContextAdapter> QWebEnginePagePrivate::browserContextAdapt WebContentsAdapter *QWebEnginePagePrivate::webContentsAdapter() { + ensureInitialized(); return adapter.data(); } @@ -696,13 +717,19 @@ const QObject *QWebEnginePagePrivate::holdingQObject() const return q; } +void QWebEnginePagePrivate::ensureInitialized() const +{ + if (!adapter->isInitialized()) + adapter->loadDefault(); +} + QWebEnginePage::QWebEnginePage(QObject* parent) : QObject(parent) , d_ptr(new QWebEnginePagePrivate()) { Q_D(QWebEnginePage); d->q_ptr = this; - d->adapter->initialize(d); + d->adapter->setClient(d); } /*! @@ -849,15 +876,14 @@ QWebEnginePage::QWebEnginePage(QWebEngineProfile *profile, QObject* parent) { Q_D(QWebEnginePage); d->q_ptr = this; - d->adapter->initialize(d); + d->adapter->setClient(d); } QWebEnginePage::~QWebEnginePage() { Q_D(QWebEnginePage); setDevToolsPage(nullptr); - if (d->adapter) - d->adapter->stopFinding(); + d->adapter->stopFinding(); QWebEngineViewPrivate::bind(d->view, 0); } @@ -976,6 +1002,7 @@ void QWebEnginePage::save(const QString &filePath, QWebEngineDownloadItem::SavePageFormat format) const { Q_D(const QWebEnginePage); + d->ensureInitialized(); d->adapter->save(filePath, format); } @@ -988,20 +1015,19 @@ void QWebEnginePage::save(const QString &filePath, \sa recentlyAudible */ bool QWebEnginePage::isAudioMuted() const { - const Q_D(QWebEnginePage); - return d->adapter->isAudioMuted(); + Q_D(const QWebEnginePage); + if (d->adapter->isInitialized()) + return d->adapter->isAudioMuted(); + return d->defaultAudioMuted; } void QWebEnginePage::setAudioMuted(bool muted) { Q_D(QWebEnginePage); - bool _isAudioMuted = isAudioMuted(); - d->adapter->setAudioMuted(muted); - if (_isAudioMuted != muted) { - Q_EMIT audioMutedChanged(muted); - } + d->defaultAudioMuted = muted; + if (d->adapter->isInitialized()) + d->adapter->setAudioMuted(muted); } - /*! \property QWebEnginePage::recentlyAudible \brief the current page's \e {audible state}, that is, whether audio was recently played @@ -1013,8 +1039,8 @@ void QWebEnginePage::setAudioMuted(bool muted) { */ bool QWebEnginePage::recentlyAudible() const { - const Q_D(QWebEnginePage); - return d->adapter->recentlyAudible(); + Q_D(const QWebEnginePage); + return d->adapter->isInitialized() && d->adapter->recentlyAudible(); } void QWebEnginePage::setView(QWidget *view) @@ -1225,6 +1251,7 @@ QAction *QWebEnginePage::action(WebAction action) const void QWebEnginePage::triggerAction(WebAction action, bool) { Q_D(QWebEnginePage); + d->ensureInitialized(); const QtWebEngineCore::WebEngineContextMenuData &menuData = *d->contextData.d; switch (action) { case Back: @@ -1471,6 +1498,10 @@ void QWebEnginePage::replaceMisspelledWord(const QString &replacement) void QWebEnginePage::findText(const QString &subString, FindFlags options, const QWebEngineCallback<bool> &resultCallback) { Q_D(QWebEnginePage); + if (!d->adapter->isInitialized()) { + d->m_callbacks.invokeEmpty(resultCallback); + return; + } if (subString.isEmpty()) { d->adapter->stopFinding(); d->m_callbacks.invokeEmpty(resultCallback); @@ -1490,11 +1521,26 @@ bool QWebEnginePage::event(QEvent *e) void QWebEnginePagePrivate::wasShown() { + if (!adapter->isInitialized()) { + // On the one hand, it is too early to initialize here. The application + // may call show() before load(), or it may call show() from + // createWindow(), and then we would create an unnecessary blank + // WebContents here. On the other hand, if the application calls show() + // then it expects something to be shown, so we have to initialize. + // Therefore we have to delay the initialization via the event loop. + wasShownTimer.start(); + return; + } adapter->wasShown(); } void QWebEnginePagePrivate::wasHidden() { + if (!adapter->isInitialized()) { + // Cancel timer from wasShown() above. + wasShownTimer.stop(); + return; + } adapter->wasHidden(); } @@ -1534,7 +1580,7 @@ void QWebEnginePagePrivate::navigationRequested(int navigationType, const QUrl & { Q_Q(QWebEnginePage); bool accepted = q->acceptNavigationRequest(url, static_cast<QWebEnginePage::NavigationType>(navigationType), isMainFrame); - if (accepted && adapter && adapter->isFindTextInProgress()) + if (accepted && adapter->isFindTextInProgress()) adapter->stopFinding(); navigationRequestAction = accepted ? WebContentsAdapterClient::AcceptRequest : WebContentsAdapterClient::IgnoreRequest; } @@ -1655,6 +1701,7 @@ QMenu *QWebEnginePage::createStandardContextMenu() Q_D(QWebEnginePage); if (!d->contextData.d) return nullptr; + d->ensureInitialized(); QMenu *menu = new QMenu(d->view); const WebEngineContextMenuData &contextMenuData = *d->contextData.d; @@ -1767,6 +1814,7 @@ WebEngineSettings *QWebEnginePagePrivate::webEngineSettings() const void QWebEnginePage::download(const QUrl& url, const QString& filename) { Q_D(QWebEnginePage); + d->ensureInitialized(); d->adapter->download(url, filename); } @@ -1791,6 +1839,7 @@ void QWebEnginePage::load(const QWebEngineHttpRequest& request) void QWebEnginePage::toHtml(const QWebEngineCallback<const QString &> &resultCallback) const { Q_D(const QWebEnginePage); + d->ensureInitialized(); quint64 requestId = d->adapter->fetchDocumentMarkup(); d->m_callbacks.registerCallback(requestId, resultCallback); } @@ -1798,6 +1847,7 @@ void QWebEnginePage::toHtml(const QWebEngineCallback<const QString &> &resultCal void QWebEnginePage::toPlainText(const QWebEngineCallback<const QString &> &resultCallback) const { Q_D(const QWebEnginePage); + d->ensureInitialized(); quint64 requestId = d->adapter->fetchDocumentInnerText(); d->m_callbacks.registerCallback(requestId, resultCallback); } @@ -1867,7 +1917,7 @@ QIcon QWebEnginePage::icon() const { Q_D(const QWebEnginePage); - if (d->iconUrl.isEmpty()) + if (d->iconUrl.isEmpty() || !d->adapter->isInitialized()) return QIcon(); return d->adapter->faviconManager()->getIcon(); @@ -1876,24 +1926,30 @@ QIcon QWebEnginePage::icon() const qreal QWebEnginePage::zoomFactor() const { Q_D(const QWebEnginePage); - return d->adapter->currentZoomFactor(); + if (d->adapter->isInitialized()) + return d->adapter->currentZoomFactor(); + return d->defaultZoomFactor; } void QWebEnginePage::setZoomFactor(qreal factor) { Q_D(QWebEnginePage); - d->adapter->setZoomFactor(factor); + d->defaultZoomFactor = factor; + if (d->adapter->isInitialized()) + d->adapter->setZoomFactor(factor); } void QWebEnginePage::runJavaScript(const QString &scriptSource) { Q_D(QWebEnginePage); + d->ensureInitialized(); d->adapter->runJavaScript(scriptSource, QWebEngineScript::MainWorld); } void QWebEnginePage::runJavaScript(const QString& scriptSource, const QWebEngineCallback<const QVariant &> &resultCallback) { Q_D(QWebEnginePage); + d->ensureInitialized(); quint64 requestId = d->adapter->runJavaScriptCallbackResult(scriptSource, QWebEngineScript::MainWorld); d->m_callbacks.registerCallback(requestId, resultCallback); } @@ -1901,12 +1957,14 @@ void QWebEnginePage::runJavaScript(const QString& scriptSource, const QWebEngine void QWebEnginePage::runJavaScript(const QString &scriptSource, quint32 worldId) { Q_D(QWebEnginePage); + d->ensureInitialized(); d->adapter->runJavaScript(scriptSource, worldId); } void QWebEnginePage::runJavaScript(const QString& scriptSource, quint32 worldId, const QWebEngineCallback<const QVariant &> &resultCallback) { Q_D(QWebEnginePage); + d->ensureInitialized(); quint64 requestId = d->adapter->runJavaScriptCallbackResult(scriptSource, worldId); d->m_callbacks.registerCallback(requestId, resultCallback); } @@ -2010,6 +2068,7 @@ void QWebEnginePage::setDevToolsPage(QWebEnginePage *devToolsPage) Q_D(QWebEnginePage); if (d->devToolsPage == devToolsPage) return; + d->ensureInitialized(); QWebEnginePage *oldDevTools = d->devToolsPage; d->devToolsPage = nullptr; if (oldDevTools) @@ -2152,6 +2211,7 @@ void QWebEnginePage::printToPdf(const QString &filePath, const QPageLayout &page return; } #endif // ENABLE_PRINTING + d->ensureInitialized(); d->adapter->printToPDF(pageLayout, filePath); #else Q_UNUSED(filePath); @@ -2181,6 +2241,7 @@ void QWebEnginePage::printToPdf(const QWebEngineCallback<const QByteArray&> &res return; } #endif // ENABLE_PRINTING + d->ensureInitialized(); quint64 requestId = d->adapter->printToPDFCallbackResult(pageLayout); d->m_callbacks.registerCallback(requestId, resultCallback); #else // if defined(ENABLE_PDF) @@ -2213,6 +2274,7 @@ void QWebEnginePage::print(QPrinter *printer, const QWebEngineCallback<bool> &re } d->currentPrinter = printer; #endif // ENABLE_PRINTING + d->ensureInitialized(); quint64 requestId = d->adapter->printToPDFCallbackResult(printer->pageLayout(), printer->colorMode() == QPrinter::Color, false); diff --git a/src/webenginewidgets/api/qwebenginepage_p.h b/src/webenginewidgets/api/qwebenginepage_p.h index 81caaf4157c3e2ede51e655832efbc863b0e6b7c..fd792800659dc8763c9df065435ce5b4eb2b2233 100644 --- a/src/webenginewidgets/api/qwebenginepage_p.h +++ b/src/webenginewidgets/api/qwebenginepage_p.h @@ -61,6 +61,7 @@ #include <QtCore/qcompilerdetection.h> #include <QtCore/QPointer> +#include <QtCore/QTimer> namespace QtWebEngineCore { class RenderWidgetHostViewQtDelegate; @@ -87,6 +88,7 @@ public: QtWebEngineCore::RenderWidgetHostViewQtDelegate* CreateRenderWidgetHostViewQtDelegate(QtWebEngineCore::RenderWidgetHostViewQtDelegateClient *client) override; QtWebEngineCore::RenderWidgetHostViewQtDelegate* CreateRenderWidgetHostViewQtDelegateForPopup(QtWebEngineCore::RenderWidgetHostViewQtDelegateClient *client) override { return CreateRenderWidgetHostViewQtDelegate(client); } + void initializationFinished() override; void titleChanged(const QString&) override; void urlChanged(const QUrl&) override; void iconChanged(const QUrl&) override; @@ -158,6 +160,7 @@ public: void recreateFromSerializedHistory(QDataStream &input); void setFullScreenMode(bool); + void ensureInitialized() const; QSharedPointer<QtWebEngineCore::WebContentsAdapter> adapter; QWebEngineHistory *history; @@ -177,6 +180,9 @@ public: bool m_navigationActionTriggered; QPointer<QWebEnginePage> inspectedPage; QPointer<QWebEnginePage> devToolsPage; + bool defaultAudioMuted; + qreal defaultZoomFactor; + QTimer wasShownTimer; mutable QtWebEngineCore::CallbackDirectory m_callbacks; mutable QAction *actions[QWebEnginePage::WebActionCount]; diff --git a/src/webenginewidgets/api/qwebenginescriptcollection.cpp b/src/webenginewidgets/api/qwebenginescriptcollection.cpp index 8d393924fdecd35d126c0e57b7c4024152a2c082..bcf0c127c78701e8e773d5eb74cc4e64be9337a3 100644 --- a/src/webenginewidgets/api/qwebenginescriptcollection.cpp +++ b/src/webenginewidgets/api/qwebenginescriptcollection.cpp @@ -175,63 +175,72 @@ QWebEngineScriptCollectionPrivate::QWebEngineScriptCollectionPrivate(QtWebEngine int QWebEngineScriptCollectionPrivate::count() const { - return m_scriptController->registeredScripts(m_contents.data()).count(); + return m_scripts.count(); } bool QWebEngineScriptCollectionPrivate::contains(const QWebEngineScript &s) const { - return m_scriptController->containsUserScript(*s.d, m_contents.data()); + return m_scripts.contains(s); } void QWebEngineScriptCollectionPrivate::insert(const QWebEngineScript &script) { - if (!script.d) + if (!script.d || script.d->isNull()) return; - m_scriptController->addUserScript(*script.d, m_contents.data()); + m_scripts.append(script); + if (!m_contents || m_contents->isInitialized()) + m_scriptController->addUserScript(*script.d, m_contents.data()); } bool QWebEngineScriptCollectionPrivate::remove(const QWebEngineScript &script) { - if (!script.d) + if (!script.d || script.d->isNull()) return false; - return m_scriptController->removeUserScript(*script.d, m_contents.data()); + if (!m_contents || m_contents->isInitialized()) + m_scriptController->removeUserScript(*script.d, m_contents.data()); + return m_scripts.removeAll(script); } QList<QWebEngineScript> QWebEngineScriptCollectionPrivate::toList(const QString &scriptName) const { + if (scriptName.isNull()) + return m_scripts; + QList<QWebEngineScript> ret; - Q_FOREACH (const UserScript &script, m_scriptController->registeredScripts(m_contents.data())) - if (scriptName.isNull() || scriptName == script.name()) - ret.append(QWebEngineScript(script)); + Q_FOREACH (const QWebEngineScript &script, m_scripts) + if (scriptName == script.name()) + ret.append(script); return ret; } QWebEngineScript QWebEngineScriptCollectionPrivate::find(const QString &name) const { - Q_FOREACH (const UserScript &script, m_scriptController->registeredScripts(m_contents.data())) + Q_FOREACH (const QWebEngineScript &script, m_scripts) if (name == script.name()) - return QWebEngineScript(script); + return script; return QWebEngineScript(); } void QWebEngineScriptCollectionPrivate::clear() { - m_scriptController->clearAllScripts(m_contents.data()); + m_scripts.clear(); + if (!m_contents || m_contents->isInitialized()) + m_scriptController->clearAllScripts(m_contents.data()); } void QWebEngineScriptCollectionPrivate::reserve(int capacity) { - m_scriptController->reserve(m_contents.data(), capacity); + m_scripts.reserve(capacity); + if (!m_contents || m_contents->isInitialized()) + m_scriptController->reserve(m_contents.data(), capacity); } -void QWebEngineScriptCollectionPrivate::rebindToContents(QSharedPointer<QtWebEngineCore::WebContentsAdapter> contents) +void QWebEngineScriptCollectionPrivate::initializationFinished(QSharedPointer<QtWebEngineCore::WebContentsAdapter> contents) { Q_ASSERT(m_contents); Q_ASSERT(contents); - Q_ASSERT(m_contents != contents); - Q_FOREACH (const UserScript &script, m_scriptController->registeredScripts(m_contents.data())) { - m_scriptController->addUserScript(script, contents.data()); - } + Q_FOREACH (const QWebEngineScript &script, m_scripts) + m_scriptController->addUserScript(*script.d, contents.data()); m_contents = contents; } diff --git a/src/webenginewidgets/api/qwebenginescriptcollection_p.h b/src/webenginewidgets/api/qwebenginescriptcollection_p.h index fa4b4d790ba1a577cac66329a7d5c1778ce10997..322ade3b6f302a3d54be693751cd4baf89eac91d 100644 --- a/src/webenginewidgets/api/qwebenginescriptcollection_p.h +++ b/src/webenginewidgets/api/qwebenginescriptcollection_p.h @@ -73,7 +73,7 @@ public: QList<QWebEngineScript> toList(const QString &scriptName = QString()) const; QWebEngineScript find(const QString & name) const; - void rebindToContents(QSharedPointer<QtWebEngineCore::WebContentsAdapter> contents); + void initializationFinished(QSharedPointer<QtWebEngineCore::WebContentsAdapter> contents); void insert(const QWebEngineScript &); bool remove(const QWebEngineScript &); @@ -83,6 +83,7 @@ public: private: QtWebEngineCore::UserResourceControllerHost *m_scriptController; QSharedPointer<QtWebEngineCore::WebContentsAdapter> m_contents; + QList<QWebEngineScript> m_scripts; }; QT_END_NAMESPACE diff --git a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp index 81877657b2e74d259080692b8208edabcd0841d3..18a33695a0537e21995489d9ff51fefa46944b3e 100644 --- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp +++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp @@ -3974,8 +3974,8 @@ void tst_QWebEnginePage::setZoomFactor() const QUrl urlToLoad("qrc:/resources/test1.html"); - QSignalSpy finishedSpy(m_page, SIGNAL(loadFinished(bool))); - m_page->setUrl(urlToLoad); + QSignalSpy finishedSpy(&page, SIGNAL(loadFinished(bool))); + page.load(urlToLoad); QTRY_COMPARE(finishedSpy.count(), 1); QVERIFY(finishedSpy.at(0).first().toBool()); QVERIFY(qFuzzyCompare(page.zoomFactor(), 2.5)); diff --git a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp index d58bfe0b3fb996f1a029db0c47a021463d0ac722..207836bef49254b627afe1dc88004fdf8f93dac3 100644 --- a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp +++ b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp @@ -873,6 +873,7 @@ void tst_QWebEngineView::stopSettingFocusWhenDisabled() QFETCH(bool, focusResult); QWebEngineView webView; + webView.settings()->setAttribute(QWebEngineSettings::FocusOnNavigationEnabled, true); webView.resize(640, 480); webView.show(); webView.setEnabled(viewEnabled);