| /* |
| * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies) |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Library General Public |
| * License as published by the Free Software Foundation; either |
| * version 2 of the License, or (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Library General Public License for more details. |
| * |
| * You should have received a copy of the GNU Library General Public License |
| * along with this program; see the file COPYING.LIB. If not, write to |
| * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
| * Boston, MA 02110-1301, USA. |
| * |
| */ |
| |
| #include "config.h" |
| #include "qquickwebview_p.h" |
| |
| #include "DownloadProxy.h" |
| #include "DrawingAreaProxyImpl.h" |
| #include "QtDialogRunner.h" |
| #include "QtDownloadManager.h" |
| #include "QtWebContext.h" |
| #include "QtWebIconDatabaseClient.h" |
| #include "QtWebPageEventHandler.h" |
| #include "UtilsQt.h" |
| #include "WebBackForwardList.h" |
| #include "WebPageGroup.h" |
| #include "WebPreferences.h" |
| |
| #include "qquickwebpage_p_p.h" |
| #include "qquickwebview_p_p.h" |
| #include "qwebdownloaditem_p_p.h" |
| #include "qwebnavigationhistory_p.h" |
| #include "qwebnavigationhistory_p_p.h" |
| #include "qwebpreferences_p.h" |
| #include "qwebpreferences_p_p.h" |
| #include "qwebviewportinfo_p.h" |
| |
| #include <JavaScriptCore/InitializeThreading.h> |
| #include <QDeclarativeEngine> |
| #include <QFileDialog> |
| #include <QtQuick/QQuickCanvas> |
| #include <WKOpenPanelResultListener.h> |
| #include <wtf/text/WTFString.h> |
| |
| QQuickWebViewPrivate::QQuickWebViewPrivate(QQuickWebView* viewport) |
| : q_ptr(viewport) |
| , alertDialog(0) |
| , confirmDialog(0) |
| , promptDialog(0) |
| , itemSelector(0) |
| , postTransitionState(adoptPtr(new PostTransitionState(this))) |
| , isTransitioningToNewPage(false) |
| , pageIsSuspended(false) |
| , m_navigatorQtObjectEnabled(false) |
| { |
| viewport->setFlags(QQuickItem::ItemClipsChildrenToShape); |
| QObject::connect(viewport, SIGNAL(visibleChanged()), viewport, SLOT(_q_onVisibleChanged())); |
| pageView.reset(new QQuickWebPage(viewport)); |
| } |
| |
| QQuickWebViewPrivate::~QQuickWebViewPrivate() |
| { |
| if (interactionEngine) |
| interactionEngine->disconnect(); |
| webPageProxy->close(); |
| } |
| |
| // Note: we delay this initialization to make sure that QQuickWebView has its d-ptr in-place. |
| void QQuickWebViewPrivate::initialize(WKContextRef contextRef, WKPageGroupRef pageGroupRef) |
| { |
| RefPtr<WebPageGroup> pageGroup; |
| if (pageGroupRef) |
| pageGroup = toImpl(pageGroupRef); |
| else |
| pageGroup = WebPageGroup::create(); |
| |
| context = contextRef ? QtWebContext::create(toImpl(contextRef)) : QtWebContext::defaultContext(); |
| webPageProxy = context->createWebPage(&pageClient, pageGroup.get()); |
| |
| QQuickWebPagePrivate* const pageViewPrivate = pageView.data()->d; |
| pageViewPrivate->initialize(webPageProxy.get()); |
| |
| pageLoadClient.reset(new QtWebPageLoadClient(toAPI(webPageProxy.get()), q_ptr)); |
| pagePolicyClient.reset(new QtWebPagePolicyClient(toAPI(webPageProxy.get()), q_ptr)); |
| pageUIClient.reset(new QtWebPageUIClient(toAPI(webPageProxy.get()), q_ptr)); |
| navigationHistory = adoptPtr(QWebNavigationHistoryPrivate::createHistory(toAPI(webPageProxy.get()))); |
| |
| RefPtr<QtWebContext> context = QtWebContext::defaultContext(); |
| QtWebIconDatabaseClient* iconDatabase = context->iconDatabase(); |
| QObject::connect(iconDatabase, SIGNAL(iconChangedForPageURL(QUrl, QUrl)), q_ptr, SLOT(_q_onIconChangedForPageURL(QUrl, QUrl))); |
| QObject::connect(q_ptr, SIGNAL(urlChanged(QUrl)), iconDatabase, SLOT(requestIconForPageURL(QUrl))); |
| |
| // Any page setting should preferrable be set before creating the page. |
| setUseTraditionalDesktopBehaviour(false); |
| webPageProxy->pageGroup()->preferences()->setAcceleratedCompositingEnabled(true); |
| |
| pageClient.initialize(q_ptr, pageViewPrivate->eventHandler.data(), &undoController); |
| webPageProxy->initializeWebPage(); |
| |
| // Trigger setting of correct visibility flags after everything was allocated and initialized. |
| _q_onVisibleChanged(); |
| } |
| |
| void QQuickWebViewPrivate::enableMouseEvents() |
| { |
| Q_Q(QQuickWebView); |
| q->setAcceptedMouseButtons(Qt::MouseButtonMask); |
| q->setAcceptHoverEvents(true); |
| pageView->setAcceptedMouseButtons(Qt::MouseButtonMask); |
| pageView->setAcceptHoverEvents(true); |
| } |
| |
| void QQuickWebViewPrivate::disableMouseEvents() |
| { |
| Q_Q(QQuickWebView); |
| q->setAcceptedMouseButtons(Qt::NoButton); |
| q->setAcceptHoverEvents(false); |
| pageView->setAcceptedMouseButtons(Qt::NoButton); |
| pageView->setAcceptHoverEvents(false); |
| } |
| |
| void QQuickWebViewPrivate::initializeDesktop(QQuickWebView* viewport) |
| { |
| if (interactionEngine) { |
| QObject::disconnect(interactionEngine.data(), SIGNAL(contentSuspendRequested()), viewport, SLOT(_q_suspend())); |
| QObject::disconnect(interactionEngine.data(), SIGNAL(contentResumeRequested()), viewport, SLOT(_q_resume())); |
| QObject::disconnect(interactionEngine.data(), SIGNAL(viewportTrajectoryVectorChanged(const QPointF&)), viewport, SLOT(_q_viewportTrajectoryVectorChanged(const QPointF&))); |
| } |
| interactionEngine.reset(0); |
| pageView->d->eventHandler->setViewportInteractionEngine(0); |
| enableMouseEvents(); |
| } |
| |
| void QQuickWebViewPrivate::initializeTouch(QQuickWebView* viewport) |
| { |
| interactionEngine.reset(new QtViewportInteractionEngine(viewport, pageView.data())); |
| pageView->d->eventHandler->setViewportInteractionEngine(interactionEngine.data()); |
| disableMouseEvents(); |
| QObject::connect(interactionEngine.data(), SIGNAL(contentSuspendRequested()), viewport, SLOT(_q_suspend())); |
| QObject::connect(interactionEngine.data(), SIGNAL(contentResumeRequested()), viewport, SLOT(_q_resume())); |
| QObject::connect(interactionEngine.data(), SIGNAL(viewportTrajectoryVectorChanged(const QPointF&)), viewport, SLOT(_q_viewportTrajectoryVectorChanged(const QPointF&))); |
| updateViewportSize(); |
| } |
| |
| void QQuickWebViewPrivate::loadDidCommit() |
| { |
| // Due to entering provisional load before committing, we |
| // might actually be suspended here. |
| |
| if (useTraditionalDesktopBehaviour) |
| return; |
| |
| isTransitioningToNewPage = true; |
| } |
| |
| void QQuickWebViewPrivate::didFinishFirstNonEmptyLayout() |
| { |
| if (useTraditionalDesktopBehaviour) |
| return; |
| |
| if (!pageIsSuspended) { |
| isTransitioningToNewPage = false; |
| postTransitionState->apply(); |
| } |
| } |
| |
| void QQuickWebViewPrivate::_q_onIconChangedForPageURL(const QUrl& pageURL, const QUrl& iconURL) |
| { |
| Q_Q(QQuickWebView); |
| if (q->url() != pageURL) |
| return; |
| |
| setIcon(iconURL); |
| } |
| |
| void QQuickWebViewPrivate::_q_suspend() |
| { |
| pageIsSuspended = true; |
| } |
| |
| void QQuickWebViewPrivate::_q_resume() |
| { |
| pageIsSuspended = false; |
| |
| if (isTransitioningToNewPage) { |
| isTransitioningToNewPage = false; |
| postTransitionState->apply(); |
| } |
| |
| updateVisibleContentRectAndScale(); |
| } |
| |
| void QQuickWebViewPrivate::didChangeContentsSize(const QSize& newSize) |
| { |
| Q_Q(QQuickWebView); |
| if (useTraditionalDesktopBehaviour) |
| return; |
| |
| // FIXME: We probably want to handle suspend here as well |
| if (isTransitioningToNewPage) { |
| postTransitionState->contentsSize = newSize; |
| return; |
| } |
| |
| pageView->setWidth(newSize.width()); |
| pageView->setHeight(newSize.height()); |
| |
| q->m_experimental->viewportInfo()->didUpdateContentsSize(); |
| } |
| |
| void QQuickWebViewPrivate::didChangeViewportProperties(const WebCore::ViewportArguments& args) |
| { |
| if (useTraditionalDesktopBehaviour) |
| return; |
| |
| viewportArguments = args; |
| |
| if (isTransitioningToNewPage) |
| return; |
| |
| interactionEngine->applyConstraints(computeViewportConstraints()); |
| } |
| |
| void QQuickWebViewPrivate::didChangeBackForwardList() |
| { |
| navigationHistory->d->reset(); |
| } |
| |
| void QQuickWebViewPrivate::pageDidRequestScroll(const QPoint& pos) |
| { |
| if (useTraditionalDesktopBehaviour) |
| return; |
| |
| if (isTransitioningToNewPage) { |
| postTransitionState->position = pos; |
| return; |
| } |
| |
| interactionEngine->pagePositionRequest(pos); |
| } |
| |
| void QQuickWebViewPrivate::processDidCrash() |
| { |
| emit q_ptr->navigationStateChanged(); |
| pageView->d->eventHandler->resetGestureRecognizers(); |
| WebCore::KURL url(WebCore::ParsedURLString, webPageProxy->urlAtProcessExit()); |
| qWarning("WARNING: The web process experienced a crash on '%s'.", qPrintable(QUrl(url).toString(QUrl::RemoveUserInfo))); |
| } |
| |
| void QQuickWebViewPrivate::didRelaunchProcess() |
| { |
| emit q_ptr->navigationStateChanged(); |
| qWarning("WARNING: The web process has been successfully restarted."); |
| pageView->d->setDrawingAreaSize(viewSize()); |
| } |
| |
| PassOwnPtr<DrawingAreaProxy> QQuickWebViewPrivate::createDrawingAreaProxy() |
| { |
| return DrawingAreaProxyImpl::create(webPageProxy.get()); |
| } |
| |
| void QQuickWebViewPrivate::handleDownloadRequest(DownloadProxy* download) |
| { |
| Q_Q(QQuickWebView); |
| // This function is responsible for hooking up a DownloadProxy to our API layer |
| // by creating a QWebDownloadItem. It will then wait for the QWebDownloadItem to be |
| // ready (filled with the ResourceResponse information) so we can pass it through to |
| // our WebViews. |
| QWebDownloadItem* downloadItem = new QWebDownloadItem(); |
| downloadItem->d->downloadProxy = download; |
| |
| q->connect(downloadItem->d, SIGNAL(receivedResponse(QWebDownloadItem*)), q, SLOT(_q_onReceivedResponseFromDownload(QWebDownloadItem*))); |
| context->downloadManager()->addDownload(download, downloadItem); |
| } |
| |
| void QQuickWebViewPrivate::updateVisibleContentRectAndScale() |
| { |
| DrawingAreaProxy* drawingArea = webPageProxy->drawingArea(); |
| if (!drawingArea) |
| return; |
| |
| Q_Q(QQuickWebView); |
| const QRectF visibleRectInPageViewCoordinates = q->mapRectToItem(pageView.data(), q->boundingRect()).intersected(pageView->boundingRect()); |
| float scale = pageView->scale(); |
| |
| QRect alignedVisibleContentRect = visibleRectInPageViewCoordinates.toAlignedRect(); |
| drawingArea->setVisibleContentsRectAndScale(alignedVisibleContentRect, scale); |
| |
| // FIXME: Once we support suspend and resume, this should be delayed until the page is active if the page is suspended. |
| webPageProxy->setFixedVisibleContentRect(alignedVisibleContentRect); |
| q->m_experimental->viewportInfo()->didUpdateCurrentScale(); |
| } |
| |
| void QQuickWebViewPrivate::_q_viewportTrajectoryVectorChanged(const QPointF& trajectoryVector) |
| { |
| DrawingAreaProxy* drawingArea = webPageProxy->drawingArea(); |
| if (!drawingArea) |
| return; |
| drawingArea->setVisibleContentRectTrajectoryVector(trajectoryVector); |
| } |
| |
| void QQuickWebViewPrivate::_q_onVisibleChanged() |
| { |
| webPageProxy->viewStateDidChange(WebPageProxy::ViewIsVisible); |
| } |
| |
| void QQuickWebViewPrivate::_q_onReceivedResponseFromDownload(QWebDownloadItem* downloadItem) |
| { |
| // Now that our downloadItem has everything we need we can emit downloadRequested. |
| if (!downloadItem) |
| return; |
| |
| Q_Q(QQuickWebView); |
| QDeclarativeEngine::setObjectOwnership(downloadItem, QDeclarativeEngine::JavaScriptOwnership); |
| emit q->experimental()->downloadRequested(downloadItem); |
| } |
| |
| void QQuickWebViewPrivate::updateViewportSize() |
| { |
| Q_Q(QQuickWebView); |
| QSize viewportSize = q->boundingRect().size().toSize(); |
| |
| if (viewportSize.isEmpty()) |
| return; |
| |
| // Let the WebProcess know about the new viewport size, so that |
| // it can resize the content accordingly. |
| webPageProxy->setViewportSize(viewportSize); |
| |
| interactionEngine->applyConstraints(computeViewportConstraints()); |
| updateVisibleContentRectAndScale(); |
| } |
| |
| void QQuickWebViewPrivate::PostTransitionState::apply() |
| { |
| p->interactionEngine->reset(); |
| p->interactionEngine->applyConstraints(p->computeViewportConstraints()); |
| p->interactionEngine->pagePositionRequest(position); |
| |
| if (contentsSize.isValid()) { |
| p->pageView->setWidth(contentsSize.width()); |
| p->pageView->setHeight(contentsSize.height()); |
| p->q_ptr->experimental()->viewportInfo()->didUpdateContentsSize(); |
| } |
| |
| position = QPoint(); |
| contentsSize = QSize(); |
| } |
| |
| QtViewportInteractionEngine::Constraints QQuickWebViewPrivate::computeViewportConstraints() |
| { |
| Q_Q(QQuickWebView); |
| |
| QtViewportInteractionEngine::Constraints newConstraints; |
| QSize availableSize = q->boundingRect().size().toSize(); |
| |
| // Return default values for zero sized viewport. |
| if (availableSize.isEmpty()) |
| return newConstraints; |
| |
| WebPreferences* wkPrefs = webPageProxy->pageGroup()->preferences(); |
| |
| // FIXME: Remove later; Hardcode some values for now to make sure the DPI adjustment is being tested. |
| wkPrefs->setDeviceDPI(240); |
| wkPrefs->setDeviceWidth(480); |
| wkPrefs->setDeviceHeight(720); |
| |
| int minimumLayoutFallbackWidth = qMax<int>(wkPrefs->layoutFallbackWidth(), availableSize.width()); |
| |
| WebCore::ViewportAttributes attr = WebCore::computeViewportAttributes(viewportArguments, minimumLayoutFallbackWidth, wkPrefs->deviceWidth(), wkPrefs->deviceHeight(), wkPrefs->deviceDPI(), availableSize); |
| WebCore::restrictMinimumScaleFactorToViewportSize(attr, availableSize); |
| WebCore::restrictScaleFactorToInitialScaleIfNotUserScalable(attr); |
| |
| newConstraints.initialScale = attr.initialScale; |
| newConstraints.minimumScale = attr.minimumScale; |
| newConstraints.maximumScale = attr.maximumScale; |
| newConstraints.devicePixelRatio = attr.devicePixelRatio; |
| newConstraints.isUserScalable = !!attr.userScalable; |
| newConstraints.layoutSize = attr.layoutSize; |
| |
| q->m_experimental->viewportInfo()->didUpdateViewportConstraints(); |
| |
| return newConstraints; |
| } |
| |
| void QQuickWebViewPrivate::runJavaScriptAlert(const QString& alertText) |
| { |
| if (!alertDialog) |
| return; |
| |
| Q_Q(QQuickWebView); |
| QtDialogRunner dialogRunner; |
| if (!dialogRunner.initForAlert(alertDialog, q, alertText)) |
| return; |
| setViewInAttachedProperties(dialogRunner.dialog()); |
| |
| disableMouseEvents(); |
| dialogRunner.exec(); |
| enableMouseEvents(); |
| } |
| |
| bool QQuickWebViewPrivate::runJavaScriptConfirm(const QString& message) |
| { |
| if (!confirmDialog) |
| return true; |
| |
| Q_Q(QQuickWebView); |
| QtDialogRunner dialogRunner; |
| if (!dialogRunner.initForConfirm(confirmDialog, q, message)) |
| return true; |
| setViewInAttachedProperties(dialogRunner.dialog()); |
| |
| disableMouseEvents(); |
| dialogRunner.exec(); |
| enableMouseEvents(); |
| |
| return dialogRunner.wasAccepted(); |
| } |
| |
| QString QQuickWebViewPrivate::runJavaScriptPrompt(const QString& message, const QString& defaultValue, bool& ok) |
| { |
| if (!promptDialog) { |
| ok = true; |
| return defaultValue; |
| } |
| |
| Q_Q(QQuickWebView); |
| QtDialogRunner dialogRunner; |
| if (!dialogRunner.initForPrompt(promptDialog, q, message, defaultValue)) { |
| ok = true; |
| return defaultValue; |
| } |
| setViewInAttachedProperties(dialogRunner.dialog()); |
| |
| disableMouseEvents(); |
| dialogRunner.exec(); |
| enableMouseEvents(); |
| |
| ok = dialogRunner.wasAccepted(); |
| return dialogRunner.result(); |
| } |
| |
| void QQuickWebViewPrivate::chooseFiles(WKOpenPanelResultListenerRef listenerRef, const QStringList& selectedFileNames, QtWebPageUIClient::FileChooserType type) |
| { |
| #ifndef QT_NO_FILEDIALOG |
| Q_Q(QQuickWebView); |
| openPanelResultListener = listenerRef; |
| |
| // Qt does not support multiple files suggestion, so we get just the first suggestion. |
| QString selectedFileName; |
| if (!selectedFileNames.isEmpty()) |
| selectedFileName = selectedFileNames.at(0); |
| |
| Q_ASSERT(!fileDialog); |
| |
| QWindow* window = q->canvas(); |
| if (!window) |
| return; |
| |
| fileDialog = new QFileDialog(0, QString(), selectedFileName); |
| fileDialog->window()->winId(); // Ensure that the dialog has a window |
| Q_ASSERT(fileDialog->window()->windowHandle()); |
| fileDialog->window()->windowHandle()->setTransientParent(window); |
| |
| fileDialog->open(q, SLOT(_q_onOpenPanelFilesSelected())); |
| |
| q->connect(fileDialog, SIGNAL(finished(int)), SLOT(_q_onOpenPanelFinished(int))); |
| #endif |
| } |
| |
| void QQuickWebViewPrivate::_q_onOpenPanelFilesSelected() |
| { |
| const QStringList fileList = fileDialog->selectedFiles(); |
| Vector<RefPtr<APIObject> > wkFiles(fileList.size()); |
| |
| for (unsigned i = 0; i < fileList.size(); ++i) |
| wkFiles[i] = WebURL::create(QUrl::fromLocalFile(fileList.at(i)).toString()); |
| |
| WKOpenPanelResultListenerChooseFiles(openPanelResultListener, toAPI(ImmutableArray::adopt(wkFiles).leakRef())); |
| } |
| |
| void QQuickWebViewPrivate::_q_onOpenPanelFinished(int result) |
| { |
| if (result == QDialog::Rejected) |
| WKOpenPanelResultListenerCancel(openPanelResultListener); |
| |
| fileDialog->deleteLater(); |
| fileDialog = 0; |
| } |
| |
| void QQuickWebViewPrivate::setUseTraditionalDesktopBehaviour(bool enable) |
| { |
| Q_Q(QQuickWebView); |
| |
| // Do not guard, testing for the same value, as we call this from the constructor. |
| |
| webPageProxy->setUseFixedLayout(!enable); |
| |
| useTraditionalDesktopBehaviour = enable; |
| if (useTraditionalDesktopBehaviour) |
| initializeDesktop(q); |
| else |
| initializeTouch(q); |
| } |
| |
| void QQuickWebViewPrivate::setViewInAttachedProperties(QObject* object) |
| { |
| Q_Q(QQuickWebView); |
| QQuickWebViewAttached* attached = static_cast<QQuickWebViewAttached*>(qmlAttachedPropertiesObject<QQuickWebView>(object)); |
| attached->setView(q); |
| } |
| |
| void QQuickWebViewPrivate::setIcon(const QUrl& iconURL) |
| { |
| Q_Q(QQuickWebView); |
| if (m_iconURL == iconURL) |
| return; |
| |
| String oldPageURL = QUrl::fromPercentEncoding(m_iconURL.encodedFragment()); |
| String newPageURL = webPageProxy->mainFrame()->url(); |
| |
| if (oldPageURL != newPageURL) { |
| RefPtr<QtWebContext> context = QtWebContext::defaultContext(); |
| QtWebIconDatabaseClient* iconDatabase = context->iconDatabase(); |
| if (!oldPageURL.isEmpty()) |
| iconDatabase->releaseIconForPageURL(oldPageURL); |
| |
| if (!newPageURL.isEmpty()) |
| iconDatabase->retainIconForPageURL(newPageURL); |
| } |
| |
| m_iconURL = iconURL; |
| emit q->iconChanged(m_iconURL); |
| } |
| |
| bool QQuickWebViewPrivate::navigatorQtObjectEnabled() const |
| { |
| return m_navigatorQtObjectEnabled; |
| } |
| |
| void QQuickWebViewPrivate::setNavigatorQtObjectEnabled(bool enabled) |
| { |
| ASSERT(enabled != m_navigatorQtObjectEnabled); |
| // FIXME: Currently we have to keep this information in both processes and the setting is asynchronous. |
| m_navigatorQtObjectEnabled = enabled; |
| context->setNavigatorQtObjectEnabled(webPageProxy.get(), enabled); |
| } |
| |
| WebCore::IntSize QQuickWebViewPrivate::viewSize() const |
| { |
| return WebCore::IntSize(pageView->width(), pageView->height()); |
| } |
| |
| void QQuickWebViewPrivate::didReceiveMessageFromNavigatorQtObject(const String& message) |
| { |
| QVariantMap variantMap; |
| variantMap.insert(QLatin1String("data"), QString(message)); |
| variantMap.insert(QLatin1String("origin"), q_ptr->url()); |
| emit q_ptr->experimental()->messageReceived(variantMap); |
| } |
| |
| /*! |
| \qmlsignal WebView::onNavigationRequested(request) |
| |
| This signal is emitted for every navigation request. The request object contains url, button and modifiers properties |
| describing the navigation action, e.g. "a middle click with shift key pressed to 'http://qt-project.org'". |
| |
| The navigation will be accepted by default. To change that, one can set the action property to WebView.IgnoreRequest to reject |
| the request or WebView.DownloadRequest to trigger a download instead of navigating to the url. |
| |
| The request object cannot be used after the signal handler function ends. |
| */ |
| |
| QQuickWebViewAttached::QQuickWebViewAttached(QObject* object) |
| : QObject(object) |
| , m_view(0) |
| { |
| |
| } |
| |
| void QQuickWebViewAttached::setView(QQuickWebView* view) |
| { |
| if (m_view == view) |
| return; |
| m_view = view; |
| emit viewChanged(); |
| } |
| |
| QQuickWebViewExperimental::QQuickWebViewExperimental(QQuickWebView *webView) |
| : QObject(webView) |
| , q_ptr(webView) |
| , d_ptr(webView->d_ptr.data()) |
| , m_viewportInfo(new QWebViewportInfo(webView->d_ptr.data(), this)) |
| { |
| } |
| |
| QQuickWebViewExperimental::~QQuickWebViewExperimental() |
| { |
| } |
| |
| void QQuickWebViewExperimental::setUseTraditionalDesktopBehaviour(bool enable) |
| { |
| Q_D(QQuickWebView); |
| |
| if (enable == d->useTraditionalDesktopBehaviour) |
| return; |
| |
| d->setUseTraditionalDesktopBehaviour(enable); |
| } |
| |
| void QQuickWebViewExperimental::postMessage(const QString& message) |
| { |
| Q_D(QQuickWebView); |
| d->context->postMessageToNavigatorQtObject(d->webPageProxy.get(), message); |
| } |
| |
| QDeclarativeComponent* QQuickWebViewExperimental::alertDialog() const |
| { |
| Q_D(const QQuickWebView); |
| return d->alertDialog; |
| } |
| |
| void QQuickWebViewExperimental::setAlertDialog(QDeclarativeComponent* alertDialog) |
| { |
| Q_D(QQuickWebView); |
| if (d->alertDialog == alertDialog) |
| return; |
| d->alertDialog = alertDialog; |
| emit alertDialogChanged(); |
| } |
| |
| QDeclarativeComponent* QQuickWebViewExperimental::confirmDialog() const |
| { |
| Q_D(const QQuickWebView); |
| return d->confirmDialog; |
| } |
| |
| void QQuickWebViewExperimental::setConfirmDialog(QDeclarativeComponent* confirmDialog) |
| { |
| Q_D(QQuickWebView); |
| if (d->confirmDialog == confirmDialog) |
| return; |
| d->confirmDialog = confirmDialog; |
| emit confirmDialogChanged(); |
| } |
| |
| QWebNavigationHistory* QQuickWebViewExperimental::navigationHistory() const |
| { |
| return d_ptr->navigationHistory.get(); |
| } |
| |
| QDeclarativeComponent* QQuickWebViewExperimental::promptDialog() const |
| { |
| Q_D(const QQuickWebView); |
| return d->promptDialog; |
| } |
| |
| QWebPreferences* QQuickWebViewExperimental::preferences() const |
| { |
| QQuickWebViewPrivate* const d = d_ptr; |
| if (!d->preferences) |
| d->preferences = adoptPtr(QWebPreferencesPrivate::createPreferences(d)); |
| return d->preferences.get(); |
| } |
| |
| void QQuickWebViewExperimental::setPromptDialog(QDeclarativeComponent* promptDialog) |
| { |
| Q_D(QQuickWebView); |
| if (d->promptDialog == promptDialog) |
| return; |
| d->promptDialog = promptDialog; |
| emit promptDialogChanged(); |
| } |
| |
| QDeclarativeComponent* QQuickWebViewExperimental::itemSelector() const |
| { |
| Q_D(const QQuickWebView); |
| return d->itemSelector; |
| } |
| |
| void QQuickWebViewExperimental::setItemSelector(QDeclarativeComponent* itemSelector) |
| { |
| Q_D(QQuickWebView); |
| if (d->itemSelector == itemSelector) |
| return; |
| d->itemSelector = itemSelector; |
| emit itemSelectorChanged(); |
| } |
| |
| bool QQuickWebViewExperimental::useTraditionalDesktopBehaviour() const |
| { |
| Q_D(const QQuickWebView); |
| return d->useTraditionalDesktopBehaviour; |
| } |
| |
| void QQuickWebViewExperimental::goForwardTo(int index) |
| { |
| d_ptr->navigationHistory->d->goForwardTo(index); |
| } |
| |
| void QQuickWebViewExperimental::goBackTo(int index) |
| { |
| d_ptr->navigationHistory->d->goBackTo(index); |
| } |
| |
| QWebViewportInfo* QQuickWebViewExperimental::viewportInfo() |
| { |
| return m_viewportInfo; |
| } |
| |
| QQuickWebPage* QQuickWebViewExperimental::page() |
| { |
| return q_ptr->page(); |
| } |
| |
| QQuickWebView::QQuickWebView(QQuickItem* parent) |
| : QQuickItem(parent) |
| , d_ptr(new QQuickWebViewPrivate(this)) |
| , m_experimental(new QQuickWebViewExperimental(this)) |
| { |
| Q_D(QQuickWebView); |
| d->initialize(); |
| d->initializeTouch(this); |
| } |
| |
| QQuickWebView::QQuickWebView(WKContextRef contextRef, WKPageGroupRef pageGroupRef, QQuickItem* parent) |
| : QQuickItem(parent) |
| , d_ptr(new QQuickWebViewPrivate(this)) |
| , m_experimental(new QQuickWebViewExperimental(this)) |
| { |
| Q_D(QQuickWebView); |
| d->initialize(contextRef, pageGroupRef); |
| } |
| |
| QQuickWebView::~QQuickWebView() |
| { |
| } |
| |
| QQuickWebPage* QQuickWebView::page() |
| { |
| Q_D(QQuickWebView); |
| return d->pageView.data(); |
| } |
| |
| void QQuickWebView::load(const QUrl& url) |
| { |
| Q_D(QQuickWebView); |
| d->webPageProxy->loadURL(url.toString()); |
| } |
| |
| void QQuickWebView::goBack() |
| { |
| Q_D(QQuickWebView); |
| d->webPageProxy->goBack(); |
| } |
| |
| void QQuickWebView::goForward() |
| { |
| Q_D(QQuickWebView); |
| d->webPageProxy->goForward(); |
| } |
| |
| void QQuickWebView::stop() |
| { |
| Q_D(QQuickWebView); |
| d->webPageProxy->stopLoading(); |
| } |
| |
| void QQuickWebView::reload() |
| { |
| Q_D(QQuickWebView); |
| const bool reloadFromOrigin = true; |
| d->webPageProxy->reload(reloadFromOrigin); |
| } |
| |
| QUrl QQuickWebView::url() const |
| { |
| Q_D(const QQuickWebView); |
| RefPtr<WebFrameProxy> mainFrame = d->webPageProxy->mainFrame(); |
| if (!mainFrame) |
| return QUrl(); |
| return QUrl(QString(mainFrame->url())); |
| } |
| |
| QUrl QQuickWebView::icon() const |
| { |
| Q_D(const QQuickWebView); |
| return d->m_iconURL; |
| } |
| |
| int QQuickWebView::loadProgress() const |
| { |
| Q_D(const QQuickWebView); |
| return d->pageLoadClient->loadProgress(); |
| } |
| |
| bool QQuickWebView::canGoBack() const |
| { |
| Q_D(const QQuickWebView); |
| return d->webPageProxy->canGoBack(); |
| } |
| |
| bool QQuickWebView::canGoForward() const |
| { |
| Q_D(const QQuickWebView); |
| return d->webPageProxy->canGoForward(); |
| } |
| |
| bool QQuickWebView::loading() const |
| { |
| Q_D(const QQuickWebView); |
| RefPtr<WebKit::WebFrameProxy> mainFrame = d->webPageProxy->mainFrame(); |
| return mainFrame && !(WebFrameProxy::LoadStateFinished == mainFrame->loadState()); |
| } |
| |
| bool QQuickWebView::canReload() const |
| { |
| Q_D(const QQuickWebView); |
| RefPtr<WebKit::WebFrameProxy> mainFrame = d->webPageProxy->mainFrame(); |
| if (mainFrame) |
| return (WebFrameProxy::LoadStateFinished == mainFrame->loadState()); |
| return d->webPageProxy->backForwardList()->currentItem(); |
| } |
| |
| QString QQuickWebView::title() const |
| { |
| Q_D(const QQuickWebView); |
| return d->webPageProxy->pageTitle(); |
| } |
| |
| QQuickWebViewExperimental* QQuickWebView::experimental() const |
| { |
| return m_experimental; |
| } |
| |
| QQuickWebViewAttached* QQuickWebView::qmlAttachedProperties(QObject* object) |
| { |
| return new QQuickWebViewAttached(object); |
| } |
| |
| void QQuickWebView::platformInitialize() |
| { |
| JSC::initializeThreading(); |
| WTF::initializeMainThread(); |
| } |
| |
| void QQuickWebView::geometryChanged(const QRectF& newGeometry, const QRectF& oldGeometry) |
| { |
| Q_D(QQuickWebView); |
| QQuickItem::geometryChanged(newGeometry, oldGeometry); |
| if (newGeometry.size() != oldGeometry.size()) { |
| if (d->useTraditionalDesktopBehaviour) { |
| d->pageView->setWidth(newGeometry.width()); |
| d->pageView->setHeight(newGeometry.height()); |
| } else |
| d->updateViewportSize(); |
| } |
| } |
| |
| void QQuickWebView::focusInEvent(QFocusEvent* event) |
| { |
| Q_D(QQuickWebView); |
| d->pageView->event(event); |
| } |
| |
| void QQuickWebView::focusOutEvent(QFocusEvent* event) |
| { |
| Q_D(QQuickWebView); |
| d->pageView->event(event); |
| } |
| |
| WKPageRef QQuickWebView::pageRef() const |
| { |
| Q_D(const QQuickWebView); |
| return toAPI(d->webPageProxy.get()); |
| } |
| |
| /*! |
| Loads the specified \a html as the content of the web view. |
| |
| External objects such as stylesheets or images referenced in the HTML |
| document are located relative to \a baseUrl. |
| |
| \sa load() |
| */ |
| void QQuickWebView::loadHtml(const QString& html, const QUrl& baseUrl) |
| { |
| Q_D(QQuickWebView); |
| d->webPageProxy->loadHTMLString(html, baseUrl.toString()); |
| } |
| |
| #include "moc_qquickwebview_p.cpp" |