File indexing completed on 2024-05-05 04:48:36

0001 /****************************************************************************************
0002  * Copyright (c) 2007 Trolltech ASA <copyright@trolltech.com>                           *
0003  * Copyright (c) 2008 Urs Wolfer <uwolfer@kde.org>                                      *
0004  *                                                                                      *
0005  * This program is free software; you can redistribute it and/or modify it under        *
0006  * the terms of the GNU General Public License as published by the Free Software        *
0007  * Foundation; either version 2 of the License, or (at your option) any later           *
0008  * version.                                                                             *
0009  *                                                                                      *
0010  * This program is distributed in the hope that it will be useful, but WITHOUT ANY      *
0011  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A      *
0012  * PARTICULAR PURPOSE. See the GNU General Public License for more details.             *
0013  *                                                                                      *
0014  * You should have received a copy of the GNU General Public License along with         *
0015  * this program.  If not, see <http://www.gnu.org/licenses/>.                           *
0016  ****************************************************************************************/
0017 
0018 #define DEBUG_PREFIX "NetworkAccessManagerProxy"
0019 
0020 #include "NetworkAccessManagerProxy.h"
0021 #ifdef DEBUG_BUILD_TYPE
0022 #include "NetworkAccessViewer.h"
0023 #endif // DEBUG_BUILD_TYPE
0024 
0025 #include "Version.h"
0026 
0027 #include <KProtocolManager>
0028 
0029 
0030 NetworkAccessManagerProxy *NetworkAccessManagerProxy::s_instance = nullptr;
0031 
0032 NetworkAccessManagerProxy *NetworkAccessManagerProxy::instance()
0033 {
0034     if( s_instance == nullptr )
0035         s_instance = new NetworkAccessManagerProxy();
0036     return s_instance;
0037 }
0038 
0039 void NetworkAccessManagerProxy::destroy()
0040 {
0041     if( s_instance )
0042     {
0043         delete s_instance;
0044         s_instance = nullptr;
0045     }
0046 }
0047 
0048 NetworkAccessManagerProxy::NetworkAccessManagerProxy( QObject *parent )
0049     : KIO::Integration::AccessManager( parent )
0050     , m_userAgent( QStringLiteral( "Amarok/" ) + AMAROK_VERSION )
0051 #ifdef DEBUG_BUILD_TYPE
0052     , m_viewer( nullptr )
0053 #endif // DEBUG_BUILD_TYPE
0054 {
0055     setCache(nullptr);   // disable QtWebKit cache to just use KIO one..
0056     qRegisterMetaType<NetworkAccessManagerProxy::Error>();
0057 }
0058 
0059 NetworkAccessManagerProxy::~NetworkAccessManagerProxy()
0060 {
0061     s_instance = nullptr;
0062 }
0063 
0064 #ifdef DEBUG_BUILD_TYPE
0065 NetworkAccessViewer *
0066 NetworkAccessManagerProxy::networkAccessViewer()
0067 {
0068     return m_viewer;
0069 }
0070 
0071 void
0072 NetworkAccessManagerProxy::setNetworkAccessViewer( NetworkAccessViewer *viewer )
0073 {
0074     if( viewer )
0075     {
0076         if( m_viewer )
0077             delete m_viewer;
0078         m_viewer = viewer;
0079     }
0080 }
0081 #endif // DEBUG_BUILD_TYPE
0082 
0083 int
0084 NetworkAccessManagerProxy::abortGet( const QList<QUrl> &urls )
0085 {
0086     int removed = 0;
0087     const QSet<QUrl> urlSet(urls.begin(), urls.end());
0088     foreach( const QUrl &url, urlSet )
0089         removed += abortGet( url );
0090     return removed;
0091 }
0092 
0093 int
0094 NetworkAccessManagerProxy::abortGet( const QUrl &url )
0095 {
0096     if( m_urlMap.contains(url) )
0097         return 0;
0098 
0099     qDeleteAll( m_urlMap.values( url ) );
0100     int removed = m_urlMap.remove( url );
0101     return removed;
0102 }
0103 
0104 QUrl
0105 NetworkAccessManagerProxy::getRedirectUrl( QNetworkReply *reply )
0106 {
0107     QUrl targetUrl;
0108 
0109     // Get the original URL.
0110     QUrl originalUrl = reply->request().url();
0111 
0112     // Get the redirect attribute.
0113     QVariant redirectAttribute = reply->attribute( QNetworkRequest::RedirectionTargetAttribute );
0114 
0115     // Get the redirect URL from the attribute.
0116     QUrl redirectUrl = QUrl( redirectAttribute.toUrl() );
0117 
0118     // If the redirect URL is valid and if it differs from the original
0119     // URL then we return the redirect URL. Otherwise an empty URL will
0120     // be returned.
0121     if( !redirectUrl.isEmpty() && redirectUrl != originalUrl )
0122     {
0123         targetUrl = redirectUrl;
0124     }
0125 
0126     return targetUrl;
0127 }
0128 
0129 void
0130 NetworkAccessManagerProxy::slotError( QObject *obj )
0131 {
0132     QNetworkReply *reply = qobject_cast<QNetworkReply*>( obj );
0133     if( !reply )
0134         return;
0135     QUrl url = reply->request().url();
0136     m_urlMap.remove( url );
0137     reply->deleteLater();
0138 }
0139 
0140 QNetworkReply *
0141 NetworkAccessManagerProxy::createRequest( Operation op, const QNetworkRequest &req, QIODevice *outgoingData )
0142 {
0143     QNetworkRequest request = req;
0144     request.setAttribute( QNetworkRequest::HttpPipeliningAllowedAttribute, true );
0145     if ( request.hasRawHeader( "User-Agent" ) )
0146         request.setRawHeader( "User-Agent", m_userAgent.toLocal8Bit() + ' ' + request.rawHeader( "User-Agent" ) );
0147     else
0148         request.setRawHeader( "User-Agent", m_userAgent.toLocal8Bit() );
0149 
0150     KIO::CacheControl cc = KProtocolManager::cacheControl();
0151     switch (cc)
0152     {
0153     case KIO::CC_CacheOnly:      // Fail request if not in cache.
0154         request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysCache);
0155         break;
0156 
0157     case KIO::CC_Refresh:        // Always validate cached entry with remote site.
0158         request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferNetwork);
0159         break;
0160 
0161     case KIO::CC_Reload:         // Always fetch from remote site
0162         request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysNetwork);
0163         break;
0164 
0165     case KIO::CC_Cache:          // Use cached entry if available.
0166     case KIO::CC_Verify:         // Validate cached entry with remote site if expired.
0167     default:
0168         request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache);
0169         break;
0170     }
0171 
0172     QNetworkReply *reply = KIO::Integration::AccessManager::createRequest( op, request, outgoingData );
0173 
0174 #ifdef DEBUG_BUILD_TYPE
0175     if( m_viewer )
0176         m_viewer->addRequest( op, request, outgoingData, reply );
0177 #endif // DEBUG_BUILD_TYPE
0178     return reply;
0179 }
0180 
0181 namespace The
0182 {
0183     NetworkAccessManagerProxy *networkAccessManager()
0184     {
0185         return NetworkAccessManagerProxy::instance();
0186     }
0187 }
0188 
0189 #include "moc_NetworkAccessManagerProxy.cpp"