1 /****************************************************************************************
2 * Copyright (c) 2007 Trolltech ASA <copyright@trolltech.com> *
3 * Copyright (c) 2008 Urs Wolfer <uwolfer@kde.org> *
4 * *
5 * This program is free software; you can redistribute it and/or modify it under *
6 * the terms of the GNU General Public License as published by the Free Software *
7 * Foundation; either version 2 of the License, or (at your option) any later *
8 * version. *
9 * *
10 * This program is distributed in the hope that it will be useful, but WITHOUT ANY *
11 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A *
12 * PARTICULAR PURPOSE. See the GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License along with *
15 * this program. If not, see <http://www.gnu.org/licenses/>. *
16 ****************************************************************************************/
17
18 #define DEBUG_PREFIX "NetworkAccessManagerProxy"
19
20 #include "NetworkAccessManagerProxy.h"
21 #ifdef DEBUG_BUILD_TYPE
22 #include "NetworkAccessViewer.h"
23 #endif // DEBUG_BUILD_TYPE
24
25 #include "Version.h"
26
27 #include <KProtocolManager>
28
29
30 NetworkAccessManagerProxy *NetworkAccessManagerProxy::s_instance = nullptr;
31
instance()32 NetworkAccessManagerProxy *NetworkAccessManagerProxy::instance()
33 {
34 if( s_instance == nullptr )
35 s_instance = new NetworkAccessManagerProxy();
36 return s_instance;
37 }
38
destroy()39 void NetworkAccessManagerProxy::destroy()
40 {
41 if( s_instance )
42 {
43 delete s_instance;
44 s_instance = nullptr;
45 }
46 }
47
NetworkAccessManagerProxy(QObject * parent)48 NetworkAccessManagerProxy::NetworkAccessManagerProxy( QObject *parent )
49 : KIO::Integration::AccessManager( parent )
50 , m_userAgent( QStringLiteral( "Amarok/" ) + AMAROK_VERSION )
51 #ifdef DEBUG_BUILD_TYPE
52 , m_viewer( nullptr )
53 #endif // DEBUG_BUILD_TYPE
54 {
55 setCache(0); // disable QtWebKit cache to just use KIO one..
56 qRegisterMetaType<NetworkAccessManagerProxy::Error>();
57 }
58
~NetworkAccessManagerProxy()59 NetworkAccessManagerProxy::~NetworkAccessManagerProxy()
60 {
61 s_instance = nullptr;
62 }
63
64 #ifdef DEBUG_BUILD_TYPE
65 NetworkAccessViewer *
networkAccessViewer()66 NetworkAccessManagerProxy::networkAccessViewer()
67 {
68 return m_viewer;
69 }
70
71 void
setNetworkAccessViewer(NetworkAccessViewer * viewer)72 NetworkAccessManagerProxy::setNetworkAccessViewer( NetworkAccessViewer *viewer )
73 {
74 if( viewer )
75 {
76 if( m_viewer )
77 delete m_viewer;
78 m_viewer = viewer;
79 }
80 }
81 #endif // DEBUG_BUILD_TYPE
82
83 int
abortGet(const QList<QUrl> & urls)84 NetworkAccessManagerProxy::abortGet( const QList<QUrl> &urls )
85 {
86 int removed = 0;
87 const QSet<QUrl> &urlSet = urls.toSet();
88 foreach( const QUrl &url, urlSet )
89 removed += abortGet( url );
90 return removed;
91 }
92
93 int
abortGet(const QUrl & url)94 NetworkAccessManagerProxy::abortGet( const QUrl &url )
95 {
96 if( m_urlMap.contains(url) )
97 return 0;
98
99 qDeleteAll( m_urlMap.values( url ) );
100 int removed = m_urlMap.remove( url );
101 return removed;
102 }
103
104 QUrl
getRedirectUrl(QNetworkReply * reply)105 NetworkAccessManagerProxy::getRedirectUrl( QNetworkReply *reply )
106 {
107 QUrl targetUrl;
108
109 // Get the original URL.
110 QUrl originalUrl = reply->request().url();
111
112 // Get the redirect attribute.
113 QVariant redirectAttribute = reply->attribute( QNetworkRequest::RedirectionTargetAttribute );
114
115 // Get the redirect URL from the attribute.
116 QUrl redirectUrl = QUrl( redirectAttribute.toUrl() );
117
118 // If the redirect URL is valid and if it differs from the original
119 // URL then we return the redirect URL. Otherwise an empty URL will
120 // be returned.
121 if( !redirectUrl.isEmpty() && redirectUrl != originalUrl )
122 {
123 targetUrl = redirectUrl;
124 }
125
126 return targetUrl;
127 }
128
129 void
slotError(QObject * obj)130 NetworkAccessManagerProxy::slotError( QObject *obj )
131 {
132 QNetworkReply *reply = qobject_cast<QNetworkReply*>( obj );
133 if( !reply )
134 return;
135 QUrl url = reply->request().url();
136 m_urlMap.remove( url );
137 reply->deleteLater();
138 }
139
140 QNetworkReply *
createRequest(Operation op,const QNetworkRequest & req,QIODevice * outgoingData)141 NetworkAccessManagerProxy::createRequest( Operation op, const QNetworkRequest &req, QIODevice *outgoingData )
142 {
143 QNetworkRequest request = req;
144 request.setAttribute( QNetworkRequest::HttpPipeliningAllowedAttribute, true );
145 if ( request.hasRawHeader( "User-Agent" ) )
146 request.setRawHeader( "User-Agent", m_userAgent.toLocal8Bit() + ' ' + request.rawHeader( "User-Agent" ) );
147 else
148 request.setRawHeader( "User-Agent", m_userAgent.toLocal8Bit() );
149
150 KIO::CacheControl cc = KProtocolManager::cacheControl();
151 switch (cc)
152 {
153 case KIO::CC_CacheOnly: // Fail request if not in cache.
154 request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysCache);
155 break;
156
157 case KIO::CC_Refresh: // Always validate cached entry with remote site.
158 request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferNetwork);
159 break;
160
161 case KIO::CC_Reload: // Always fetch from remote site
162 request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysNetwork);
163 break;
164
165 case KIO::CC_Cache: // Use cached entry if available.
166 case KIO::CC_Verify: // Validate cached entry with remote site if expired.
167 default:
168 request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache);
169 break;
170 }
171
172 QNetworkReply *reply = KIO::Integration::AccessManager::createRequest( op, request, outgoingData );
173
174 #ifdef DEBUG_BUILD_TYPE
175 if( m_viewer )
176 m_viewer->addRequest( op, request, outgoingData, reply );
177 #endif // DEBUG_BUILD_TYPE
178 return reply;
179 }
180
181 namespace The
182 {
networkAccessManager()183 NetworkAccessManagerProxy *networkAccessManager()
184 {
185 return NetworkAccessManagerProxy::instance();
186 }
187 }
188
189 #include "moc_NetworkAccessManagerProxy.cpp"
190