blob: 1f0ad14316429c0cb25c8f7d63fdb6ac53044fe1 [file] [log] [blame] [edit]
/*
* 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 "QtWebPagePolicyClient.h"
#include "WKFrame.h"
#include "WKURLQt.h"
#include "qquickwebview_p_p.h"
#include "qwebnavigationrequest_p.h"
#include <QtCore/QObject>
#include <WKFramePolicyListener.h>
#include <WKRetainPtr.h>
#include <WKURLRequest.h>
namespace WebKit {
QtWebPagePolicyClient::QtWebPagePolicyClient(WKPageRef pageRef, QQuickWebView* webView)
: m_webView(webView)
{
WKPagePolicyClient policyClient;
memset(&policyClient, 0, sizeof(WKPagePolicyClient));
policyClient.version = kWKPagePolicyClientCurrentVersion;
policyClient.clientInfo = this;
policyClient.decidePolicyForNavigationAction = decidePolicyForNavigationAction;
policyClient.decidePolicyForResponse = decidePolicyForResponse;
WKPageSetPagePolicyClient(pageRef, &policyClient);
}
void QtWebPagePolicyClient::decidePolicyForNavigationAction(const QUrl& url, Qt::MouseButton mouseButton, Qt::KeyboardModifiers keyboardModifiers, QQuickWebView::NavigationType navigationType, WKFramePolicyListenerRef listener)
{
// NOTE: even though the C API (and the WebKit2 IPC) supports an asynchronous answer, this is not currently working.
// We are expected to call the listener immediately. See the patch for https://bugs.webkit.org/show_bug.cgi?id=53785.
QWebNavigationRequest navigationRequest(url, mouseButton, keyboardModifiers, navigationType);
emit m_webView->navigationRequested(&navigationRequest);
switch (navigationRequest.action()) {
case QQuickWebView::IgnoreRequest:
WKFramePolicyListenerIgnore(listener);
return;
case QQuickWebViewExperimental::DownloadRequest:
WKFramePolicyListenerDownload(listener);
return;
case QQuickWebView::AcceptRequest:
WKFramePolicyListenerUse(listener);
return;
}
ASSERT_NOT_REACHED();
}
static inline QtWebPagePolicyClient* toQtWebPagePolicyClient(const void* clientInfo)
{
ASSERT(clientInfo);
return reinterpret_cast<QtWebPagePolicyClient*>(const_cast<void*>(clientInfo));
}
static Qt::MouseButton toQtMouseButton(WKEventMouseButton button)
{
switch (button) {
case kWKEventMouseButtonLeftButton:
return Qt::LeftButton;
case kWKEventMouseButtonMiddleButton:
return Qt::MiddleButton;
case kWKEventMouseButtonRightButton:
return Qt::RightButton;
case kWKEventMouseButtonNoButton:
return Qt::NoButton;
}
ASSERT_NOT_REACHED();
return Qt::NoButton;
}
static Qt::KeyboardModifiers toQtKeyboardModifiers(WKEventModifiers modifiers)
{
Qt::KeyboardModifiers qtModifiers = Qt::NoModifier;
if (modifiers & kWKEventModifiersShiftKey)
qtModifiers |= Qt::ShiftModifier;
if (modifiers & kWKEventModifiersControlKey)
qtModifiers |= Qt::ControlModifier;
if (modifiers & kWKEventModifiersAltKey)
qtModifiers |= Qt::AltModifier;
if (modifiers & kWKEventModifiersMetaKey)
qtModifiers |= Qt::MetaModifier;
return qtModifiers;
}
static QQuickWebView::NavigationType toQuickWebViewNavigationType(WKFrameNavigationType navigationType)
{
switch (navigationType) {
case kWKFrameNavigationTypeLinkClicked:
return QQuickWebView::LinkClickedNavigation;
case kWKFrameNavigationTypeFormSubmitted:
return QQuickWebView::FormSubmittedNavigation;
case kWKFrameNavigationTypeBackForward:
return QQuickWebView::BackForwardNavigation;
case kWKFrameNavigationTypeReload:
return QQuickWebView::ReloadNavigation;
case kWKFrameNavigationTypeFormResubmitted:
return QQuickWebView::FormResubmittedNavigation;
case kWKFrameNavigationTypeOther:
return QQuickWebView::OtherNavigation;
}
ASSERT_NOT_REACHED();
return QQuickWebView::OtherNavigation;
}
void QtWebPagePolicyClient::decidePolicyForNavigationAction(WKPageRef, WKFrameRef frame, WKFrameNavigationType navigationType, WKEventModifiers modifiers, WKEventMouseButton mouseButton, WKURLRequestRef request, WKFramePolicyListenerRef listener, WKTypeRef, const void* clientInfo)
{
WKRetainPtr<WKURLRef> frameURL(AdoptWK, WKFrameCopyURL(frame));
WKRetainPtr<WKURLRef> requestURL(AdoptWK, WKURLRequestCopyURL(request));
QUrl qUrl = WKURLCopyQUrl(requestURL.get());
toQtWebPagePolicyClient(clientInfo)->decidePolicyForNavigationAction(qUrl, toQtMouseButton(mouseButton), toQtKeyboardModifiers(modifiers), toQuickWebViewNavigationType(navigationType), listener);
}
void QtWebPagePolicyClient::decidePolicyForResponse(WKPageRef page, WKFrameRef frame, WKURLResponseRef response, WKURLRequestRef, WKFramePolicyListenerRef listener, WKTypeRef, const void*)
{
String type = toImpl(response)->resourceResponse().mimeType();
type.makeLower();
bool canShowMIMEType = toImpl(frame)->canShowMIMEType(type);
if (WKPageGetMainFrame(page) == frame) {
if (canShowMIMEType) {
WKFramePolicyListenerUse(listener);
return;
}
// If we can't use (show) it then we should download it.
WKFramePolicyListenerDownload(listener);
return;
}
// We should ignore downloadable top-level content for subframes, with an exception for text/xml and application/xml so we can still support Acid3 test.
// It makes the browser intentionally behave differently when it comes to text(application)/xml content in subframes vs. mainframe.
if (!canShowMIMEType && !(type == "text/xml" || type == "application/xml")) {
WKFramePolicyListenerIgnore(listener);
return;
}
WKFramePolicyListenerUse(listener);
}
} // namespace WebKit