1/* 2 * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies) 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Library General Public 6 * License as published by the Free Software Foundation; either 7 * version 2 of the License, or (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Library General Public License for more details. 13 * 14 * You should have received a copy of the GNU Library General Public License 15 * along with this program; see the file COPYING.LIB. If not, write to 16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 17 * Boston, MA 02110-1301, USA. 18 * 19 */ 20 21#include "config.h" 22#include "QtWebPagePolicyClient.h" 23 24#include "WKFrame.h" 25#include "WKURLQt.h" 26#include "qquickwebview_p_p.h" 27#include "qwebnavigationrequest_p.h" 28#include <QtCore/QObject> 29#include <WKFramePolicyListener.h> 30#include <WKRetainPtr.h> 31#include <WKURLRequest.h> 32 33namespace WebKit { 34 35QtWebPagePolicyClient::QtWebPagePolicyClient(WKPageRef pageRef, QQuickWebView* webView) 36 : m_webView(webView) 37{ 38 WKPagePolicyClient policyClient; 39 memset(&policyClient, 0, sizeof(WKPagePolicyClient)); 40 policyClient.version = kWKPagePolicyClientCurrentVersion; 41 policyClient.clientInfo = this; 42 policyClient.decidePolicyForNavigationAction = decidePolicyForNavigationAction; 43 policyClient.decidePolicyForResponse = decidePolicyForResponse; 44 WKPageSetPagePolicyClient(pageRef, &policyClient); 45} 46 47void QtWebPagePolicyClient::decidePolicyForNavigationAction(const QUrl& url, Qt::MouseButton mouseButton, Qt::KeyboardModifiers keyboardModifiers, QQuickWebView::NavigationType navigationType, WKFramePolicyListenerRef listener) 48{ 49 // NOTE: even though the C API (and the WebKit2 IPC) supports an asynchronous answer, this is not currently working. 50 // We are expected to call the listener immediately. See the patch for https://bugs.webkit.org/show_bug.cgi?id=53785. 51 QWebNavigationRequest navigationRequest(url, mouseButton, keyboardModifiers, navigationType); 52 emit m_webView->navigationRequested(&navigationRequest); 53 54 switch (navigationRequest.action()) { 55 case QQuickWebView::IgnoreRequest: 56 WKFramePolicyListenerIgnore(listener); 57 return; 58 case QQuickWebViewExperimental::DownloadRequest: 59 WKFramePolicyListenerDownload(listener); 60 return; 61 case QQuickWebView::AcceptRequest: 62 WKFramePolicyListenerUse(listener); 63 return; 64 } 65 ASSERT_NOT_REACHED(); 66} 67 68static inline QtWebPagePolicyClient* toQtWebPagePolicyClient(const void* clientInfo) 69{ 70 ASSERT(clientInfo); 71 return reinterpret_cast<QtWebPagePolicyClient*>(const_cast<void*>(clientInfo)); 72} 73 74static Qt::MouseButton toQtMouseButton(WKEventMouseButton button) 75{ 76 switch (button) { 77 case kWKEventMouseButtonLeftButton: 78 return Qt::LeftButton; 79 case kWKEventMouseButtonMiddleButton: 80 return Qt::MiddleButton; 81 case kWKEventMouseButtonRightButton: 82 return Qt::RightButton; 83 case kWKEventMouseButtonNoButton: 84 return Qt::NoButton; 85 } 86 ASSERT_NOT_REACHED(); 87 return Qt::NoButton; 88} 89 90static Qt::KeyboardModifiers toQtKeyboardModifiers(WKEventModifiers modifiers) 91{ 92 Qt::KeyboardModifiers qtModifiers = Qt::NoModifier; 93 if (modifiers & kWKEventModifiersShiftKey) 94 qtModifiers |= Qt::ShiftModifier; 95 if (modifiers & kWKEventModifiersControlKey) 96 qtModifiers |= Qt::ControlModifier; 97 if (modifiers & kWKEventModifiersAltKey) 98 qtModifiers |= Qt::AltModifier; 99 if (modifiers & kWKEventModifiersMetaKey) 100 qtModifiers |= Qt::MetaModifier; 101 return qtModifiers; 102} 103 104static QQuickWebView::NavigationType toQuickWebViewNavigationType(WKFrameNavigationType navigationType) 105{ 106 switch (navigationType) { 107 case kWKFrameNavigationTypeLinkClicked: 108 return QQuickWebView::LinkClickedNavigation; 109 case kWKFrameNavigationTypeFormSubmitted: 110 return QQuickWebView::FormSubmittedNavigation; 111 case kWKFrameNavigationTypeBackForward: 112 return QQuickWebView::BackForwardNavigation; 113 case kWKFrameNavigationTypeReload: 114 return QQuickWebView::ReloadNavigation; 115 case kWKFrameNavigationTypeFormResubmitted: 116 return QQuickWebView::FormResubmittedNavigation; 117 case kWKFrameNavigationTypeOther: 118 return QQuickWebView::OtherNavigation; 119 } 120 ASSERT_NOT_REACHED(); 121 return QQuickWebView::OtherNavigation; 122} 123 124void QtWebPagePolicyClient::decidePolicyForNavigationAction(WKPageRef, WKFrameRef frame, WKFrameNavigationType navigationType, WKEventModifiers modifiers, WKEventMouseButton mouseButton, WKURLRequestRef request, WKFramePolicyListenerRef listener, WKTypeRef, const void* clientInfo) 125{ 126 WKRetainPtr<WKURLRef> frameURL(AdoptWK, WKFrameCopyURL(frame)); 127 WKRetainPtr<WKURLRef> requestURL(AdoptWK, WKURLRequestCopyURL(request)); 128 QUrl qUrl = WKURLCopyQUrl(requestURL.get()); 129 toQtWebPagePolicyClient(clientInfo)->decidePolicyForNavigationAction(qUrl, toQtMouseButton(mouseButton), toQtKeyboardModifiers(modifiers), toQuickWebViewNavigationType(navigationType), listener); 130} 131 132void QtWebPagePolicyClient::decidePolicyForResponse(WKPageRef page, WKFrameRef frame, WKURLResponseRef response, WKURLRequestRef, WKFramePolicyListenerRef listener, WKTypeRef, const void*) 133{ 134 String type = toImpl(response)->resourceResponse().mimeType(); 135 type.makeLower(); 136 bool canShowMIMEType = toImpl(frame)->canShowMIMEType(type); 137 138 if (WKPageGetMainFrame(page) == frame) { 139 if (canShowMIMEType) { 140 WKFramePolicyListenerUse(listener); 141 return; 142 } 143 144 // If we can't use (show) it then we should download it. 145 WKFramePolicyListenerDownload(listener); 146 return; 147 } 148 149 // 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. 150 // It makes the browser intentionally behave differently when it comes to text(application)/xml content in subframes vs. mainframe. 151 if (!canShowMIMEType && !(type == "text/xml" || type == "application/xml")) { 152 WKFramePolicyListenerIgnore(listener); 153 return; 154 } 155 156 WKFramePolicyListenerUse(listener); 157} 158 159} // namespace WebKit 160 161