File indexing completed on 2024-05-19 05:01:23
0001 /* 0002 This file is part of the KDE project. 0003 0004 SPDX-FileCopyrightText: 2009 Dawit Alemayehu <adawit@kde.org> 0005 SPDX-FileCopyrightText: 2018 Stefano Crocco <stefano.crocco@alice.it> 0006 0007 SPDX-License-Identifier: LGPL-2.0-or-later 0008 */ 0009 #ifndef WEBENGINEWALLET_H 0010 #define WEBENGINEWALLET_H 0011 0012 #include <QObject> 0013 #include <QString> 0014 #include <QList> 0015 #include <QPair> 0016 #include <QUrl> 0017 #include <QWidget> 0018 #include <QtGlobal> 0019 #include <QDebug> 0020 #include <QWebEnginePage> 0021 #include <QMap> 0022 0023 #include "settings/webenginesettings.h" 0024 0025 class WebEnginePage; 0026 class WebEnginePart; 0027 class QWebEngineScript; 0028 0029 /** 0030 * @brief Class which allows WebEnginePart to cache form data in `KWallet` 0031 * 0032 */ 0033 class WebEngineWallet : public QObject 0034 { 0035 Q_OBJECT 0036 0037 public: 0038 0039 /** 0040 * Holds data from a HTML <form> element. 0041 */ 0042 struct WebForm { 0043 0044 /** 0045 * @brief Enum describing a field type 0046 */ 0047 enum class WebFieldType { 0048 Text, ///< The field has type @e text 0049 Password, ///< The field has type @e password 0050 Email, ///< The field has type @e email 0051 Other ///< The field has a type not described by other values 0052 }; 0053 0054 /** 0055 * @brief The WebFieldType corresponding to a given field type name 0056 * 0057 * @param name the name of the field type. It must be lowercase 0058 * @return The WebForm::WebFieldType value corresponding to @p name. If @p name is not @e text, @e password or @e email, WebFieldType::Other is returned 0059 * @note For efficiency, this function requires @p name to be lowercase 0060 */ 0061 static WebFieldType fieldTypeFromTypeName(const QString &name); 0062 0063 /** 0064 * @brief A string representation of the type of a web field 0065 * 0066 * @param type the type of the field 0067 * @param localized whether or not the returned type should be localized 0068 * @return a string with the name of the type @type. If @p localized is @b true, `i18n` will be used to localize the string 0069 */ 0070 static QString fieldNameFromType(WebFieldType type, bool localized = false); 0071 0072 /** 0073 * @brief Struct describing a field inside of a web form 0074 */ 0075 struct WebField { 0076 QString name; ///< The name of the field 0077 QString id; ///< The id of the field 0078 WebFieldType type; ///< The type of the field 0079 bool readOnly; ///< Whether the field is read-only 0080 bool disabled; ///< Whether the field is disabled 0081 bool autocompleteAllowed; ///< Whether the autocomplete attribute of the field is on or off 0082 QString value; ///< The value of the field 0083 QString label; ///< The HTML label associated with the field 0084 0085 /** 0086 * @brief Whether the field can be automatically filled or not 0087 * 0088 * A field can be automatically filled if all these conditions are true: 0089 * - it is @b not read-only 0090 * - it is @b not disabled 0091 * - autocomplete is @b on 0092 * 0093 * @return @b true if the field can be automatically filled and @b false otherwise 0094 * @note The user can request that a field is cached (and so filled) even if this function returns false 0095 */ 0096 bool isAutoFillable() const {return !readOnly && !disabled && autocompleteAllowed;} 0097 }; 0098 0099 /** 0100 * @brief Removes all fields which aren't automatically fillable from the forms 0101 * 0102 * After calling this function, \link fields \endlink will only contain fields for which WebField::isAutoFillable() returns @b true. 0103 * If none of the fields is automatically fillable, #fields will be empty. 0104 */ 0105 void deleteNotAutoFillableFields(); 0106 0107 /** 0108 * @brief Returns a copy of this object which only contains auto fillable fields 0109 * 0110 * @return a copy of this object which only contains fields for which WebField::isAutoFillable() returns @b true 0111 */ 0112 WebForm withAutoFillableFieldsOnly() const; 0113 0114 /** 0115 * @brief Whether the form contains fields of type @e password 0116 * 0117 * @return @b true if at least one of the #fields has type @e password and @b false otherwise 0118 */ 0119 bool hasPasswords() const; 0120 0121 /** 0122 * @brief Whether the form has autofillable fields 0123 * 0124 * @return @b true if at least one of the #fields can be automatically filled according to WebField::isAutoFillable() and @b false otherwise 0125 */ 0126 bool hasAutoFillableFields() const; 0127 0128 /** 0129 * @brief Whether any of the writable fields in the form have non-empty values 0130 * 0131 * @return @b true if at least one of the #fields is not read-only and has a non-empty value 0132 */ 0133 bool hasFieldsWithWrittenValues() const; 0134 0135 /** 0136 * @brief Creates a WebEngineSettings::WebFormInfo from this object 0137 * 0138 * @return a WebEngineSettings::WebFormInfo having the same name, frame path and fields names as this object 0139 */ 0140 WebEngineSettings::WebFormInfo toSettingsInfo() const; 0141 0142 /// @brief The URL the form was found at. 0143 QUrl url; 0144 0145 ///@brief The name attribute of the form. 0146 QString name; 0147 0148 /// @brief The position of the form on the web page, relative to other forms. 0149 QString index; 0150 0151 /** @brief The path of the frame the form belongs to relative to the toplevel window (in the javascript sense). 0152 * 0153 * This is stored as a string containing a javascript array (it is passed as is to javascript code, so no need to store it in C++ format 0154 */ 0155 QString framePath; 0156 0157 /// @brief The name and value attributes of each input element in the form. 0158 QVector<WebField> fields; 0159 }; 0160 0161 /** 0162 * @brief A list of web forms 0163 */ 0164 typedef QVector<WebForm> WebFormList; 0165 0166 /** 0167 * @brief Constructs a WebEngineWebWallet 0168 * 0169 * @p parent is usually the WebEnginePage this wallet is being used for. 0170 * 0171 * The @p wid parameter is used to tell the KWallet manager which window 0172 * is requesting access to the wallet. 0173 * 0174 * @param parent the owner of this wallet 0175 * @param wid the window ID of the window the web page will be 0176 * embedded in 0177 */ 0178 explicit WebEngineWallet(WebEnginePart *parent = nullptr, WId wid = 0); 0179 0180 /** 0181 * @brief Destructor 0182 */ 0183 ~WebEngineWallet() override; 0184 0185 /** 0186 * @brief Whether the wallet is open or not 0187 * @return @b true if the wallet is open and @b false otherwise 0188 */ 0189 bool isOpen() const; 0190 0191 /** 0192 * @brief Attempts to save the form data from @p page and its children frames. 0193 * 0194 * You must connect to the @ref saveFormDataRequested signal and call either 0195 * @ref rejectSaveFormDataRequest or @ref acceptSaveFormDataRequest signals 0196 * in order to complete the save request. Otherwise, you request will simply 0197 * be ignored. 0198 * 0199 * Note that this function is asynchronous, as it requires running javascript code 0200 * on the page using QWebEnginePage::runJavaScript. This function only requests 0201 * for the form data to be saved when QWebEnginePage::runJavaScript finishes. 0202 */ 0203 void saveFormData(WebEnginePage *page, const WebFormList &allForms, bool force = false); 0204 0205 /** 0206 * @brief Attempts to fill forms contained in @p page with cached data. 0207 * 0208 * Note that this function is asynchronous, as it requires running javascript code 0209 * on the page using QWebEnginePage::runJavaScript. This function only requests 0210 * for the form data to be filled when QWebEnginePage::runJavaScript finishes. 0211 */ 0212 void fillFormData(WebEnginePage *page, const WebFormList &allForms); 0213 0214 /** 0215 * @brief Removes the form data specified by @p forms from the persistent storage. 0216 * 0217 * Note that this function will remove all cached data for forms found in @p page. 0218 * 0219 * Note that this function is asynchronous, as it requires running javascript code 0220 * on the page using QWebEnginePage::runJavaScript. This function only requests 0221 * for the form data to be removed when QWebEnginePage::runJavaScript finishes. 0222 */ 0223 void removeFormData(WebEnginePage *page); 0224 0225 /** 0226 * @brief Removes the form data specified by @p forms from the persistent storage. 0227 * 0228 * @param forms The forms to remove 0229 * @see formsWithCachedData 0230 */ 0231 void removeFormData(const WebFormList &forms); 0232 0233 /** 0234 * @brief the forms to save for the given key 0235 * 0236 * @param key the key associated with the page whose forms should be returned. It's the same key passed by the saveFormDataRequested() signal 0237 * @return the forms associated with the page corresponding to the given key 0238 */ 0239 WebFormList pendingSaveData(const QString &key); 0240 0241 /** 0242 * @brief Whether the user has customized which forms should be cached for the given URL 0243 * 0244 * @param url the URL to check 0245 * @return @b true if the user has customized the forms to cache for @p URL and false if the forms to cache for @p URL are detected automatically 0246 */ 0247 static bool hasCustomizedCacheableForms(const QUrl &url); 0248 0249 public Q_SLOTS: 0250 /** 0251 * @brief Accepts the save form data request associated with @p key. 0252 * 0253 * The @p key parameter is the one sent through the @ref saveFormDataRequested 0254 * signal. 0255 * 0256 * You must always call this function or @ref rejectSaveFormDataRequest in 0257 * order to complete the save form data request. Otherwise, the request will 0258 * simply be ignored. 0259 * 0260 * @see saveFormDataRequested. 0261 */ 0262 void acceptSaveFormDataRequest(const QString &key); 0263 0264 /** 0265 * @brief Rejects the save form data request associated with @p key. 0266 * 0267 * The @p key parameter is the one sent through the @ref saveFormDataRequested 0268 * signal. 0269 * 0270 * @see saveFormDataRequested. 0271 */ 0272 void rejectSaveFormDataRequest(const QString &key); 0273 0274 /** 0275 * @brief Detects the form in the given WebEnginePage and fills its form with cached data 0276 * 0277 * It usually is called in response to the <a href="https://doc.qt.io/qt-5/qwebenginepage.html#loadFinished">WebEnginePage::loadFinished</a> signal. 0278 * 0279 * @param page the WebEnginePage whose forms should be filled 0280 */ 0281 void detectAndFillPageForms(WebEnginePage *page); 0282 0283 /** 0284 * @brief Caches the contents of the fields 0285 * 0286 * @param page the page whose forms should be saved. If @b nullptr, nothing is done 0287 */ 0288 void saveFormsInPage(WebEnginePage *page); 0289 0290 /** 0291 * @brief Displays a dialog where the user can choose which fields in the current page should be cached 0292 * 0293 * If the user asks for it, besides saving the choice of fields, this function also immediately stores the field contents in the cache. 0294 * @note If the fields contents are cached immediately, the old cached contents is overwritten without confirmation. 0295 * 0296 * @param page the page for which to choose the forms to cache 0297 * @param widget the widget to use as the dialog parent 0298 */ 0299 void customizeFieldsToCache(WebEnginePage *page, QWidget *widget = nullptr); 0300 0301 /** 0302 * @brief Remove the customized list of forms to cache for a given URL 0303 * 0304 * @param url the URL of the page whose customization should be removed 0305 * @note This function doesn't remove the cached information but only the list of which forms should be cached for the given URL 0306 */ 0307 void removeCustomizationForPage(const QUrl &url); 0308 0309 /** 0310 * @brief Immediately caches the form data of the given page 0311 * 0312 * @param page the page whose form data should be cached 0313 */ 0314 void savePageDataNow(WebEnginePage *page); 0315 0316 Q_SIGNALS: 0317 /** 0318 * @brief This signal is emitted whenever a save form data request is received. 0319 * 0320 * Unless you connect to this signal and call @ref acceptSaveFormDataRequest 0321 * or @ref rejectSaveFormDataRequest slots, the save form data requested through 0322 * @ref saveFormData will simply be ignored. 0323 * 0324 * @p key is a value that uniquely identifies the save request and @p url 0325 * is the address for which the form data is being saved. 0326 * 0327 * @see acceptSaveFormDataRequest 0328 * @see rejectSaveFormDataRequest 0329 */ 0330 void saveFormDataRequested(const QString &key, const QUrl &url); 0331 0332 /** 0333 * @brief This signal is emitted whenever a save form data request is completed. 0334 * 0335 * @p ok will be set to true if the save form data request for @p url was 0336 * completed successfully. 0337 * 0338 * @see saveFormDataRequested 0339 */ 0340 void saveFormDataCompleted(const QUrl &url, bool ok); 0341 0342 /** 0343 * @brief This signal is emitted whenever a fill form data request is completed. 0344 * 0345 * @p ok will be set to true if any forms were successfully filled with 0346 * cached data from the persistent storage. 0347 * 0348 * @see fillFormData 0349 * @since 4.5 0350 */ 0351 void fillFormRequestCompleted(bool ok); 0352 0353 /** 0354 * @brief Signal emitted from detectAndFillPageForms() after form detection has finished. 0355 * 0356 * @param url the URL of the page 0357 * @param found whether the page contains any form of type @e text, @e, email or @e password 0358 * @param autoFillableFound whether the page contains any form which can be automatically filled 0359 * 0360 * @see detectAndFillPageForms() 0361 * @see WebForm::WebField::isAutoFillable() 0362 */ 0363 void formDetectionDone(const QUrl& url, bool found, bool autoFillableFound); 0364 0365 /** 0366 * @brief This signal is emitted whenever the current wallet is closed. 0367 */ 0368 void walletClosed(); 0369 0370 /** 0371 * @brief Signal emitted when the wallet is opened 0372 */ 0373 void walletOpened(); 0374 0375 protected: 0376 /** 0377 * @brief Returns a list of forms for @p url that are waiting to be filled. 0378 * 0379 * This function returns an empty list if there is no pending requests 0380 * for filling forms associated with @p url. 0381 * 0382 * @return a list of forms for @p url that are waiting to be filled. 0383 */ 0384 WebFormList formsToFill(const QUrl &url) const; 0385 0386 /** 0387 * @brief Returns forms to be removed from persistent storage. 0388 * 0389 * @return a list of forms to be removed from persistent storage. 0390 */ 0391 WebFormList formsToDelete() const; 0392 0393 /** 0394 * The key under which the custom list of fields to cache for a page should be saved 0395 * 0396 * @param url the URL of the page 0397 * @see WebEngineSettings::setCustomizedCacheableFieldsForPage() 0398 */ 0399 static QString customFormsKey(const QUrl &url); 0400 0401 /** 0402 * @brief Whether or not there's data associate with @p form in the persistent storage 0403 * 0404 * @return @b true when there is data associated with @p form in the 0405 * persistent storage and @b false otherwise. 0406 */ 0407 bool hasCachedFormData(const WebForm &form) const; 0408 0409 /** 0410 * @return Fills the web forms in frame that point to @p url with data from @p forms. 0411 * 0412 * @param url the URL of the page 0413 * @param forms the forms to fill the page with 0414 * @see fillFormDataFromCache. 0415 */ 0416 void fillWebForm(const QUrl &url, const WebFormList &forms); 0417 0418 /** 0419 * @brief Fills form data from persistent storage. 0420 * 0421 * If you reimplement this function, call @ref formsToFill to obtain 0422 * the list of forms pending to be filled. Once you fill the list with 0423 * the cached data from the persistent storage, you must call @p fillWebForm 0424 * to fill out the actual web forms. 0425 * 0426 * @see formsToFill 0427 * @param list the list of URLs to fill 0428 */ 0429 void fillFormDataFromCache(const QList<QUrl> &list); 0430 0431 /** 0432 * @brief Stores form data associated with @p key to a persistent storage. 0433 * 0434 * If you reimplement this function, call @ref formsToSave to obtain the 0435 * list of form data pending to be saved to persistent storage. 0436 * 0437 * @param key the string to retrieve the data 0438 * @see formsToSave 0439 */ 0440 void saveFormDataToCache(const QString &key); 0441 0442 /** 0443 * @brief Removes all cached form data associated with @p forms from persistent storage. 0444 * 0445 * If you reimplement this function, call @ref formsToDelete to obtain the 0446 * list of form data pending to be removed from persistent storage. 0447 * 0448 * @param forms the forms to delete 0449 * @see formsToDelete 0450 */ 0451 void removeFormDataFromCache(const WebFormList &forms); 0452 0453 /** 0454 * @brief Enum to distinguish between filling and saving operations with forms 0455 */ 0456 enum class CacheOperation { 0457 Fill, ///< Forms are being filled 0458 Save ///< Forms are being cached 0459 }; 0460 0461 /** 0462 * @brief Selects from the given list of forms for an URL the fields to cache 0463 * 0464 * Depending on the user choices, this function can return either the result of calling WebForm::withAutoFillableFieldsOnly() on each form 0465 * or the customized fields list chosen by the user. 0466 * 0467 * @param url the URL of the page 0468 * @param allForms the list of all forms contained in the page 0469 * @param op whether the function should return the forms to fill or those to save 0470 * @return a list of all cacheable forms in the page according to the user's settings 0471 */ 0472 WebFormList cacheableForms(const QUrl &url, const WebFormList &allForms, CacheOperation op) const; 0473 0474 private: 0475 class WebEngineWalletPrivate; 0476 friend class WebEngineWalletPrivate; 0477 WebEngineWalletPrivate *const d; 0478 0479 Q_PRIVATE_SLOT(d, void _k_openWalletDone(bool)) 0480 Q_PRIVATE_SLOT(d, void _k_walletClosed()) 0481 }; 0482 0483 QDebug operator<<(QDebug dbg, const WebEngineWallet::WebForm form); 0484 QDebug operator<<(QDebug dbg, const WebEngineWallet::WebForm::WebFieldType type); 0485 QDebug operator<<(QDebug dbg, const WebEngineWallet::WebForm::WebField field); 0486 0487 #endif // WEBENGINEWALLET_H