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