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);