File indexing completed on 2024-12-22 04:43:21

0001 /* This file is part of the KDE project
0002     SPDX-FileCopyrightText: 1999 David Faure <faure@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "webenginesettings.h"
0008 
0009 #include "webengine_filter.h"
0010 #include <webenginepart_debug.h>
0011 #include "../../src/htmldefaults.h"
0012 #include "profile.h"
0013 
0014 #include <KConfig>
0015 #include <KSharedConfig>
0016 #include <KLocalizedString>
0017 #include <KConfigGroup>
0018 #include <KJob>
0019 #include <KIO/StoredTransferJob>
0020 #include <KMessageBox>
0021 
0022 #include <QWebEngineSettings>
0023 #include <QFontDatabase>
0024 #include <QFileInfo>
0025 #include <QDir>
0026 #include <QStringView>
0027 #include <QRegularExpression>
0028 
0029 using namespace KonqWebEnginePart;
0030 
0031 QDataStream & operator<<(QDataStream& ds, const WebEngineSettings::WebFormInfo& info)
0032 {
0033     ds << info.name<< info.framePath << info.fields;
0034     return ds;
0035 }
0036 
0037 QDataStream & operator>>(QDataStream& ds, WebEngineSettings::WebFormInfo& info)
0038 {
0039     ds >> info.name >> info.framePath >> info.fields;
0040     return ds;
0041 }
0042 
0043 /**
0044  * @internal
0045  * Contains all settings which are both available globally and per-domain
0046  */
0047 struct KPerDomainSettings {
0048     bool m_bEnableJava : 1;
0049     bool m_bEnableJavaScript : 1;
0050     bool m_bEnablePlugins : 1;
0051     // don't forget to maintain the bitfields as the enums grow
0052     HtmlSettingsInterface::JSWindowOpenPolicy m_windowOpenPolicy : 2;
0053     HtmlSettingsInterface::JSWindowStatusPolicy m_windowStatusPolicy : 1;
0054     HtmlSettingsInterface::JSWindowFocusPolicy m_windowFocusPolicy : 1;
0055     HtmlSettingsInterface::JSWindowMovePolicy m_windowMovePolicy : 1;
0056     HtmlSettingsInterface::JSWindowResizePolicy m_windowResizePolicy : 1;
0057 
0058 #ifdef DEBUG_SETTINGS
0059     void dump(const QString &infix = QString()) const {
0060       qCDebug(WEBENGINEPART_LOG) << "KPerDomainSettings " << infix << " @" << this << ":";
0061       qCDebug(WEBENGINEPART_LOG) << "  m_bEnableJava: " << m_bEnableJava;
0062       qCDebug(WEBENGINEPART_LOG) << "  m_bEnableJavaScript: " << m_bEnableJavaScript;
0063       qCDebug(WEBENGINEPART_LOG) << "  m_bEnablePlugins: " << m_bEnablePlugins;
0064       qCDebug(WEBENGINEPART_LOG) << "  m_windowOpenPolicy: " << m_windowOpenPolicy;
0065       qCDebug(WEBENGINEPART_LOG) << "  m_windowStatusPolicy: " << m_windowStatusPolicy;
0066       qCDebug(WEBENGINEPART_LOG) << "  m_windowFocusPolicy: " << m_windowFocusPolicy;
0067       qCDebug(WEBENGINEPART_LOG) << "  m_windowMovePolicy: " << m_windowMovePolicy;
0068       qCDebug(WEBENGINEPART_LOG) << "  m_windowResizePolicy: " << m_windowResizePolicy;
0069     }
0070 #endif
0071 };
0072 
0073 typedef QMap<QString,KPerDomainSettings> PolicyMap;
0074 
0075 class WebEngineSettingsData
0076 {
0077 public:  
0078     bool m_bChangeCursor : 1;
0079     bool m_bOpenMiddleClick : 1;
0080     bool m_underlineLink : 1;
0081     bool m_hoverLink : 1;
0082     bool m_bEnableJavaScriptDebug : 1;
0083     bool m_bEnableJavaScriptErrorReporting : 1;
0084     bool enforceCharset : 1;
0085     bool m_bAutoLoadImages : 1;
0086     bool m_bUnfinishedImageFrame : 1;
0087     bool m_formCompletionEnabled : 1;
0088     bool m_autoDelayedActionsEnabled : 1;
0089     bool m_jsErrorsEnabled : 1;
0090     bool m_follow_system_colors : 1;
0091     bool m_allowTabulation : 1;
0092     bool m_autoSpellCheck : 1;
0093     bool m_adFilterEnabled : 1;
0094     bool m_hideAdsEnabled : 1;
0095     bool m_jsPopupBlockerPassivePopup : 1;
0096     bool m_accessKeysEnabled : 1;
0097     bool m_zoomTextOnly : 1;
0098     bool m_useCookieJar : 1;
0099 #ifndef MANAGE_COOKIES_INTERNALLY
0100     bool m_acceptCrossDomainCookies : 1;
0101 #endif
0102     bool m_bAutoRefreshPage: 1;
0103     bool m_bEnableFavicon:1;
0104     bool m_disableInternalPluginHandling:1;
0105     bool m_offerToSaveWebSitePassword:1;
0106     bool m_loadPluginsOnDemand:1;
0107     bool m_enableLocalStorage:1;
0108     bool m_enableOfflineStorageDb:1;
0109     bool m_enableOfflineWebAppCache:1;
0110     bool m_enableWebGL:1;
0111     bool m_zoomToDPI:1;
0112     bool m_allowActiveMixedContent:1;
0113     bool m_allowMixedContentDisplay:1;
0114 
0115     // the virtual global "domain"
0116     KPerDomainSettings global;
0117 
0118     int m_fontSize;
0119     int m_minFontSize;
0120     int m_maxFormCompletionItems;
0121     WebEngineSettings::KAnimationAdvice m_showAnimations;
0122     WebEngineSettings::KSmoothScrollingMode m_smoothScrolling;
0123 
0124     QString m_encoding;
0125     QString m_userSheet;
0126 
0127     QColor m_textColor;
0128     QColor m_baseColor;
0129     QColor m_linkColor;
0130     QColor m_vLinkColor;
0131 
0132     PolicyMap domainPolicy;
0133     QStringList fonts;
0134     QStringList defaultFonts;
0135 
0136     KDEPrivate::FilterSet adBlackList;
0137     KDEPrivate::FilterSet adWhiteList;
0138     QList< QPair< QString, QChar > > m_fallbackAccessKeysAssignments;
0139 
0140     KSharedConfig::Ptr nonPasswordStorableSites;
0141     KSharedConfig::Ptr sitesWithCustomForms;
0142     bool m_internalPdfViewer;
0143 };
0144 
0145 class WebEngineSettingsPrivate : public QObject, public WebEngineSettingsData
0146 {
0147     Q_OBJECT
0148 public:
0149     void adblockFilterLoadList(const QString& filename)
0150     {
0151         /** load list file and process each line */
0152         QFile file(filename);
0153         if (file.open(QIODevice::ReadOnly)) {
0154             QTextStream ts(&file);
0155             QString line = ts.readLine();
0156             while (!line.isEmpty()) {
0157                 //qCDebug(WEBENGINEPART_LOG) << "Adding filter:" << line;
0158                 /** white list lines start with "@@" */
0159                 if (line.startsWith(QLatin1String("@@")))
0160                     adWhiteList.addFilter(line);
0161                 else
0162                     adBlackList.addFilter(line);
0163                 line = ts.readLine();
0164             }
0165             file.close();
0166         }
0167     }
0168 
0169 public Q_SLOTS:
0170     void adblockFilterResult(KJob *job)
0171     {
0172         KIO::StoredTransferJob *tJob = qobject_cast<KIO::StoredTransferJob*>(job);
0173         Q_ASSERT(tJob);
0174 
0175         if ( job->error() == KJob::NoError )
0176         {
0177             const QByteArray byteArray = tJob->data();
0178             const QString localFileName = tJob->property( "webenginesettings_adBlock_filename" ).toString();
0179 
0180             QFile file(localFileName);
0181             if ( file.open(QFile::WriteOnly) )
0182             {
0183                 const bool success = (file.write(byteArray) == byteArray.size());
0184                 if ( success )
0185                     adblockFilterLoadList(localFileName);
0186                 else
0187                     qCWarning(WEBENGINEPART_LOG) << "Could not write" << byteArray.size() << "to file" << localFileName;
0188                 file.close();
0189             }
0190             else
0191                 qCDebug(WEBENGINEPART_LOG) << "Cannot open file" << localFileName << "for filter list";
0192         }
0193         else
0194             qCDebug(WEBENGINEPART_LOG) << "Downloading" << tJob->url() << "failed with message:" << job->errorText();
0195     }
0196 };
0197 
0198 
0199 /** Returns a writeable per-domains settings instance for the given domain
0200   * or a deep copy of the global settings if not existent.
0201   */
0202 static KPerDomainSettings &setup_per_domain_policy(WebEngineSettingsPrivate* const d, const QString &domain)
0203 {
0204   if (domain.isEmpty())
0205     qCWarning(WEBENGINEPART_LOG) << "setup_per_domain_policy: domain is empty";
0206 
0207   const QString ldomain = domain.toLower();
0208   PolicyMap::iterator it = d->domainPolicy.find(ldomain);
0209   if (it == d->domainPolicy.end()) {
0210     // simply copy global domain settings (they should have been initialized
0211     // by this time)
0212     it = d->domainPolicy.insert(ldomain,d->global);
0213   }
0214   return *it;
0215 }
0216 
0217 template<typename T>
0218 static T readEntry(const KConfigGroup& config, const QString& key, int defaultValue)
0219 {
0220     return static_cast<T>(config.readEntry(key, defaultValue));
0221 }
0222 
0223 void WebEngineSettings::readDomainSettings(const KConfigGroup &config, bool reset,
0224                                         bool global, KPerDomainSettings &pd_settings)
0225 {
0226   const QString javaPrefix ((global ? QString() : QStringLiteral("java.")));
0227   const QString jsPrefix ((global ? QString() : QStringLiteral("javascript.")));
0228   const QString pluginsPrefix (global ? QString() : QStringLiteral("plugins."));
0229 
0230   // The setting for Java
0231   QString key = javaPrefix + QLatin1String("EnableJava");
0232   if ( (global && reset) || config.hasKey( key ) )
0233     pd_settings.m_bEnableJava = config.readEntry( key, false );
0234   else if ( !global )
0235     pd_settings.m_bEnableJava = d->global.m_bEnableJava;
0236 
0237   // The setting for Plugins
0238   key = pluginsPrefix + QLatin1String("EnablePlugins");
0239   if ( (global && reset) || config.hasKey( key ) )
0240     pd_settings.m_bEnablePlugins = config.readEntry( key, true );
0241   else if ( !global )
0242     pd_settings.m_bEnablePlugins = d->global.m_bEnablePlugins;
0243 
0244   // The setting for JavaScript
0245   key = jsPrefix + QLatin1String("EnableJavaScript");
0246   if ( (global && reset) || config.hasKey( key ) )
0247     pd_settings.m_bEnableJavaScript = config.readEntry( key, true );
0248   else if ( !global )
0249     pd_settings.m_bEnableJavaScript = d->global.m_bEnableJavaScript;
0250 
0251   // window property policies
0252   key = jsPrefix + QLatin1String("WindowOpenPolicy");
0253   if ( (global && reset) || config.hasKey( key ) )
0254     pd_settings.m_windowOpenPolicy = readEntry<HtmlSettingsInterface::JSWindowOpenPolicy>(config, key, HtmlSettingsInterface::JSWindowOpenSmart);
0255   else if ( !global )
0256     pd_settings.m_windowOpenPolicy = d->global.m_windowOpenPolicy;
0257 
0258   key = jsPrefix + QLatin1String("WindowMovePolicy");
0259   if ( (global && reset) || config.hasKey( key ) )
0260     pd_settings.m_windowMovePolicy = readEntry<HtmlSettingsInterface::JSWindowMovePolicy>(config, key, HtmlSettingsInterface::JSWindowMoveAllow);
0261   else if ( !global )
0262     pd_settings.m_windowMovePolicy = d->global.m_windowMovePolicy;
0263 
0264   key = jsPrefix + QLatin1String("WindowResizePolicy");
0265   if ( (global && reset) || config.hasKey( key ) )
0266     pd_settings.m_windowResizePolicy = readEntry<HtmlSettingsInterface::JSWindowResizePolicy>(config, key, HtmlSettingsInterface::JSWindowResizeAllow);
0267   else if ( !global )
0268     pd_settings.m_windowResizePolicy = d->global.m_windowResizePolicy;
0269 
0270   key = jsPrefix + QLatin1String("WindowStatusPolicy");
0271   if ( (global && reset) || config.hasKey( key ) )
0272     pd_settings.m_windowStatusPolicy = readEntry<HtmlSettingsInterface::JSWindowStatusPolicy>(config, key, HtmlSettingsInterface::JSWindowStatusAllow);
0273   else if ( !global )
0274     pd_settings.m_windowStatusPolicy = d->global.m_windowStatusPolicy;
0275 
0276   key = jsPrefix + QLatin1String("WindowFocusPolicy");
0277   if ( (global && reset) || config.hasKey( key ) )
0278     pd_settings.m_windowFocusPolicy = readEntry<HtmlSettingsInterface::JSWindowFocusPolicy>(config, key, HtmlSettingsInterface::JSWindowFocusAllow);
0279   else if ( !global )
0280     pd_settings.m_windowFocusPolicy = d->global.m_windowFocusPolicy;
0281 }
0282 
0283 
0284 WebEngineSettings::WebEngineSettings()
0285   :d (new WebEngineSettingsPrivate)
0286 {
0287   init();
0288 }
0289 
0290 WebEngineSettings::~WebEngineSettings()
0291 {
0292   delete d;
0293 }
0294 
0295 bool WebEngineSettings::changeCursor() const
0296 {
0297   return d->m_bChangeCursor;
0298 }
0299 
0300 bool WebEngineSettings::underlineLink() const
0301 {
0302   return d->m_underlineLink;
0303 }
0304 
0305 bool WebEngineSettings::hoverLink() const
0306 {
0307   return d->m_hoverLink;
0308 }
0309 
0310 bool WebEngineSettings::internalPdfViewer() const
0311 {
0312     return d->m_internalPdfViewer;
0313 }
0314 
0315 void WebEngineSettings::init()
0316 {
0317   initWebEngineSettings();
0318 
0319   KConfig global( QStringLiteral("khtmlrc"), KConfig::NoGlobals );
0320   init( &global, true );
0321 
0322   KSharedConfig::Ptr local = KSharedConfig::openConfig();
0323   if ( local ) {
0324       init( local.data(), false );
0325   }
0326 
0327   initNSPluginSettings();
0328   initCookieJarSettings();
0329 }
0330 
0331 void WebEngineSettings::init( KConfig * config, bool reset )
0332 {
0333   KConfigGroup cg( config, "MainView Settings" );
0334   if (reset || cg.exists() )
0335   {
0336     if ( reset || cg.hasKey( "OpenMiddleClick" ) )
0337         d->m_bOpenMiddleClick = cg.readEntry( "OpenMiddleClick", true );
0338   }
0339 
0340   KConfigGroup cgAccess(config,"Access Keys" );
0341   if (reset || cgAccess.exists() ) {
0342       d->m_accessKeysEnabled = cgAccess.readEntry( "Enabled", true );
0343   }
0344 
0345   KConfigGroup cgFilter( config, "Filter Settings" );
0346   if ((reset || cgFilter.exists()) && (d->m_adFilterEnabled = cgFilter.readEntry("Enabled", false)))
0347   {
0348       d->m_hideAdsEnabled = cgFilter.readEntry("Shrink", false);
0349 
0350       d->adBlackList.clear();
0351       d->adWhiteList.clear();
0352 
0353       /** read maximum age for filter list files, minimum is one day */
0354       int htmlFilterListMaxAgeDays = cgFilter.readEntry(QStringLiteral("HTMLFilterListMaxAgeDays")).toInt();
0355       if (htmlFilterListMaxAgeDays < 1)
0356           htmlFilterListMaxAgeDays = 1;
0357 
0358       QMapIterator<QString,QString> it (cgFilter.entryMap());
0359       while (it.hasNext())
0360       {
0361           it.next();
0362           int id = -1;
0363           const QString name = it.key();
0364           const QString url = it.value();
0365 
0366           if (name.startsWith(QLatin1String("Filter")))
0367           {
0368               if (url.startsWith(QLatin1String("@@")))
0369                   d->adWhiteList.addFilter(url);
0370               else
0371                   d->adBlackList.addFilter(url);
0372           }
0373           else if (name.startsWith(QLatin1String("HTMLFilterListName-")) && (id = QStringView{name}.mid(19).toInt()) > 0)
0374           {
0375               /** check if entry is enabled */
0376               bool filterEnabled = cgFilter.readEntry(QStringLiteral("HTMLFilterListEnabled-").append(QString::number(id))) != QLatin1String("false");
0377 
0378               /** get url for HTMLFilterList */
0379               QUrl url(cgFilter.readEntry(QStringLiteral("HTMLFilterListURL-").append(QString::number(id))));
0380 
0381               if (filterEnabled && url.isValid()) {
0382                   /** determine where to cache HTMLFilterList file */
0383                   QString localFile = cgFilter.readEntry(QStringLiteral("HTMLFilterListLocalFilename-").append(QString::number(id)));
0384                   QString dirName = QStandardPaths::writableLocation(QStandardPaths::CacheLocation);
0385                   QDir().mkpath(dirName);
0386                   localFile =  dirName + '/' + localFile;
0387 
0388                   /** determine existence and age of cache file */
0389                   QFileInfo fileInfo(localFile);
0390 
0391                   /** load cached file if it exists, irrespective of age */
0392                   if (fileInfo.exists())
0393                       d->adblockFilterLoadList( localFile );
0394 
0395                   /** if no cache list file exists or if it is too old ... */
0396                   if (!fileInfo.exists() || fileInfo.lastModified().daysTo(QDateTime::currentDateTime()) > htmlFilterListMaxAgeDays)
0397                   {
0398                       /** ... in this case, refetch list asynchronously */
0399                       // qCDebug(WEBENGINEPART_LOG) << "Fetching filter list from" << url << "to" << localFile;
0400                       KIO::StoredTransferJob *job = KIO::storedGet( url, KIO::Reload, KIO::HideProgressInfo );
0401                       QObject::connect( job, &KJob::result, d, &WebEngineSettingsPrivate::adblockFilterResult);
0402                       /** for later reference, store name of cache file */
0403                       job->setProperty("webenginesettings_adBlock_filename", localFile);
0404                   }
0405               }
0406           }
0407       }
0408   }
0409 
0410   KConfigGroup cgHtml( config, "HTML Settings" );
0411   if (reset || cgHtml.exists() )
0412   {
0413     // Fonts and colors
0414     if( reset ) {
0415         d->defaultFonts = QStringList();
0416         d->defaultFonts.append( cgHtml.readEntry( "StandardFont", QFontDatabase::systemFont(QFontDatabase::GeneralFont).family() ) );
0417         d->defaultFonts.append( cgHtml.readEntry( "FixedFont", QFontDatabase::systemFont(QFontDatabase::FixedFont).family() ));
0418         d->defaultFonts.append( cgHtml.readEntry( "SerifFont", HTML_DEFAULT_VIEW_SERIF_FONT ) );
0419         d->defaultFonts.append( cgHtml.readEntry( "SansSerifFont", HTML_DEFAULT_VIEW_SANSSERIF_FONT ) );
0420         d->defaultFonts.append( cgHtml.readEntry( "CursiveFont", HTML_DEFAULT_VIEW_CURSIVE_FONT ) );
0421         d->defaultFonts.append( cgHtml.readEntry( "FantasyFont", HTML_DEFAULT_VIEW_FANTASY_FONT ) );
0422         d->defaultFonts.append( QStringLiteral( "0" ) ); // font size adjustment
0423     }
0424 
0425     if ( reset || cgHtml.hasKey( "MinimumFontSize" ) )
0426         d->m_minFontSize = cgHtml.readEntry( "MinimumFontSize", HTML_DEFAULT_MIN_FONT_SIZE );
0427 
0428     if ( reset || cgHtml.hasKey( "MediumFontSize" ) )
0429         d->m_fontSize = cgHtml.readEntry( "MediumFontSize", 12 );
0430 
0431     d->fonts = cgHtml.readEntry( "Fonts", QStringList() );
0432 
0433     if ( reset || cgHtml.hasKey( "DefaultEncoding" ) )
0434         d->m_encoding = cgHtml.readEntry( "DefaultEncoding", "" );
0435 
0436     if ( reset || cgHtml.hasKey( "EnforceDefaultCharset" ) )
0437         d->enforceCharset = cgHtml.readEntry( "EnforceDefaultCharset", false );
0438 
0439     // Behavior
0440 
0441     if ( reset || cgHtml.hasKey("UnderlineLinks") )
0442         d->m_underlineLink = cgHtml.readEntry( "UnderlineLinks", true );
0443 
0444     if ( reset || cgHtml.hasKey( "HoverLinks" ) )
0445     {
0446         if ( (d->m_hoverLink = cgHtml.readEntry( "HoverLinks", false )))
0447             d->m_underlineLink = false;
0448     }
0449 
0450     if ( reset || cgHtml.hasKey( "AllowTabulation" ) )
0451         d->m_allowTabulation = cgHtml.readEntry( "AllowTabulation", false );
0452 
0453     if ( reset || cgHtml.hasKey( "AutoSpellCheck" ) )
0454         d->m_autoSpellCheck = cgHtml.readEntry( "AutoSpellCheck", true );
0455 
0456     // Other
0457     if ( reset || cgHtml.hasKey( "AutoLoadImages" ) )
0458       d->m_bAutoLoadImages = cgHtml.readEntry( "AutoLoadImages", true );
0459 
0460     if ( reset || cgHtml.hasKey( "AutoDelayedActions" ) )
0461         d->m_bAutoRefreshPage = cgHtml.readEntry( "AutoDelayedActions", true );
0462 
0463     if ( reset || cgHtml.hasKey( "UnfinishedImageFrame" ) )
0464       d->m_bUnfinishedImageFrame = cgHtml.readEntry( "UnfinishedImageFrame", true );
0465 
0466     if ( reset || cgHtml.hasKey( "ShowAnimations" ) )
0467     {
0468       QString value = cgHtml.readEntry( "ShowAnimations").toLower();
0469       if (value == QLatin1String("disabled"))
0470          d->m_showAnimations = KAnimationDisabled;
0471       else if (value == QLatin1String("looponce"))
0472          d->m_showAnimations = KAnimationLoopOnce;
0473       else
0474          d->m_showAnimations = KAnimationEnabled;
0475     }
0476 
0477     if ( reset || cgHtml.hasKey( "SmoothScrolling" ) )
0478     {
0479       QString value = cgHtml.readEntry( "SmoothScrolling", "whenefficient" ).toLower();
0480       if (value == QLatin1String("disabled"))
0481          d->m_smoothScrolling = KSmoothScrollingDisabled;
0482       else if (value == QLatin1String("whenefficient"))
0483          d->m_smoothScrolling = KSmoothScrollingWhenEfficient;
0484       else
0485          d->m_smoothScrolling = KSmoothScrollingEnabled;
0486     } 
0487 
0488     if ( reset || cgHtml.hasKey( "ZoomTextOnly" ) ) {
0489         d->m_zoomTextOnly = cgHtml.readEntry( "ZoomTextOnly", false );
0490     }
0491 
0492     if ( reset || cgHtml.hasKey( "ZoomToDPI" ) ) {
0493         d->m_zoomToDPI = cgHtml.readEntry( "ZoomToDPI", false );
0494     }
0495 
0496     if (cgHtml.readEntry("UserStyleSheetEnabled", false)) {
0497         if (reset || cgHtml.hasKey("UserStyleSheet"))
0498             d->m_userSheet = cgHtml.readEntry("UserStyleSheet", QString());
0499     } else {
0500         d->m_userSheet.clear();
0501     }
0502 
0503     if (reset || cgHtml.hasKey("InternalPdfViewer")) {
0504         d->m_internalPdfViewer = cgHtml.readEntry("InternalPdfViewer", false);
0505     }
0506 
0507     d->m_formCompletionEnabled = cgHtml.readEntry("FormCompletion", true);
0508     d->m_maxFormCompletionItems = cgHtml.readEntry("MaxFormCompletionItems", 10);
0509     d->m_autoDelayedActionsEnabled = cgHtml.readEntry ("AutoDelayedActions", true);
0510     d->m_jsErrorsEnabled = cgHtml.readEntry("ReportJSErrors", true);
0511     const QStringList accesskeys = cgHtml.readEntry("FallbackAccessKeysAssignments", QStringList());
0512     d->m_fallbackAccessKeysAssignments.clear();
0513     for( QStringList::ConstIterator it = accesskeys.begin(); it != accesskeys.end(); ++it )
0514         if( (*it).length() > 2 && (*it)[ 1 ] == ':' )
0515             d->m_fallbackAccessKeysAssignments.append( qMakePair( (*it).mid( 2 ), (*it)[ 0 ] ));
0516 
0517     d->m_bEnableFavicon = cgHtml.readEntry("EnableFavicon", true);
0518     d->m_offerToSaveWebSitePassword = cgHtml.readEntry("OfferToSaveWebsitePassword", true);
0519   }
0520 
0521   // Colors
0522   //In which group ?????
0523   if ( reset || cg.hasKey( "FollowSystemColors" ) )
0524       d->m_follow_system_colors = cg.readEntry( "FollowSystemColors", false );
0525 
0526   KConfigGroup cgGeneral( config, "General" );
0527   if ( reset || cgGeneral.exists( ) )
0528   {
0529     if ( reset || cgGeneral.hasKey( "foreground" ) ) {
0530       QColor def(HTML_DEFAULT_TXT_COLOR);
0531       d->m_textColor = cgGeneral.readEntry( "foreground", def );
0532     }
0533 
0534     if ( reset || cgGeneral.hasKey( "linkColor" ) ) {
0535       QColor def(HTML_DEFAULT_LNK_COLOR);
0536       d->m_linkColor = cgGeneral.readEntry( "linkColor", def );
0537     }
0538 
0539     if ( reset || cgGeneral.hasKey( "visitedLinkColor" ) ) {
0540       QColor def(HTML_DEFAULT_VLNK_COLOR);
0541       d->m_vLinkColor = cgGeneral.readEntry( "visitedLinkColor", def);
0542     }
0543 
0544     if ( reset || cgGeneral.hasKey( "background" ) ) {
0545       QColor def(HTML_DEFAULT_BASE_COLOR);
0546       d->m_baseColor = cgGeneral.readEntry( "background", def);
0547     }
0548   }
0549 
0550   KConfigGroup cgJava( config, "Java/JavaScript Settings" );
0551   if( reset || cgJava.exists() )
0552   {
0553     // The global setting for JavaScript debugging
0554     // This is currently always enabled by default
0555     if ( reset || cgJava.hasKey( "EnableJavaScriptDebug" ) )
0556       d->m_bEnableJavaScriptDebug = cgJava.readEntry( "EnableJavaScriptDebug", false );
0557 
0558     // The global setting for JavaScript error reporting
0559     if ( reset || cgJava.hasKey( "ReportJavaScriptErrors" ) )
0560       d->m_bEnableJavaScriptErrorReporting = cgJava.readEntry( "ReportJavaScriptErrors", false );
0561 
0562     // The global setting for popup block passive popup
0563     if ( reset || cgJava.hasKey( "PopupBlockerPassivePopup" ) )
0564       d->m_jsPopupBlockerPassivePopup = cgJava.readEntry("PopupBlockerPassivePopup", true );
0565 
0566     // Read options from the global "domain"
0567     readDomainSettings(cgJava,reset,true,d->global);
0568 #ifdef DEBUG_SETTINGS
0569     d->global.dump("init global");
0570 #endif
0571 
0572     // The domain-specific settings.
0573 
0574     static const char *const domain_keys[] = {  // always keep order of keys
0575         "ECMADomains", "JavaDomains", "PluginDomains"
0576     };
0577     bool check_old_ecma_settings = true;
0578     bool check_old_java_settings = true;
0579     // merge all domains into one list
0580     QSet<QString> domainList;
0581     for (unsigned i = 0; i < sizeof domain_keys/sizeof domain_keys[0]; ++i) {
0582         if (reset || cgJava.hasKey(domain_keys[i])) {
0583             if (i == 0) check_old_ecma_settings = false;
0584             else if (i == 1) check_old_java_settings = false;
0585             const QStringList dl = cgJava.readEntry( domain_keys[i], QStringList() );
0586             const QSet<QString>::Iterator notfound = domainList.end();
0587             QStringList::ConstIterator it = dl.begin();
0588             const QStringList::ConstIterator itEnd = dl.end();
0589             for (; it != itEnd; ++it) {
0590                 const QString domain = (*it).toLower();
0591                 QSet<QString>::Iterator pos = domainList.find(domain);
0592                 if (pos == notfound) domainList.insert(domain);
0593             }/*next it*/
0594         }
0595     }/*next i*/
0596 
0597     if (reset)
0598       d->domainPolicy.clear();
0599 
0600     {
0601       QSet<QString>::ConstIterator it = domainList.constBegin();
0602       const QSet<QString>::ConstIterator itEnd = domainList.constEnd();
0603       for ( ; it != itEnd; ++it)
0604       {
0605         const QString domain = *it;
0606         KConfigGroup cg( config, domain );
0607         readDomainSettings(cg,reset,false,d->domainPolicy[domain]);
0608 #ifdef DEBUG_SETTINGS
0609         d->domainPolicy[domain].dump("init "+domain);
0610 #endif
0611       }
0612     }
0613 
0614     bool check_old_java = true;
0615     if( (reset || cgJava.hasKey("JavaDomainSettings")) && check_old_java_settings)
0616     {
0617       check_old_java = false;
0618       const QStringList domainList = cgJava.readEntry( "JavaDomainSettings", QStringList() );
0619       QStringList::ConstIterator it = domainList.constBegin();
0620       const QStringList::ConstIterator itEnd = domainList.constEnd();
0621       for ( ; it != itEnd; ++it)
0622       {
0623         QString domain;
0624         HtmlSettingsInterface::JavaScriptAdvice javaAdvice;
0625         HtmlSettingsInterface::JavaScriptAdvice javaScriptAdvice;
0626         HtmlSettingsInterface::splitDomainAdvice(*it, domain, javaAdvice, javaScriptAdvice);
0627         setup_per_domain_policy(d,domain).m_bEnableJava = javaAdvice == HtmlSettingsInterface::JavaScriptAccept;
0628 #ifdef DEBUG_SETTINGS
0629         setup_per_domain_policy(d,domain).dump("JavaDomainSettings 4 "+domain);
0630 #endif
0631       }
0632     }
0633 
0634     bool check_old_ecma = true;
0635     if( ( reset || cgJava.hasKey( "ECMADomainSettings" ) ) && check_old_ecma_settings )
0636     {
0637       check_old_ecma = false;
0638       const QStringList domainList = cgJava.readEntry( "ECMADomainSettings", QStringList() );
0639       QStringList::ConstIterator it = domainList.constBegin();
0640       const QStringList::ConstIterator itEnd = domainList.constEnd();
0641       for ( ; it != itEnd; ++it)
0642       {
0643         QString domain;
0644         HtmlSettingsInterface::JavaScriptAdvice javaAdvice;
0645         HtmlSettingsInterface::JavaScriptAdvice javaScriptAdvice;
0646         HtmlSettingsInterface::splitDomainAdvice(*it, domain, javaAdvice, javaScriptAdvice);
0647         setup_per_domain_policy(d,domain).m_bEnableJavaScript = javaScriptAdvice == HtmlSettingsInterface::JavaScriptAccept;
0648 #ifdef DEBUG_SETTINGS
0649     setup_per_domain_policy(d,domain).dump("ECMADomainSettings 4 "+domain);
0650 #endif
0651       }
0652     }
0653 
0654     if( ( reset || cgJava.hasKey( "JavaScriptDomainAdvice" ) )
0655              && ( check_old_java || check_old_ecma )
0656          && ( check_old_ecma_settings || check_old_java_settings ) )
0657     {
0658       const QStringList domainList = cgJava.readEntry( "JavaScriptDomainAdvice", QStringList() );
0659       QStringList::ConstIterator it = domainList.constBegin();
0660       const QStringList::ConstIterator itEnd = domainList.constEnd();
0661       for ( ; it != itEnd; ++it)
0662       {
0663         QString domain;
0664         HtmlSettingsInterface::JavaScriptAdvice javaAdvice;
0665         HtmlSettingsInterface::JavaScriptAdvice javaScriptAdvice;
0666         HtmlSettingsInterface::splitDomainAdvice(*it, domain, javaAdvice, javaScriptAdvice);
0667         if( check_old_java )
0668           setup_per_domain_policy(d,domain).m_bEnableJava = javaAdvice == HtmlSettingsInterface::JavaScriptAccept;
0669         if( check_old_ecma )
0670           setup_per_domain_policy(d,domain).m_bEnableJavaScript = javaScriptAdvice == HtmlSettingsInterface::JavaScriptAccept;
0671 #ifdef DEBUG_SETTINGS
0672         setup_per_domain_policy(d,domain).dump("JavaScriptDomainAdvice 4 "+domain);
0673 #endif
0674       }
0675     }
0676   }
0677 
0678 #if 0
0679   // DNS Prefect support...
0680   if ( reset || cgHtml.hasKey( "DNSPrefetch" ) )
0681   {
0682     // Enabled, Disabled, OnlyWWWAndSLD
0683     QString value = cgHtml.readEntry( "DNSPrefetch", "Enabled" ).toLower();
0684 
0685     if (value == "enabled")
0686         Profile::defaultProfile()->settings()->setAttribute(QWebEngineSettings::DnsPrefetchEnabled, true);
0687     else
0688         Profile::defaultProfile()->settings()->setAttribute(QWebEngineSettings::DnsPrefetchEnabled, false);
0689   }
0690 
0691   // Sync with QWebEngineSettings.
0692   if (!d->m_encoding.isEmpty())
0693       Profile::defaultProfile()->settings()->setDefaultTextEncoding(d->m_encoding);
0694   Profile::defaultProfile()->settings()->setUserStyleSheetUrl(QUrl::fromUserInput(userStyleSheet()));
0695 #endif
0696 
0697 
0698   Profile::defaultProfile()->settings()->setAttribute(QWebEngineSettings::AutoLoadImages, autoLoadImages());
0699   Profile::defaultProfile()->settings()->setAttribute(QWebEngineSettings::JavascriptEnabled, isJavaScriptEnabled());
0700  // Profile::defaultProfile()->settings()->setAttribute(QWebEngineSettings::JavaEnabled, isJavaEnabled());
0701   Profile::defaultProfile()->settings()->setAttribute(QWebEngineSettings::PluginsEnabled, isPluginsEnabled());
0702 
0703   // By default disable JS window.open when policy is deny or smart.
0704   const HtmlSettingsInterface::JSWindowOpenPolicy policy = windowOpenPolicy();
0705   if (policy == HtmlSettingsInterface::JSWindowOpenDeny || policy == HtmlSettingsInterface::JSWindowOpenSmart)
0706       Profile::defaultProfile()->settings()->setAttribute(QWebEngineSettings::JavascriptCanOpenWindows, false);
0707   else
0708       Profile::defaultProfile()->settings()->setAttribute(QWebEngineSettings::JavascriptCanOpenWindows, true);
0709 
0710 //  Profile::defaultProfile()->settings()->setAttribute(QWebEngineSettings::ZoomTextOnly, zoomTextOnly());
0711 //  Profile::defaultProfile()->settings()->setAttribute(QWebEngineSettings::DeveloperExtrasEnabled, isJavaScriptDebugEnabled());
0712   Profile::defaultProfile()->settings()->setFontFamily(QWebEngineSettings::StandardFont, stdFontName());
0713   Profile::defaultProfile()->settings()->setFontFamily(QWebEngineSettings::FixedFont, fixedFontName());
0714   Profile::defaultProfile()->settings()->setFontFamily(QWebEngineSettings::SerifFont, serifFontName());
0715   Profile::defaultProfile()->settings()->setFontFamily(QWebEngineSettings::SansSerifFont, sansSerifFontName());
0716   Profile::defaultProfile()->settings()->setFontFamily(QWebEngineSettings::CursiveFont, cursiveFontName());
0717   Profile::defaultProfile()->settings()->setFontFamily(QWebEngineSettings::FantasyFont, fantasyFontName());
0718 
0719   // TODO: Create a webengine config module that gets embedded into Konqueror's kcm.
0720   // Turn on WebGL support
0721 //  Profile::defaultProfile()->settings()->setAttribute(QWebEngineSettings::WebGLEnabled, d->m_enableWebGL);
0722   // Turn on HTML 5 local and offline storage capabilities...
0723 //  Profile::defaultProfile()->settings()->setAttribute(QWebEngineSettings::OfflineStorageDatabaseEnabled, d->m_enableOfflineStorageDb);
0724 //  Profile::defaultProfile()->settings()->setAttribute(QWebEngineSettings::OfflineWebApplicationCacheEnabled, d->m_enableOfflineWebAppCache);
0725   Profile::defaultProfile()->settings()->setAttribute(QWebEngineSettings::LocalStorageEnabled, d->m_enableLocalStorage);
0726 
0727   Profile::defaultProfile()->settings()->setAttribute(QWebEngineSettings::ScrollAnimatorEnabled, smoothScrolling() != KSmoothScrollingDisabled);
0728 
0729   Profile::defaultProfile()->settings()->setAttribute(QWebEngineSettings::PdfViewerEnabled, internalPdfViewer());
0730 
0731   Profile::defaultProfile()->settings()->setAttribute(QWebEngineSettings::FullScreenSupportEnabled, true);
0732 
0733   // These numbers should be calculated from real "logical" DPI/72, using a default dpi of 96 for now
0734   computeFontSizes(96);
0735 
0736 }
0737 
0738 
0739 void WebEngineSettings::computeFontSizes( int logicalDpi )
0740 {
0741   if (zoomToDPI())
0742       logicalDpi = 96;
0743 
0744   float toPix = logicalDpi/72.0;
0745 
0746   if (toPix < 96.0/72.0)
0747       toPix = 96.0/72.0;
0748 
0749   Profile::defaultProfile()->settings()->setFontSize(QWebEngineSettings::MinimumFontSize, qRound(minFontSize() * toPix));
0750   Profile::defaultProfile()->settings()->setFontSize(QWebEngineSettings::DefaultFontSize, qRound(mediumFontSize() * toPix));
0751 }
0752 
0753 bool WebEngineSettings::zoomToDPI() const
0754 {
0755     return d->m_zoomToDPI;
0756 }
0757 
0758 void WebEngineSettings::setZoomToDPI(bool enabled)
0759 {
0760   d->m_zoomToDPI = enabled;
0761   // save it
0762   KConfigGroup cg( KSharedConfig::openConfig(), "HTML Settings");
0763   cg.writeEntry("ZoomToDPI", enabled);
0764   cg.sync();
0765 }
0766 
0767 /** Local helper for retrieving per-domain settings.
0768   *
0769   * In case of doubt, the global domain is returned.
0770   */
0771 static const KPerDomainSettings& lookup_hostname_policy(const WebEngineSettingsPrivate* const d,
0772                                                         const QString& hostname)
0773 {
0774 #ifdef DEBUG_SETTINGS
0775   qCDebug(WEBENGINEPART_LOG) << "lookup_hostname_policy(" << hostname << ")";
0776 #endif
0777   if (hostname.isEmpty()) {
0778 #ifdef DEBUG_SETTINGS
0779     d->global.dump("global");
0780 #endif
0781     return d->global;
0782   }
0783 
0784   const PolicyMap::const_iterator notfound = d->domainPolicy.constEnd();
0785 
0786   // First check whether there is a perfect match.
0787   PolicyMap::const_iterator it = d->domainPolicy.find(hostname);
0788   if( it != notfound ) {
0789 #ifdef DEBUG_SETTINGS
0790     qCDebug(WEBENGINEPART_LOG) << "perfect match";
0791     (*it).dump(hostname);
0792 #endif
0793     // yes, use it (unless dunno)
0794     return *it;
0795   }
0796 
0797   // Now, check for partial match.  Chop host from the left until
0798   // there's no dots left.
0799   QString host_part = hostname;
0800   int dot_idx = -1;
0801   while( (dot_idx = host_part.indexOf(QChar('.'))) >= 0 ) {
0802     host_part.remove(0,dot_idx);
0803     it = d->domainPolicy.find(host_part);
0804     Q_ASSERT(notfound == d->domainPolicy.end());
0805     if( it != notfound ) {
0806 #ifdef DEBUG_SETTINGS
0807       qCDebug(WEBENGINEPART_LOG) << "partial match";
0808       (*it).dump(host_part);
0809 #endif
0810       return *it;
0811     }
0812     // assert(host_part[0] == QChar('.'));
0813     host_part.remove(0,1); // Chop off the dot.
0814   }
0815 
0816   // No domain-specific entry: use global domain
0817 #ifdef DEBUG_SETTINGS
0818   qCDebug(WEBENGINEPART_LOG) << "no match";
0819   d->global.dump("global");
0820 #endif
0821   return d->global;
0822 }
0823 
0824 bool WebEngineSettings::isOpenMiddleClickEnabled()
0825 {
0826   return d->m_bOpenMiddleClick;
0827 }
0828 
0829 bool WebEngineSettings::accessKeysEnabled() const
0830 {
0831     return d->m_accessKeysEnabled;
0832 }
0833 
0834 bool WebEngineSettings::favIconsEnabled() const
0835 {
0836     return d->m_bEnableFavicon;
0837 }
0838 
0839 bool WebEngineSettings::isAdFilterEnabled() const
0840 {
0841     return d->m_adFilterEnabled;
0842 }
0843 
0844 bool WebEngineSettings::isHideAdsEnabled() const
0845 {
0846     return d->m_hideAdsEnabled;
0847 }
0848 
0849 bool WebEngineSettings::isAdFiltered( const QString &url ) const
0850 {
0851     if (!d->m_adFilterEnabled)
0852         return false;
0853 
0854     if (url.startsWith(QLatin1String("data:")))
0855         return false;
0856 
0857     return d->adBlackList.isUrlMatched(url) && !d->adWhiteList.isUrlMatched(url);
0858 }
0859 
0860 QString WebEngineSettings::adFilteredBy( const QString &url, bool *isWhiteListed ) const
0861 {
0862     QString m = d->adWhiteList.urlMatchedBy(url);
0863 
0864     if (!m.isEmpty()) {
0865         if (isWhiteListed != nullptr)
0866             *isWhiteListed = true;
0867         return m;
0868     }
0869 
0870     m = d->adBlackList.urlMatchedBy(url);
0871     if (m.isEmpty())
0872         return QString();
0873 
0874     if (isWhiteListed != nullptr)
0875         *isWhiteListed = false;
0876     return m;
0877 }
0878 
0879 void WebEngineSettings::addAdFilter( const QString &url )
0880 {
0881     KConfigGroup config = KSharedConfig::openConfig( QStringLiteral("khtmlrc"), KConfig::NoGlobals )->group( "Filter Settings" );
0882 
0883     QRegularExpression rx;
0884 
0885     // Try compiling to avoid invalid stuff. Only support the basic syntax here...
0886     // ### refactor somewhat
0887     if (url.length()>2 && url[0]=='/' && url[url.length()-1] == '/')
0888     {
0889         const QString inside = url.mid(1, url.length()-2);
0890         rx.setPattern(inside);
0891     }
0892     else
0893     {
0894         rx.setPattern(QRegularExpression::wildcardToRegularExpression(url));
0895     }
0896 
0897     if (rx.isValid())
0898     {
0899         int last=config.readEntry("Count", 0);
0900         const QString key = "Filter-" + QString::number(last);
0901         config.writeEntry(key, url);
0902         config.writeEntry("Count",last+1);
0903         config.sync();
0904 
0905         if (url.startsWith(QLatin1String("@@")))
0906             d->adWhiteList.addFilter(url);
0907         else
0908             d->adBlackList.addFilter(url);
0909     }
0910     else
0911     {
0912         KMessageBox::error(nullptr,
0913                            rx.errorString(),
0914                            i18n("Filter error"));
0915     }
0916 }
0917 
0918 bool WebEngineSettings::isJavaEnabled( const QString& hostname ) const
0919 {
0920   return lookup_hostname_policy(d,hostname.toLower()).m_bEnableJava;
0921 }
0922 
0923 bool WebEngineSettings::isJavaScriptEnabled( const QString& hostname ) const
0924 {
0925   return lookup_hostname_policy(d,hostname.toLower()).m_bEnableJavaScript;
0926 }
0927 
0928 bool WebEngineSettings::isJavaScriptDebugEnabled( const QString& /*hostname*/ ) const
0929 {
0930   // debug setting is global for now, but could change in the future
0931   return d->m_bEnableJavaScriptDebug;
0932 }
0933 
0934 bool WebEngineSettings::isJavaScriptErrorReportingEnabled( const QString& /*hostname*/ ) const
0935 {
0936   // error reporting setting is global for now, but could change in the future
0937   return d->m_bEnableJavaScriptErrorReporting;
0938 }
0939 
0940 bool WebEngineSettings::isPluginsEnabled( const QString& hostname ) const
0941 {
0942   return lookup_hostname_policy(d,hostname.toLower()).m_bEnablePlugins;
0943 }
0944 
0945 HtmlSettingsInterface::JSWindowOpenPolicy WebEngineSettings::windowOpenPolicy(const QString& hostname) const {
0946   return lookup_hostname_policy(d,hostname.toLower()).m_windowOpenPolicy;
0947 }
0948 
0949 HtmlSettingsInterface::JSWindowMovePolicy WebEngineSettings::windowMovePolicy(const QString& hostname) const {
0950   return lookup_hostname_policy(d,hostname.toLower()).m_windowMovePolicy;
0951 }
0952 
0953 HtmlSettingsInterface::JSWindowResizePolicy WebEngineSettings::windowResizePolicy(const QString& hostname) const {
0954   return lookup_hostname_policy(d,hostname.toLower()).m_windowResizePolicy;
0955 }
0956 
0957 HtmlSettingsInterface::JSWindowStatusPolicy WebEngineSettings::windowStatusPolicy(const QString& hostname) const {
0958   return lookup_hostname_policy(d,hostname.toLower()).m_windowStatusPolicy;
0959 }
0960 
0961 HtmlSettingsInterface::JSWindowFocusPolicy WebEngineSettings::windowFocusPolicy(const QString& hostname) const {
0962   return lookup_hostname_policy(d,hostname.toLower()).m_windowFocusPolicy;
0963 }
0964 
0965 int WebEngineSettings::mediumFontSize() const
0966 {
0967     return d->m_fontSize;
0968 }
0969 
0970 int WebEngineSettings::minFontSize() const
0971 {
0972   return d->m_minFontSize;
0973 }
0974 
0975 QString WebEngineSettings::settingsToCSS() const
0976 {
0977     // lets start with the link properties
0978     QString str = QStringLiteral("a:link {\ncolor: ");
0979     str += d->m_linkColor.name();
0980     str += ';';
0981     if(d->m_underlineLink)
0982         str += QLatin1String("\ntext-decoration: underline;");
0983 
0984     if( d->m_bChangeCursor )
0985     {
0986         str += QLatin1String("\ncursor: pointer;");
0987         str += QLatin1String("\n}\ninput[type=image] { cursor: pointer;");
0988     }
0989     str += QLatin1String("\n}\n");
0990     str += QLatin1String("a:visited {\ncolor: ");
0991     str += d->m_vLinkColor.name();
0992     str += ';';
0993     if(d->m_underlineLink)
0994         str += QLatin1String("\ntext-decoration: underline;");
0995 
0996     if( d->m_bChangeCursor )
0997         str += QLatin1String("\ncursor: pointer;");
0998     str += QLatin1String("\n}\n");
0999 
1000     if(d->m_hoverLink)
1001         str += QLatin1String("a:link:hover, a:visited:hover { text-decoration: underline; }\n");
1002 
1003     return str;
1004 }
1005 
1006 QString WebEngineSettings::lookupFont(int i) const
1007 {
1008     if (d->fonts.count() > i) {
1009         return d->fonts.at(i);
1010     }
1011 
1012     if (d->defaultFonts.count() > i) {
1013         return d->defaultFonts.at(i);
1014     }
1015 
1016     return QString();
1017 }
1018 
1019 QString WebEngineSettings::stdFontName() const
1020 {
1021     return lookupFont(0);
1022 }
1023 
1024 QString WebEngineSettings::fixedFontName() const
1025 {
1026     return lookupFont(1);
1027 }
1028 
1029 QString WebEngineSettings::serifFontName() const
1030 {
1031     return lookupFont(2);
1032 }
1033 
1034 QString WebEngineSettings::sansSerifFontName() const
1035 {
1036     return lookupFont(3);
1037 }
1038 
1039 QString WebEngineSettings::cursiveFontName() const
1040 {
1041     return lookupFont(4);
1042 }
1043 
1044 QString WebEngineSettings::fantasyFontName() const
1045 {
1046     return lookupFont(5);
1047 }
1048 
1049 void WebEngineSettings::setStdFontName(const QString &n)
1050 {
1051     while(d->fonts.count() <= 0)
1052         d->fonts.append(QString());
1053     d->fonts[0] = n;
1054 }
1055 
1056 void WebEngineSettings::setFixedFontName(const QString &n)
1057 {
1058     while(d->fonts.count() <= 1)
1059         d->fonts.append(QString());
1060     d->fonts[1] = n;
1061 }
1062 
1063 QString WebEngineSettings::userStyleSheet() const
1064 {
1065     return d->m_userSheet;
1066 }
1067 
1068 bool WebEngineSettings::isFormCompletionEnabled() const
1069 {
1070   return d->m_formCompletionEnabled;
1071 }
1072 
1073 int WebEngineSettings::maxFormCompletionItems() const
1074 {
1075   return d->m_maxFormCompletionItems;
1076 }
1077 
1078 const QString &WebEngineSettings::encoding() const
1079 {
1080   return d->m_encoding;
1081 }
1082 
1083 bool WebEngineSettings::followSystemColors() const
1084 {
1085     return d->m_follow_system_colors;
1086 }
1087 
1088 const QColor& WebEngineSettings::textColor() const
1089 {
1090   return d->m_textColor;
1091 }
1092 
1093 const QColor& WebEngineSettings::baseColor() const
1094 {
1095   return d->m_baseColor;
1096 }
1097 
1098 const QColor& WebEngineSettings::linkColor() const
1099 {
1100   return d->m_linkColor;
1101 }
1102 
1103 const QColor& WebEngineSettings::vLinkColor() const
1104 {
1105   return d->m_vLinkColor;
1106 }
1107 
1108 bool WebEngineSettings::autoPageRefresh() const
1109 {
1110   return d->m_bAutoRefreshPage;
1111 }
1112 
1113 bool WebEngineSettings::autoLoadImages() const
1114 {
1115   return d->m_bAutoLoadImages;
1116 }
1117 
1118 bool WebEngineSettings::unfinishedImageFrame() const
1119 {
1120   return d->m_bUnfinishedImageFrame;
1121 }
1122 
1123 WebEngineSettings::KAnimationAdvice WebEngineSettings::showAnimations() const
1124 {
1125   return d->m_showAnimations;
1126 }
1127 
1128 WebEngineSettings::KSmoothScrollingMode WebEngineSettings::smoothScrolling() const
1129 {
1130   return d->m_smoothScrolling;
1131 }
1132 
1133 bool WebEngineSettings::zoomTextOnly() const
1134 {
1135   return d->m_zoomTextOnly;
1136 }
1137 
1138 bool WebEngineSettings::isAutoDelayedActionsEnabled() const
1139 {
1140   return d->m_autoDelayedActionsEnabled;
1141 }
1142 
1143 bool WebEngineSettings::jsErrorsEnabled() const
1144 {
1145   return d->m_jsErrorsEnabled;
1146 }
1147 
1148 void WebEngineSettings::setJSErrorsEnabled(bool enabled)
1149 {
1150   d->m_jsErrorsEnabled = enabled;
1151   // save it
1152   KConfigGroup cg( KSharedConfig::openConfig(), "HTML Settings");
1153   cg.writeEntry("ReportJSErrors", enabled);
1154   cg.sync();
1155 }
1156 
1157 bool WebEngineSettings::allowTabulation() const
1158 {
1159     return d->m_allowTabulation;
1160 }
1161 
1162 bool WebEngineSettings::autoSpellCheck() const
1163 {
1164     return d->m_autoSpellCheck;
1165 }
1166 
1167 QList< QPair< QString, QChar > > WebEngineSettings::fallbackAccessKeysAssignments() const
1168 {
1169     return d->m_fallbackAccessKeysAssignments;
1170 }
1171 
1172 void WebEngineSettings::setJSPopupBlockerPassivePopup(bool enabled)
1173 {
1174     d->m_jsPopupBlockerPassivePopup = enabled;
1175     // save it
1176     KConfigGroup cg( KSharedConfig::openConfig(), "Java/JavaScript Settings");
1177     cg.writeEntry("PopupBlockerPassivePopup", enabled);
1178     cg.sync();
1179 }
1180 
1181 bool WebEngineSettings::jsPopupBlockerPassivePopup() const
1182 {
1183     return d->m_jsPopupBlockerPassivePopup;
1184 }
1185 
1186 #ifndef MANAGE_COOKIES_INTERNALLY
1187 bool WebEngineSettings::isCookieJarEnabled() const
1188 {
1189     return d->m_useCookieJar;
1190 }
1191 
1192 bool WebEngineSettings::acceptCrossDomainCookies() const
1193 {
1194     return d->m_acceptCrossDomainCookies;
1195 }
1196 #endif
1197 
1198 // Password storage...
1199 KConfigGroup WebEngineSettings::nonPasswordStorableSitesCg() const
1200 {
1201     if (!d->nonPasswordStorableSites) {
1202         d->nonPasswordStorableSites = KSharedConfig::openConfig(QString(), KConfig::NoGlobals);
1203     }
1204     return KConfigGroup(d->nonPasswordStorableSites, "NonPasswordStorableSites");
1205 }
1206 
1207 bool WebEngineSettings::isNonPasswordStorableSite(const QString &host) const
1208 {
1209     KConfigGroup cg = nonPasswordStorableSitesCg();
1210     const QStringList sites = cg.readEntry("Sites", QStringList());
1211     return sites.contains(host);
1212 }
1213 
1214 void WebEngineSettings::addNonPasswordStorableSite(const QString &host)
1215 {
1216     KConfigGroup cg = nonPasswordStorableSitesCg();
1217     QStringList sites = cg.readEntry("Sites", QStringList());
1218     sites.append(host);
1219     cg.writeEntry("Sites", sites);
1220     cg.sync();
1221 }
1222 
1223 void WebEngineSettings::removeNonPasswordStorableSite(const QString &host)
1224 {
1225     KConfigGroup cg = nonPasswordStorableSitesCg();
1226     QStringList sites = cg.readEntry("Sites", QStringList());
1227     sites.removeOne(host);
1228     cg.writeEntry("Sites", sites);
1229     cg.sync();
1230 }
1231 
1232 KConfigGroup WebEngineSettings::pagesWithCustomizedCacheableFieldsCg() const
1233 {
1234     if (!d->sitesWithCustomForms) {
1235         d->sitesWithCustomForms = KSharedConfig::openConfig(QString(), KConfig::NoGlobals); 
1236     }
1237     return KConfigGroup(d->sitesWithCustomForms, "PagesWithCustomizedCacheableFields");
1238 }
1239 
1240 void WebEngineSettings::setCustomizedCacheableFieldsForPage(const QString& url, const WebFormInfoList& forms)
1241 {
1242     KConfigGroup cg = pagesWithCustomizedCacheableFieldsCg();
1243     QByteArray data;
1244     QDataStream ds(&data, QIODevice::WriteOnly);
1245     ds << forms;
1246     cg.writeEntry(url, data);
1247     cg.sync();
1248 }
1249 
1250 bool WebEngineSettings::hasPageCustomizedCacheableFields(const QString& url) const
1251 {
1252     KConfigGroup cg = pagesWithCustomizedCacheableFieldsCg();
1253     return cg.hasKey(url);
1254 }
1255 
1256 void WebEngineSettings::removeCacheableFieldsCustomizationForPage(const QString& url)
1257 {
1258     KConfigGroup cg = pagesWithCustomizedCacheableFieldsCg();
1259     cg.deleteEntry(url);
1260     cg.sync();
1261 }
1262 
1263 WebEngineSettings::WebFormInfoList WebEngineSettings::customizedCacheableFieldsForPage(const QString& url)
1264 {
1265     KConfigGroup cg = pagesWithCustomizedCacheableFieldsCg();
1266     QByteArray data = cg.readEntry(url, QByteArray());
1267     if (data.isEmpty()) {
1268         return {};
1269     }
1270     QDataStream ds(data);
1271     WebFormInfoList res;
1272     ds >> res;
1273     return res;
1274 }
1275 
1276 bool WebEngineSettings::askToSaveSitePassword() const
1277 {
1278     return d->m_offerToSaveWebSitePassword;
1279 }
1280 
1281 bool WebEngineSettings::isInternalPluginHandlingDisabled() const
1282 {
1283     return d->m_disableInternalPluginHandling;
1284 }
1285 
1286 bool WebEngineSettings::isLoadPluginsOnDemandEnabled() const
1287 {
1288     return d->m_loadPluginsOnDemand;
1289 }
1290 
1291 bool WebEngineSettings::allowMixedContentDisplay() const
1292 {
1293     return d->m_allowMixedContentDisplay;
1294 }
1295 
1296 bool WebEngineSettings::alowActiveMixedContent() const
1297 {
1298     return d->m_allowActiveMixedContent;
1299 }
1300 
1301 
1302 void WebEngineSettings::initWebEngineSettings()
1303 {
1304     KConfig cfg (QStringLiteral("webenginepartrc"), KConfig::NoGlobals);
1305     KConfigGroup generalCfg (&cfg, "General");
1306     d->m_disableInternalPluginHandling = generalCfg.readEntry("DisableInternalPluginHandling", false);
1307     d->m_enableLocalStorage = generalCfg.readEntry("EnableLocalStorage", true);
1308     d->m_enableOfflineStorageDb = generalCfg.readEntry("EnableOfflineStorageDatabase", true);
1309     d->m_enableOfflineWebAppCache = generalCfg.readEntry("EnableOfflineWebApplicationCache", true);
1310     d->m_enableWebGL = generalCfg.readEntry("EnableWebGL", true);
1311     d->m_allowActiveMixedContent = generalCfg.readEntry("AllowActiveMixedContent", false);
1312     d->m_allowMixedContentDisplay = generalCfg.readEntry("AllowMixedContentDisplay", true);
1313 
1314     // Force the reloading of the non password storable sites settings.
1315     d->nonPasswordStorableSites.reset();
1316 }
1317 
1318 void WebEngineSettings::initCookieJarSettings()
1319 {
1320     KSharedConfig::Ptr cookieCfgPtr = KSharedConfig::openConfig(QStringLiteral("kcookiejarrc"), KConfig::NoGlobals);
1321     KConfigGroup cookieCfg ( cookieCfgPtr, "Cookie Policy");
1322     d->m_useCookieJar = cookieCfg.readEntry("Cookies", false);
1323 #ifndef MANAGE_COOKIES_INTERNALLY
1324     d->m_acceptCrossDomainCookies = !cookieCfg.readEntry("RejectCrossDomainCookies", true);
1325 #endif
1326 }
1327 
1328 void WebEngineSettings::initNSPluginSettings()
1329 {
1330     KSharedConfig::Ptr cookieCfgPtr = KSharedConfig::openConfig(QStringLiteral("kcmnspluginrc"), KConfig::NoGlobals);
1331     KConfigGroup cookieCfg ( cookieCfgPtr, "Misc");
1332     d->m_loadPluginsOnDemand = cookieCfg.readEntry("demandLoad", false);
1333 }
1334 
1335 
1336 WebEngineSettings* WebEngineSettings::self()
1337 {
1338     static WebEngineSettings s_webEngineSettings;
1339     return &s_webEngineSettings;
1340 }
1341 
1342 QDebug operator<<(QDebug dbg, const WebEngineSettings::WebFormInfo& info)
1343 {
1344     QDebugStateSaver state(dbg);
1345     dbg.nospace() << "CustomWebFormInfo{";
1346     dbg << info.name << ", " << info.framePath << ", " << info.fields << "}";
1347     return dbg;
1348 }
1349 
1350 #include "webenginesettings.moc"