1 /**************************************************************************
2 * Otter Browser: Web browser controlled by the user, not vice-versa.
3 * Copyright (C) 2013 - 2018 Michal Dutkiewicz aka Emdek <michal@emdek.pl>
4 * Copyright (C) 2015 Piotr Wójcik <chocimier@tlen.pl>
5 * Copyright (C) 2015 Jan Bajer aka bajasoft <jbajer@gmail.com>
6 * Copyright (C) 2017 Piktas Zuikis <piktas.zuikis@inbox.lt>
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 *
21 **************************************************************************/
22
23 #include "WebWidget.h"
24 #include "ContentsDialog.h"
25 #include "ContentsWidget.h"
26 #include "Menu.h"
27 #include "TransferDialog.h"
28 #include "Window.h"
29 #include "../core/Application.h"
30 #include "../core/BookmarksManager.h"
31 #include "../core/ContentFiltersManager.h"
32 #include "../core/HandlersManager.h"
33 #include "../core/HistoryManager.h"
34 #include "../core/IniSettings.h"
35 #include "../core/SearchEnginesManager.h"
36 #include "../core/SettingsManager.h"
37 #include "../core/ThemesManager.h"
38 #include "../core/TransfersManager.h"
39 #include "../core/Utils.h"
40
41 #include <QtCore/QDir>
42 #include <QtCore/QJsonArray>
43 #include <QtCore/QJsonDocument>
44 #include <QtGui/QClipboard>
45 #include <QtWidgets/QToolTip>
46
47 namespace Otter
48 {
49
50 QString WebWidget::m_fastForwardScript;
51
WebWidget(const QVariantMap & parameters,WebBackend * backend,ContentsWidget * parent)52 WebWidget::WebWidget(const QVariantMap ¶meters, WebBackend *backend, ContentsWidget *parent) : QWidget(parent), ActionExecutor(),
53 m_parent(parent),
54 m_backend(backend),
55 m_windowIdentifier(0),
56 m_loadingTime(0),
57 m_loadingTimer(0),
58 m_reloadTimer(0)
59 {
60 Q_UNUSED(parameters)
61
62 connect(this, &WebWidget::loadingStateChanged, this, &WebWidget::handleLoadingStateChange);
63 connect(BookmarksManager::getModel(), &BookmarksModel::modelModified, this, [&]()
64 {
65 emit categorizedActionsStateChanged({ActionsManager::ActionDefinition::BookmarkCategory});
66 });
67 connect(PasswordsManager::getInstance(), &PasswordsManager::passwordsModified, this, [&]()
68 {
69 emit arbitraryActionsStateChanged({ActionsManager::FillPasswordAction});
70 });
71 }
72
timerEvent(QTimerEvent * event)73 void WebWidget::timerEvent(QTimerEvent *event)
74 {
75 if (event->timerId() == m_loadingTimer)
76 {
77 ++m_loadingTime;
78
79 emit pageInformationChanged(LoadingTimeInformation, m_loadingTime);
80 }
81 else if (event->timerId() == m_reloadTimer)
82 {
83 killTimer(m_reloadTimer);
84
85 m_reloadTimer = 0;
86
87 if (getLoadingState() == FinishedLoadingState)
88 {
89 triggerAction(ActionsManager::ReloadAction);
90 }
91 }
92 }
93
triggerAction(int identifier,const QVariantMap & parameters,ActionsManager::TriggerType trigger)94 void WebWidget::triggerAction(int identifier, const QVariantMap ¶meters, ActionsManager::TriggerType trigger)
95 {
96 Q_UNUSED(identifier)
97 Q_UNUSED(parameters)
98 Q_UNUSED(trigger)
99 }
100
search(const QString & query,const QString & searchEngine)101 void WebWidget::search(const QString &query, const QString &searchEngine)
102 {
103 Q_UNUSED(query)
104 Q_UNUSED(searchEngine)
105 }
106
startWatchingChanges(QObject * object,ChangeWatcher watcher)107 void WebWidget::startWatchingChanges(QObject *object, ChangeWatcher watcher)
108 {
109 if (!m_changeWatchers.contains(watcher))
110 {
111 m_changeWatchers[watcher] = {object};
112
113 updateWatchedData(watcher);
114 }
115 else if (!m_changeWatchers[watcher].contains(object))
116 {
117 m_changeWatchers[watcher].append(object);
118 }
119 else
120 {
121 return;
122 }
123
124 connect(object, &QObject::destroyed, this, [=]()
125 {
126 stopWatchingChanges(object, watcher);
127 });
128 }
129
stopWatchingChanges(QObject * object,ChangeWatcher watcher)130 void WebWidget::stopWatchingChanges(QObject *object, ChangeWatcher watcher)
131 {
132 if (m_changeWatchers.contains(watcher))
133 {
134 m_changeWatchers[watcher].removeAll(object);
135 }
136 }
137
startReloadTimer()138 void WebWidget::startReloadTimer()
139 {
140 const int reloadTime(getOption(SettingsManager::Content_PageReloadTimeOption).toInt());
141
142 if (reloadTime >= 0)
143 {
144 triggerAction(ActionsManager::StopScheduledReloadAction);
145
146 if (reloadTime > 0)
147 {
148 m_reloadTimer = startTimer(reloadTime * 1000);
149 }
150 }
151 }
152
startTransfer(Transfer * transfer)153 void WebWidget::startTransfer(Transfer *transfer)
154 {
155 if (transfer->getState() == Transfer::CancelledState)
156 {
157 transfer->deleteLater();
158
159 return;
160 }
161
162 const HandlersManager::HandlerDefinition handler(HandlersManager::getHandler(transfer->getMimeType()));
163
164 switch (handler.transferMode)
165 {
166 case HandlersManager::HandlerDefinition::IgnoreTransfer:
167 transfer->cancel();
168 transfer->deleteLater();
169
170 break;
171 case HandlersManager::HandlerDefinition::AskTransfer:
172 {
173 TransferDialog *transferDialog(new TransferDialog(transfer, this));
174 ContentsDialog *dialog(new ContentsDialog(ThemesManager::createIcon(QLatin1String("download")), transferDialog->windowTitle(), QString(), QString(), QDialogButtonBox::NoButton, transferDialog, this));
175
176 connect(transferDialog, &TransferDialog::finished, dialog, &ContentsDialog::close);
177
178 showDialog(dialog, false);
179 }
180
181 break;
182 case HandlersManager::HandlerDefinition::OpenTransfer:
183 transfer->setOpenCommand(handler.openCommand);
184
185 TransfersManager::addTransfer(transfer);
186
187 break;
188 case HandlersManager::HandlerDefinition::SaveTransfer:
189 transfer->setTarget(handler.downloadsPath + QDir::separator() + transfer->getSuggestedFileName());
190
191 if (transfer->getState() == Transfer::CancelledState)
192 {
193 TransfersManager::addTransfer(transfer);
194 }
195 else
196 {
197 transfer->deleteLater();
198 }
199
200 break;
201 case HandlersManager::HandlerDefinition::SaveAsTransfer:
202 {
203 const QString path(Utils::getSavePath(transfer->getSuggestedFileName(), handler.downloadsPath, {}, true).path);
204
205 if (path.isEmpty())
206 {
207 transfer->cancel();
208 transfer->deleteLater();
209
210 return;
211 }
212
213 transfer->setTarget(path, true);
214
215 TransfersManager::addTransfer(transfer);
216 }
217
218 break;
219 default:
220 break;
221 }
222 }
223
clearOptions()224 void WebWidget::clearOptions()
225 {
226 const QString host(Utils::extractHost(getUrl()));
227 const QList<int> identifiers(m_options.keys());
228
229 m_options.clear();
230
231 for (int i = 0; i < identifiers.count(); ++i)
232 {
233 emit optionChanged(identifiers.at(i), SettingsManager::getOption(identifiers.at(i), host));
234 }
235
236 emit arbitraryActionsStateChanged({ActionsManager::ResetQuickPreferencesAction});
237 }
238
fillPassword(const PasswordsManager::PasswordInformation & password)239 void WebWidget::fillPassword(const PasswordsManager::PasswordInformation &password)
240 {
241 Q_UNUSED(password)
242 }
243
openUrl(const QUrl & url,SessionsManager::OpenHints hints)244 void WebWidget::openUrl(const QUrl &url, SessionsManager::OpenHints hints)
245 {
246 switch (hints)
247 {
248 case SessionsManager::CurrentTabOpen:
249 case SessionsManager::DefaultOpen:
250 setUrl(url, false);
251
252 break;
253 default:
254 {
255 WebWidget *widget(clone(false, hints.testFlag(SessionsManager::PrivateOpen), SettingsManager::getOption(SettingsManager::Sessions_OptionsExludedFromInheritingOption).toStringList()));
256 widget->setRequestedUrl(url, false);
257
258 emit requestedNewWindow(widget, hints, {});
259 }
260
261 break;
262 }
263 }
264
handleLoadingStateChange(LoadingState state)265 void WebWidget::handleLoadingStateChange(LoadingState state)
266 {
267 if (m_loadingTimer != 0)
268 {
269 killTimer(m_loadingTimer);
270
271 m_loadingTimer = 0;
272 }
273
274 if (state == OngoingLoadingState)
275 {
276 m_loadingTime = 0;
277 m_loadingTimer = startTimer(1000);
278
279 emit pageInformationChanged(LoadingTimeInformation, 0);
280 }
281 }
282
handleToolTipEvent(QHelpEvent * event,QWidget * widget)283 void WebWidget::handleToolTipEvent(QHelpEvent *event, QWidget *widget)
284 {
285 const HitTestResult hitResult(getHitTestResult(event->pos()));
286 const QString toolTipsMode(SettingsManager::getOption(SettingsManager::Browser_ToolTipsModeOption).toString());
287 const QString link((hitResult.linkUrl.isValid() ? hitResult.linkUrl : hitResult.formUrl).toString());
288 QString text;
289
290 if (toolTipsMode != QLatin1String("disabled"))
291 {
292 const QString title(QString(hitResult.title).replace(QLatin1Char('&'), QLatin1String("&")).replace(QLatin1Char('<'), QLatin1String("<")).replace(QLatin1Char('>'), QLatin1String(">")));
293
294 if (toolTipsMode == QLatin1String("extended"))
295 {
296 if (!link.isEmpty())
297 {
298 text = (title.isEmpty() ? QString() : tr("Title: %1").arg(title) + QLatin1String("<br>")) + tr("Address: %1").arg(link);
299 }
300 else if (!title.isEmpty())
301 {
302 text = title;
303 }
304 }
305 else
306 {
307 text = title;
308 }
309 }
310
311 setStatusMessageOverride(link.isEmpty() ? hitResult.title : link);
312
313 if (!text.isEmpty())
314 {
315 QToolTip::showText(event->globalPos(), QStringLiteral("<div style=\"white-space:pre-line;\">%1</div>").arg(text), widget);
316 }
317
318 event->accept();
319 }
320
handleWindowCloseRequest()321 void WebWidget::handleWindowCloseRequest()
322 {
323 const QString host(Utils::extractHost(getUrl()));
324
325 if (isPopup() && SettingsManager::getOption(SettingsManager::Permissions_ScriptsCanCloseSelfOpenedWindowsOption, host).toBool())
326 {
327 emit requestedCloseWindow();
328
329 return;
330 }
331
332 const QString mode(SettingsManager::getOption(SettingsManager::Permissions_ScriptsCanCloseWindowsOption, host).toString());
333
334 if (mode != QLatin1String("ask"))
335 {
336 if (mode == QLatin1String("allow"))
337 {
338 emit requestedCloseWindow();
339 }
340
341 return;
342 }
343
344 ContentsDialog *dialog(new ContentsDialog(ThemesManager::createIcon(QLatin1String("dialog-warning")), tr("JavaScript"), tr("Webpage wants to close this tab, do you want to allow to close it?"), QString(), (QDialogButtonBox::Ok | QDialogButtonBox::Cancel), nullptr, this));
345 dialog->setCheckBox(tr("Do not show this message again"), false);
346
347 connect(this, &WebWidget::aboutToReload, dialog, &ContentsDialog::close);
348 connect(dialog, &ContentsDialog::finished, [&](int result, bool isChecked)
349 {
350 const bool isAccepted(result == QDialog::Accepted);
351
352 if (isChecked)
353 {
354 SettingsManager::setOption(SettingsManager::Permissions_ScriptsCanCloseWindowsOption, (isAccepted ? QLatin1String("allow") : QLatin1String("disallow")));
355 }
356
357 if (isAccepted)
358 {
359 emit requestedCloseWindow();
360 }
361 });
362
363 showDialog(dialog, false);
364 }
365
notifyRedoActionStateChanged()366 void WebWidget::notifyRedoActionStateChanged()
367 {
368 emit arbitraryActionsStateChanged({ActionsManager::RedoAction});
369 }
370
notifyUndoActionStateChanged()371 void WebWidget::notifyUndoActionStateChanged()
372 {
373 emit arbitraryActionsStateChanged({ActionsManager::UndoAction});
374 }
375
updateHitTestResult(const QPoint & position)376 void WebWidget::updateHitTestResult(const QPoint &position)
377 {
378 m_hitResult = getHitTestResult(position);
379 }
380
updateWatchedData(ChangeWatcher watcher)381 void WebWidget::updateWatchedData(ChangeWatcher watcher)
382 {
383 Q_UNUSED(watcher)
384 }
385
showDialog(ContentsDialog * dialog,bool lockEventLoop)386 void WebWidget::showDialog(ContentsDialog *dialog, bool lockEventLoop)
387 {
388 if (m_parent)
389 {
390 m_parent->showDialog(dialog, lockEventLoop);
391 }
392 }
393
showContextMenu(const QPoint & position)394 void WebWidget::showContextMenu(const QPoint &position)
395 {
396 const bool hasSelection(this->hasSelection() && !getSelectedText().trimmed().isEmpty());
397
398 if (position.isNull() && (!hasSelection || m_clickPosition.isNull()))
399 {
400 return;
401 }
402
403 const QPoint hitPosition(position.isNull() ? m_clickPosition : position);
404
405 if (isScrollBar(hitPosition) || !canShowContextMenu(hitPosition))
406 {
407 return;
408 }
409
410 updateHitTestResult(hitPosition);
411
412 emit categorizedActionsStateChanged({ActionsManager::ActionDefinition::EditingCategory});
413
414 QStringList includeSections;
415
416 if (m_hitResult.flags.testFlag(HitTestResult::IsFormTest))
417 {
418 includeSections.append(QLatin1String("form"));
419 }
420
421 if (!m_hitResult.imageUrl.isValid() && m_hitResult.flags.testFlag(HitTestResult::IsSelectedTest) && hasSelection)
422 {
423 includeSections.append(QLatin1String("selection"));
424 }
425
426 if (m_hitResult.linkUrl.isValid())
427 {
428 if (m_hitResult.linkUrl.scheme() == QLatin1String("mailto"))
429 {
430 includeSections.append(QLatin1String("mail"));
431 }
432 else
433 {
434 includeSections.append(QLatin1String("link"));
435 }
436 }
437
438 if (!m_hitResult.imageUrl.isEmpty())
439 {
440 includeSections.append(QLatin1String("image"));
441 }
442
443 if (m_hitResult.mediaUrl.isValid())
444 {
445 includeSections.append(QLatin1String("media"));
446 }
447
448 if (m_hitResult.flags.testFlag(HitTestResult::IsContentEditableTest))
449 {
450 includeSections.append(QLatin1String("edit"));
451 }
452
453 if (includeSections.isEmpty() || (includeSections.count() == 1 && includeSections.first() == QLatin1String("form")))
454 {
455 includeSections.append(QLatin1String("standard"));
456
457 if (m_hitResult.frameUrl.isValid())
458 {
459 includeSections.append(QLatin1String("frame"));
460 }
461 }
462
463 if (includeSections.isEmpty())
464 {
465 return;
466 }
467
468 ActionExecutor::Object executor;
469
470 if (m_parent)
471 {
472 if (m_parent->getWindow())
473 {
474 executor = ActionExecutor::Object(m_parent->getWindow(), m_parent->getWindow());
475 }
476 else
477 {
478 executor = ActionExecutor::Object(m_parent, m_parent);
479 }
480 }
481 else
482 {
483 executor = ActionExecutor::Object(this, this);
484 }
485
486 Menu menu(Menu::UnknownMenu, this);
487 menu.load(QLatin1String("menu/webWidget.json"), includeSections, executor);
488 menu.exec(mapToGlobal(hitPosition));
489 }
490
setParent(QWidget * parent)491 void WebWidget::setParent(QWidget *parent)
492 {
493 QWidget::setParent(parent);
494
495 ContentsWidget *contentsWidget(qobject_cast<ContentsWidget*>(parent));
496
497 if (contentsWidget)
498 {
499 m_parent = contentsWidget;
500 }
501 }
502
setActiveStyleSheet(const QString & styleSheet)503 void WebWidget::setActiveStyleSheet(const QString &styleSheet)
504 {
505 Q_UNUSED(styleSheet)
506 }
507
setClickPosition(const QPoint & position)508 void WebWidget::setClickPosition(const QPoint &position)
509 {
510 m_clickPosition = position;
511 }
512
setStatusMessage(const QString & message)513 void WebWidget::setStatusMessage(const QString &message)
514 {
515 const QString previousMessage(getStatusMessage());
516
517 m_statusMessage = message;
518
519 const QString currentMessage(getStatusMessage());
520
521 if (currentMessage != previousMessage)
522 {
523 emit statusMessageChanged(currentMessage);
524 }
525 }
526
setStatusMessageOverride(const QString & message)527 void WebWidget::setStatusMessageOverride(const QString &message)
528 {
529 const QString previousMessage(getStatusMessage());
530
531 m_statusMessageOverride = message;
532
533 const QString currentMessage(getStatusMessage());
534
535 if (currentMessage != previousMessage)
536 {
537 emit statusMessageChanged(currentMessage);
538 }
539 }
540
setPermission(FeaturePermission feature,const QUrl & url,PermissionPolicies policies)541 void WebWidget::setPermission(FeaturePermission feature, const QUrl &url, PermissionPolicies policies)
542 {
543 if (policies.testFlag(KeepAskingPermission))
544 {
545 return;
546 }
547
548 const QString value(policies.testFlag(GrantedPermission) ? QLatin1String("allow") : QLatin1String("disallow"));
549 const QString host(Utils::extractHost(url));
550
551 switch (feature)
552 {
553 case FullScreenFeature:
554 SettingsManager::setOption(SettingsManager::Permissions_EnableFullScreenOption, value, host);
555
556 return;
557 case GeolocationFeature:
558 SettingsManager::setOption(SettingsManager::Permissions_EnableGeolocationOption, value, host);
559
560 return;
561 case NotificationsFeature:
562 SettingsManager::setOption(SettingsManager::Permissions_EnableNotificationsOption, value, host);
563
564 return;
565 case PointerLockFeature:
566 SettingsManager::setOption(SettingsManager::Permissions_EnablePointerLockOption, value, host);
567
568 return;
569 case CaptureAudioFeature:
570 SettingsManager::setOption(SettingsManager::Permissions_EnableMediaCaptureAudioOption, value, host);
571
572 return;
573 case CaptureVideoFeature:
574 SettingsManager::setOption(SettingsManager::Permissions_EnableMediaCaptureVideoOption, value, host);
575
576 return;
577 case CaptureAudioVideoFeature:
578 SettingsManager::setOption(SettingsManager::Permissions_EnableMediaCaptureAudioOption, value, host);
579 SettingsManager::setOption(SettingsManager::Permissions_EnableMediaCaptureVideoOption, value, host);
580
581 return;
582 case PlaybackAudioFeature:
583 SettingsManager::setOption(SettingsManager::Permissions_EnableMediaPlaybackAudioOption, value, host);
584
585 return;
586 default:
587 return;
588 }
589 }
590
setOption(int identifier,const QVariant & value)591 void WebWidget::setOption(int identifier, const QVariant &value)
592 {
593 if (value == m_options.value(identifier))
594 {
595 return;
596 }
597
598 if (value.isNull())
599 {
600 m_options.remove(identifier);
601 }
602 else
603 {
604 m_options[identifier] = value;
605 }
606
607 SessionsManager::markSessionAsModified();
608
609 switch (identifier)
610 {
611 case SettingsManager::Content_PageReloadTimeOption:
612 {
613 const int reloadTime(value.toInt());
614
615 emit arbitraryActionsStateChanged({ActionsManager::ResetQuickPreferencesAction});
616 emit optionChanged(identifier, (value.isNull() ? getOption(identifier) : value));
617
618 if (m_reloadTimer != 0)
619 {
620 killTimer(m_reloadTimer);
621
622 m_reloadTimer = 0;
623 }
624
625 if (reloadTime >= 0)
626 {
627 triggerAction(ActionsManager::StopScheduledReloadAction);
628
629 if (reloadTime > 0)
630 {
631 m_reloadTimer = startTimer(reloadTime * 1000);
632 }
633 }
634 }
635
636 break;
637 case SettingsManager::Network_EnableReferrerOption:
638 emit arbitraryActionsStateChanged({ActionsManager::EnableReferrerAction});
639
640 break;
641 case SettingsManager::Permissions_EnableJavaScriptOption:
642 emit arbitraryActionsStateChanged({ActionsManager::EnableJavaScriptAction});
643
644 break;
645 default:
646 break;
647 }
648 }
649
setOptions(const QHash<int,QVariant> & options,const QStringList & excludedOptions)650 void WebWidget::setOptions(const QHash<int, QVariant> &options, const QStringList &excludedOptions)
651 {
652 const QList<int> identifiers((m_options.keys() + options.keys()).toSet().toList());
653
654 m_options = options;
655
656 for (int i = 0; i < excludedOptions.count(); ++i)
657 {
658 const int identifier(SettingsManager::getOptionIdentifier(excludedOptions.at(i)));
659
660 if (identifier >= 0 && m_options.contains(identifier))
661 {
662 m_options.remove(identifier);
663 }
664 }
665
666 const QString host(Utils::extractHost(getUrl()));
667
668 for (int i = 0; i < identifiers.count(); ++i)
669 {
670 if (m_options.contains(identifiers.at(i)))
671 {
672 emit optionChanged(identifiers.at(i), m_options[identifiers.at(i)]);
673 }
674 else
675 {
676 emit optionChanged(identifiers.at(i), SettingsManager::getOption(identifiers.at(i), host));
677 }
678 }
679
680 emit arbitraryActionsStateChanged({ActionsManager::ResetQuickPreferencesAction});
681 }
682
setRequestedUrl(const QUrl & url,bool isTyped,bool onlyUpdate)683 void WebWidget::setRequestedUrl(const QUrl &url, bool isTyped, bool onlyUpdate)
684 {
685 m_requestedUrl = url;
686
687 if (onlyUpdate)
688 {
689 emit urlChanged(url);
690 }
691 else
692 {
693 setUrl(url, isTyped);
694 }
695 }
696
setWindowIdentifier(quint64 identifier)697 void WebWidget::setWindowIdentifier(quint64 identifier)
698 {
699 m_windowIdentifier = identifier;
700 }
701
getInspector()702 QWidget* WebWidget::getInspector()
703 {
704 return nullptr;
705 }
706
getViewport()707 QWidget* WebWidget::getViewport()
708 {
709 return this;
710 }
711
getBackend() const712 WebBackend* WebWidget::getBackend() const
713 {
714 return m_backend;
715 }
716
getDescription() const717 QString WebWidget::getDescription() const
718 {
719 return {};
720 }
721
suggestSaveFileName(const QString & extension) const722 QString WebWidget::suggestSaveFileName(const QString &extension) const
723 {
724 const QUrl url(getUrl());
725 QString fileName(url.fileName());
726
727 if (fileName.isEmpty() && !url.path().isEmpty() && url.path() != QLatin1String("/"))
728 {
729 fileName = QDir(url.path()).dirName();
730 }
731
732 if (fileName.isEmpty() && !url.host().isEmpty())
733 {
734 fileName = url.host() + extension;
735 }
736
737 if (fileName.isEmpty())
738 {
739 fileName = QLatin1String("file") + extension;
740 }
741
742 if (!fileName.contains(QLatin1Char('.')) && !extension.isEmpty())
743 {
744 fileName.append(extension);
745 }
746
747 return fileName;
748 }
749
suggestSaveFileName(SaveFormat format) const750 QString WebWidget::suggestSaveFileName(SaveFormat format) const
751 {
752 switch (format)
753 {
754 case MhtmlSaveFormat:
755 return suggestSaveFileName(QLatin1String(".mht"));
756 case PdfSaveFormat:
757 return suggestSaveFileName(QLatin1String(".pdf"));
758 case SingleFileSaveFormat:
759 return suggestSaveFileName(QLatin1String(".html"));
760 default:
761 break;
762 }
763
764 return suggestSaveFileName({});
765 }
766
getSavePath(const QVector<SaveFormat> & allowedFormats,SaveFormat * selectedFormat) const767 QString WebWidget::getSavePath(const QVector<SaveFormat> &allowedFormats, SaveFormat *selectedFormat) const
768 {
769 const QMap<SaveFormat, QString> formats({{SingleFileSaveFormat, tr("HTML file (*.html *.htm)")}, {CompletePageSaveFormat, tr("HTML file with all resources (*.html *.htm)")}, {MhtmlSaveFormat, tr("Web archive (*.mht)")}, {PdfSaveFormat, tr("PDF document (*.pdf)")}});
770 QStringList filters;
771 filters.reserve(allowedFormats.count());
772
773 for (int i = 0; i < allowedFormats.count(); ++i)
774 {
775 filters.append(formats.value(allowedFormats.at(i)));
776 }
777
778 const SaveInformation result(Utils::getSavePath(suggestSaveFileName(SingleFileSaveFormat), {}, filters));
779
780 if (!result.canSave)
781 {
782 return {};
783 }
784
785 *selectedFormat = formats.key(result.filter);
786
787 return result.path;
788 }
789
getOpenActionText(SessionsManager::OpenHints hints) const790 QString WebWidget::getOpenActionText(SessionsManager::OpenHints hints) const
791 {
792 if (hints == SessionsManager::CurrentTabOpen)
793 {
794 return QCoreApplication::translate("actions", "Open in This Tab");
795 }
796
797 if (hints == SessionsManager::NewTabOpen)
798 {
799 return QCoreApplication::translate("actions", "Open in New Tab");
800 }
801
802 if (hints == (SessionsManager::NewTabOpen | SessionsManager::BackgroundOpen))
803 {
804 return QCoreApplication::translate("actions", "Open in New Background Tab");
805 }
806
807 if (hints == SessionsManager::NewWindowOpen)
808 {
809 return QCoreApplication::translate("actions", "Open in New Window");
810 }
811
812 if (hints == (SessionsManager::NewWindowOpen | SessionsManager::BackgroundOpen))
813 {
814 return QCoreApplication::translate("actions", "Open in New Background Window");
815 }
816
817 if (hints == (SessionsManager::NewTabOpen | SessionsManager::PrivateOpen))
818 {
819 return QCoreApplication::translate("actions", "Open in New Private Tab");
820 }
821
822 if (hints == (SessionsManager::NewTabOpen | SessionsManager::BackgroundOpen | SessionsManager::PrivateOpen))
823 {
824 return QCoreApplication::translate("actions", "Open in New Private Background Tab");
825 }
826
827 if (hints == (SessionsManager::NewWindowOpen | SessionsManager::PrivateOpen))
828 {
829 return QCoreApplication::translate("actions", "Open in New Private Window");
830 }
831
832 if (hints == (SessionsManager::NewWindowOpen | SessionsManager::BackgroundOpen | SessionsManager::PrivateOpen))
833 {
834 return QCoreApplication::translate("actions", "Open in New Private Background Window");
835 }
836
837 return QCoreApplication::translate("actions", "Open");
838 }
839
getFastForwardScript(bool isSelectingTheBestLink)840 QString WebWidget::getFastForwardScript(bool isSelectingTheBestLink)
841 {
842 QString script(m_fastForwardScript);
843
844 if (m_fastForwardScript.isEmpty())
845 {
846 IniSettings settings(SessionsManager::getReadableDataPath(QLatin1String("fastforward.ini")));
847 QFile file(SessionsManager::getReadableDataPath(QLatin1String("fastforward.js")));
848
849 if (!file.open(QIODevice::ReadOnly))
850 {
851 return {};
852 }
853
854 script = file.readAll();
855
856 file.close();
857
858 const QStringList categories({QLatin1String("Href"), QLatin1String("Class"), QLatin1String("Id"), QLatin1String("Text")});
859
860 for (int i = 0; i < categories.count(); ++i)
861 {
862 settings.beginGroup(categories.at(i));
863
864 const QStringList keys(settings.getKeys());
865 QJsonArray tokensArray;
866
867 for (int j = 0; j < keys.count(); ++j)
868 {
869 tokensArray.append(QJsonObject({{QLatin1Literal("value"), keys.at(j).toUpper()}, {QLatin1Literal("score"), settings.getValue(keys.at(j)).toInt()}}));
870 }
871
872 settings.endGroup();
873
874 script.replace(QLatin1Char('{') + categories.at(i).toLower() + QLatin1String("Tokens}"), QString::fromUtf8(QJsonDocument(tokensArray).toJson(QJsonDocument::Compact)));
875 }
876
877 m_fastForwardScript = script;
878 }
879
880 return script.replace(QLatin1String("{isSelectingTheBestLink}"), (isSelectingTheBestLink ? QLatin1String("true") : QLatin1String("false")));
881 }
882
getActiveStyleSheet() const883 QString WebWidget::getActiveStyleSheet() const
884 {
885 return {};
886 }
887
getCharacterEncoding() const888 QString WebWidget::getCharacterEncoding() const
889 {
890 return {};
891 }
892
getSelectedText() const893 QString WebWidget::getSelectedText() const
894 {
895 return {};
896 }
897
getStatusMessage() const898 QString WebWidget::getStatusMessage() const
899 {
900 return (m_statusMessageOverride.isEmpty() ? m_statusMessage : m_statusMessageOverride);
901 }
902
getOption(int identifier,const QUrl & url) const903 QVariant WebWidget::getOption(int identifier, const QUrl &url) const
904 {
905 if (m_options.contains(identifier))
906 {
907 return m_options[identifier];
908 }
909
910 return SettingsManager::getOption(identifier, Utils::extractHost(url.isEmpty() ? getUrl() : url));
911 }
912
getPageInformation(PageInformation key) const913 QVariant WebWidget::getPageInformation(PageInformation key) const
914 {
915 if (key == LoadingTimeInformation)
916 {
917 return m_loadingTime;
918 }
919
920 return {};
921 }
922
getRequestedUrl() const923 QUrl WebWidget::getRequestedUrl() const
924 {
925 return ((getUrl().isEmpty() || getLoadingState() == OngoingLoadingState) ? m_requestedUrl : getUrl());
926 }
927
createThumbnail(const QSize & size)928 QPixmap WebWidget::createThumbnail(const QSize &size)
929 {
930 Q_UNUSED(size)
931
932 return {};
933 }
934
getClickPosition() const935 QPoint WebWidget::getClickPosition() const
936 {
937 return m_clickPosition;
938 }
939
getGeometry(bool excludeScrollBars) const940 QRect WebWidget::getGeometry(bool excludeScrollBars) const
941 {
942 Q_UNUSED(excludeScrollBars)
943
944 return geometry();
945 }
946
getActionState(int identifier,const QVariantMap & parameters) const947 ActionsManager::ActionDefinition::State WebWidget::getActionState(int identifier, const QVariantMap ¶meters) const
948 {
949 ActionsManager::ActionDefinition::State state(ActionsManager::getActionDefinition(identifier).getDefaultState());
950
951 switch (identifier)
952 {
953 case ActionsManager::ClearTabHistoryAction:
954 state.isEnabled = !getHistory().isEmpty();
955
956 if (parameters.value(QLatin1String("clearGlobalHistory"), false).toBool())
957 {
958 state.text = QCoreApplication::translate("actions", "Purge Tab History");
959 }
960
961 break;
962 case ActionsManager::PurgeTabHistoryAction:
963 state.isEnabled = !getHistory().isEmpty();
964
965 break;
966 case ActionsManager::OpenLinkAction:
967 case ActionsManager::OpenLinkInCurrentTabAction:
968 case ActionsManager::OpenLinkInNewTabAction:
969 case ActionsManager::OpenLinkInNewTabBackgroundAction:
970 case ActionsManager::OpenLinkInNewWindowAction:
971 case ActionsManager::OpenLinkInNewWindowBackgroundAction:
972 case ActionsManager::OpenLinkInNewPrivateTabAction:
973 case ActionsManager::OpenLinkInNewPrivateTabBackgroundAction:
974 case ActionsManager::OpenLinkInNewPrivateWindowAction:
975 case ActionsManager::OpenLinkInNewPrivateWindowBackgroundAction:
976 case ActionsManager::CopyLinkToClipboardAction:
977 case ActionsManager::SaveLinkToDiskAction:
978 case ActionsManager::SaveLinkToDownloadsAction:
979 state.isEnabled = m_hitResult.linkUrl.isValid();
980
981 if (identifier == ActionsManager::OpenLinkAction && parameters.contains(QLatin1String("hints")))
982 {
983 const SessionsManager::OpenHints hints(SessionsManager::calculateOpenHints(parameters));
984
985 state.text = getOpenActionText(hints);
986
987 if (hints != SessionsManager::DefaultOpen)
988 {
989 state.icon = {};
990 }
991 }
992
993 break;
994 case ActionsManager::BookmarkLinkAction:
995 state.text = (BookmarksManager::hasBookmark(m_hitResult.linkUrl) ? QCoreApplication::translate("actions", "Edit Link Bookmark…") : QCoreApplication::translate("actions", "Bookmark Link…"));
996 state.isEnabled = m_hitResult.linkUrl.isValid();
997
998 break;
999 case ActionsManager::OpenFrameAction:
1000 case ActionsManager::OpenFrameInCurrentTabAction:
1001 case ActionsManager::OpenFrameInNewTabAction:
1002 case ActionsManager::OpenFrameInNewTabBackgroundAction:
1003 case ActionsManager::CopyFrameLinkToClipboardAction:
1004 case ActionsManager::ReloadFrameAction:
1005 case ActionsManager::ViewFrameSourceAction:
1006 state.isEnabled = m_hitResult.frameUrl.isValid();
1007
1008 if (identifier == ActionsManager::OpenFrameAction && parameters.contains(QLatin1String("hints")))
1009 {
1010 state.text = getOpenActionText(SessionsManager::calculateOpenHints(parameters));
1011 }
1012
1013 break;
1014 case ActionsManager::OpenImageAction:
1015 case ActionsManager::OpenImageInNewTabAction:
1016 case ActionsManager::OpenImageInNewTabBackgroundAction:
1017 if (m_hitResult.imageUrl.isValid())
1018 {
1019 const QString fileName((m_hitResult.imageUrl.scheme() == QLatin1String("data")) ? QString() : fontMetrics().elidedText(m_hitResult.imageUrl.fileName(), Qt::ElideMiddle, 256));
1020
1021 if (identifier == ActionsManager::OpenImageAction)
1022 {
1023 const SessionsManager::OpenHints hints(SessionsManager::calculateOpenHints(parameters));
1024
1025 if (hints == SessionsManager::CurrentTabOpen)
1026 {
1027 state.text = QCoreApplication::translate("actions", "Open Image in This Tab");
1028 }
1029 else if (hints == SessionsManager::NewTabOpen)
1030 {
1031 state.text = QCoreApplication::translate("actions", "Open Image in New Tab");
1032 }
1033 else if (hints == (SessionsManager::NewTabOpen | SessionsManager::BackgroundOpen))
1034 {
1035 state.text = QCoreApplication::translate("actions", "Open Image in New Background Tab");
1036 }
1037 else if (hints == SessionsManager::NewWindowOpen)
1038 {
1039 state.text = QCoreApplication::translate("actions", "Open Image in New Window");
1040 }
1041 else if (hints == (SessionsManager::NewWindowOpen | SessionsManager::BackgroundOpen))
1042 {
1043 state.text = QCoreApplication::translate("actions", "Open Image in New Background Window");
1044 }
1045 else if (hints == (SessionsManager::NewTabOpen | SessionsManager::PrivateOpen))
1046 {
1047 state.text = QCoreApplication::translate("actions", "Open Image in New Private Tab");
1048 }
1049 else if (hints == (SessionsManager::NewTabOpen | SessionsManager::BackgroundOpen | SessionsManager::PrivateOpen))
1050 {
1051 state.text = QCoreApplication::translate("actions", "Open Image in New Private Background Tab");
1052 }
1053 else if (hints == (SessionsManager::NewWindowOpen | SessionsManager::PrivateOpen))
1054 {
1055 state.text = QCoreApplication::translate("actions", "Open Image in New Private Window");
1056 }
1057 else if (hints == (SessionsManager::NewWindowOpen | SessionsManager::BackgroundOpen | SessionsManager::PrivateOpen))
1058 {
1059 state.text = QCoreApplication::translate("actions", "Open Image in New Private Background Window");
1060 }
1061
1062 if (!fileName.isEmpty())
1063 {
1064 state.text.append(QLatin1String(" (") + fileName + QLatin1Char(')'));
1065 }
1066 }
1067 else if (!fileName.isEmpty())
1068 {
1069 if (identifier == ActionsManager::OpenImageInNewTabBackgroundAction)
1070 {
1071 state.text = tr("Open Image in New Background Tab (%1)").arg(fileName);
1072 }
1073 else
1074 {
1075 state.text = tr("Open Image in New Tab (%1)").arg(fileName);
1076 }
1077 }
1078
1079 state.isEnabled = !getUrl().matches(m_hitResult.imageUrl, (QUrl::NormalizePathSegments | QUrl::RemoveFragment | QUrl::StripTrailingSlash));
1080 }
1081 else
1082 {
1083 state.isEnabled = false;
1084 }
1085
1086 break;
1087 case ActionsManager::SaveImageToDiskAction:
1088 case ActionsManager::CopyImageToClipboardAction:
1089 case ActionsManager::CopyImageUrlToClipboardAction:
1090 case ActionsManager::ReloadImageAction:
1091 case ActionsManager::ImagePropertiesAction:
1092 state.isEnabled = m_hitResult.imageUrl.isValid();
1093
1094 break;
1095 case ActionsManager::SaveMediaToDiskAction:
1096 state.text = ((m_hitResult.tagName == QLatin1String("video")) ? QCoreApplication::translate("actions", "Save Video…") : QCoreApplication::translate("actions", "Save Audio…"));
1097 state.isEnabled = m_hitResult.mediaUrl.isValid();
1098
1099 break;
1100 case ActionsManager::CopyMediaUrlToClipboardAction:
1101 state.text = ((m_hitResult.tagName == QLatin1String("video")) ? QCoreApplication::translate("actions", "Copy Video Link to Clipboard") : QCoreApplication::translate("actions", "Copy Audio Link to Clipboard"));
1102 state.isEnabled = m_hitResult.mediaUrl.isValid();
1103
1104 break;
1105 case ActionsManager::MediaControlsAction:
1106 state.isChecked = m_hitResult.flags.testFlag(HitTestResult::MediaHasControlsTest);
1107 state.isEnabled = m_hitResult.mediaUrl.isValid();
1108
1109 break;
1110 case ActionsManager::MediaLoopAction:
1111 state.isChecked = m_hitResult.flags.testFlag(HitTestResult::MediaIsLoopedTest);
1112 state.isEnabled = m_hitResult.mediaUrl.isValid();
1113
1114 break;
1115 case ActionsManager::MediaPlayPauseAction:
1116 state.text = (m_hitResult.flags.testFlag(HitTestResult::MediaIsPausedTest) ? QCoreApplication::translate("actions", "Play") : QCoreApplication::translate("actions", "Pause"));
1117 state.icon = ThemesManager::createIcon(m_hitResult.flags.testFlag(HitTestResult::MediaIsPausedTest) ? QLatin1String("media-playback-start") : QLatin1String("media-playback-pause"));
1118 state.isEnabled = m_hitResult.mediaUrl.isValid();
1119
1120 break;
1121 case ActionsManager::MediaMuteAction:
1122 state.text = (m_hitResult.flags.testFlag(HitTestResult::MediaIsMutedTest) ? QCoreApplication::translate("actions", "Unmute") : QCoreApplication::translate("actions", "Mute"));
1123 state.icon = ThemesManager::createIcon(m_hitResult.flags.testFlag(HitTestResult::MediaIsMutedTest) ? QLatin1String("audio-volume-medium") : QLatin1String("audio-volume-muted"));
1124 state.isEnabled = m_hitResult.mediaUrl.isValid();
1125
1126 break;
1127 case ActionsManager::MediaPlaybackRateAction:
1128 {
1129 const qreal rate(parameters.value(QLatin1String("rate")).toReal());
1130
1131 state.text = tr("Playback Rate: %1x").arg(QLocale().toString(rate));
1132 state.isChecked = qFuzzyCompare(rate, m_hitResult.playbackRate);
1133 state.isEnabled = m_hitResult.mediaUrl.isValid();
1134 }
1135
1136 break;
1137 case ActionsManager::FillPasswordAction:
1138 state.isEnabled = (!Utils::isUrlEmpty(getUrl()) && PasswordsManager::hasPasswords(getUrl(), PasswordsManager::FormPassword));
1139
1140 break;
1141 case ActionsManager::MuteTabMediaAction:
1142 state.icon = ThemesManager::createIcon(isAudioMuted() ? QLatin1String("audio-volume-muted") : QLatin1String("audio-volume-medium"));
1143 state.text = (isAudioMuted() ? QCoreApplication::translate("actions", "Unmute Tab Media") : QCoreApplication::translate("actions", "Mute Tab Media"));
1144
1145 break;
1146 case ActionsManager::GoBackAction:
1147 case ActionsManager::RewindAction:
1148 state.isEnabled = canGoBack();
1149
1150 break;
1151 case ActionsManager::GoForwardAction:
1152 state.isEnabled = canGoForward();
1153
1154 break;
1155 case ActionsManager::GoToHistoryIndexAction:
1156 if (parameters.contains(QLatin1String("index")))
1157 {
1158 const WindowHistoryInformation history(getHistory());
1159 const int index(parameters[QLatin1String("index")].toInt());
1160
1161 if (index >= 0 && index < history.entries.count())
1162 {
1163 state.icon = HistoryManager::getIcon(QUrl(history.entries.at(index).url));
1164 state.text = history.entries.at(index).getTitle().replace(QLatin1Char('&'), QLatin1String("&&"));
1165 state.isEnabled = true;
1166 }
1167 }
1168
1169 break;
1170 case ActionsManager::FastForwardAction:
1171 state.isEnabled = canFastForward();
1172
1173 break;
1174 case ActionsManager::RemoveHistoryIndexAction:
1175 if (parameters.value(QLatin1String("clearGlobalHistory"), false).toBool())
1176 {
1177 state.text = QCoreApplication::translate("actions", "Purge History Entry");
1178 }
1179
1180 if (parameters.contains(QLatin1String("index")))
1181 {
1182 const int index(parameters[QLatin1String("index")].toInt());
1183
1184 if (index >= 0 && index < getHistory().entries.count())
1185 {
1186 state.isEnabled = true;
1187 }
1188 }
1189
1190 break;
1191 case ActionsManager::StopAction:
1192 state.isEnabled = (getLoadingState() == OngoingLoadingState);
1193
1194 break;
1195 case ActionsManager::ReloadAction:
1196 state.isEnabled = (getLoadingState() != OngoingLoadingState);
1197
1198 break;
1199 case ActionsManager::ReloadOrStopAction:
1200 state = getActionState((getLoadingState() == OngoingLoadingState) ? ActionsManager::StopAction : ActionsManager::ReloadAction);
1201
1202 break;
1203 case ActionsManager::ScheduleReloadAction:
1204 if (!parameters.contains(QLatin1String("time")) || (parameters.contains(QLatin1String("time")) && parameters[QLatin1String("time")].type() == QVariant::String && parameters[QLatin1String("time")].toString() == QLatin1String("custom")))
1205 {
1206 state.isChecked = (m_options.contains(SettingsManager::Content_PageReloadTimeOption) && !QVector<int>({-1, 0, 60, 1800, 3600, 7200}).contains(m_options[SettingsManager::Content_PageReloadTimeOption].toInt()));
1207 }
1208 else if (parameters.contains(QLatin1String("time")) && parameters[QLatin1String("time")].type() != QVariant::String)
1209 {
1210 const int reloadTime(parameters[QLatin1String("time")].toInt());
1211
1212 if (reloadTime < 0)
1213 {
1214 state.isChecked = (!m_options.contains(SettingsManager::Content_PageReloadTimeOption) || m_options[SettingsManager::Content_PageReloadTimeOption].toInt() < 0);
1215 state.text = tr("Page Default");
1216 }
1217 else
1218 {
1219 state.isChecked = (m_options.contains(SettingsManager::Content_PageReloadTimeOption) && reloadTime == m_options[SettingsManager::Content_PageReloadTimeOption].toInt());
1220
1221 if (reloadTime == 0)
1222 {
1223 state.text = tr("Never Reload");
1224 }
1225 else
1226 {
1227 state.text = tr("Reload Every: %n second(s)", "", reloadTime);
1228 }
1229 }
1230 }
1231
1232 break;
1233 case ActionsManager::UndoAction:
1234 state.isEnabled = canUndo();
1235
1236 break;
1237 case ActionsManager::RedoAction:
1238 state.isEnabled = canRedo();
1239
1240 break;
1241 case ActionsManager::CutAction:
1242 state.isEnabled = (this->hasSelection() && !getSelectedText().trimmed().isEmpty() && m_hitResult.flags.testFlag(HitTestResult::IsContentEditableTest));
1243
1244 break;
1245 case ActionsManager::CopyAction:
1246 case ActionsManager::CopyPlainTextAction:
1247 case ActionsManager::CopyToNoteAction:
1248 case ActionsManager::UnselectAction:
1249 state.isEnabled = (this->hasSelection() && !getSelectedText().trimmed().isEmpty());
1250
1251 break;
1252 case ActionsManager::PasteAction:
1253 state.isEnabled = (m_hitResult.flags.testFlag(HitTestResult::IsContentEditableTest) && (parameters.contains(QLatin1String("note")) || parameters.contains(QLatin1String("text")) || (QApplication::clipboard()->mimeData() && QApplication::clipboard()->mimeData()->hasText())));
1254
1255 break;
1256 case ActionsManager::PasteAndGoAction:
1257 state.isEnabled = (QApplication::clipboard()->mimeData() && QApplication::clipboard()->mimeData()->hasText());
1258
1259 break;
1260 case ActionsManager::DeleteAction:
1261 state.isEnabled = (m_hitResult.flags.testFlag(HitTestResult::IsContentEditableTest) && !m_hitResult.flags.testFlag(HitTestResult::IsEmptyTest) && this->hasSelection() && !getSelectedText().trimmed().isEmpty());
1262
1263 break;
1264 case ActionsManager::SelectAllAction:
1265 state.isEnabled = !m_hitResult.flags.testFlag(HitTestResult::IsEmptyTest);
1266
1267 break;
1268 case ActionsManager::ClearAllAction:
1269 state.isEnabled = (m_hitResult.flags.testFlag(HitTestResult::IsContentEditableTest) && !m_hitResult.flags.testFlag(HitTestResult::IsEmptyTest));
1270
1271 break;
1272 case ActionsManager::CheckSpellingAction:
1273 {
1274 const QVector<SpellCheckManager::DictionaryInformation> dictionaries(getDictionaries());
1275
1276 state.isEnabled = (getOption(SettingsManager::Browser_EnableSpellCheckOption, getUrl()).toBool() && !dictionaries.isEmpty());
1277
1278 if (parameters.contains(QLatin1String("dictionary")))
1279 {
1280 const QString dictionary(parameters[QLatin1String("dictionary")].toString());
1281
1282 state.text = dictionary;
1283 state.isChecked = (dictionary == (getOption(SettingsManager::Browser_SpellCheckDictionaryOption).isNull() ? SpellCheckManager::getDefaultDictionary() : getOption(SettingsManager::Browser_SpellCheckDictionaryOption).toString()));
1284
1285 for (int i = 0; i < dictionaries.count(); ++i)
1286 {
1287 if (dictionaries.at(i).name == dictionary)
1288 {
1289 state.text = dictionaries.at(i).title;
1290
1291 break;
1292 }
1293 }
1294 }
1295 else
1296 {
1297 state.isChecked = (m_hitResult.flags.testFlag(HitTestResult::IsSpellCheckEnabled));
1298 }
1299 }
1300
1301 break;
1302 case ActionsManager::SearchAction:
1303 {
1304 const SearchEnginesManager::SearchEngineDefinition searchEngine(SearchEnginesManager::getSearchEngine(parameters.contains(QLatin1String("searchEngine")) ? parameters[QLatin1String("searchEngine")].toString() : getOption(SettingsManager::Search_DefaultQuickSearchEngineOption).toString()));
1305
1306 state.text = (searchEngine.isValid() ? searchEngine.title : QCoreApplication::translate("actions", "Search"));
1307 state.icon = (searchEngine.icon.isNull() ? ThemesManager::createIcon(QLatin1String("edit-find")) : searchEngine.icon);
1308 state.isEnabled = searchEngine.isValid();
1309 }
1310
1311 break;
1312 case ActionsManager::CreateSearchAction:
1313 state.isEnabled = m_hitResult.flags.testFlag(HitTestResult::IsFormTest);
1314
1315 break;
1316 case ActionsManager::TakeScreenshotAction:
1317 state.isEnabled = canTakeScreenshot();
1318
1319 break;
1320 case ActionsManager::BookmarkPageAction:
1321 state.text = (BookmarksManager::hasBookmark(getUrl()) ? QCoreApplication::translate("actions", "Edit Bookmark…") : QCoreApplication::translate("actions", "Add Bookmark…"));
1322
1323 break;
1324 case ActionsManager::LoadPluginsAction:
1325 state.isEnabled = (getAmountOfDeferredPlugins() > 0);
1326
1327 break;
1328 case ActionsManager::EnableJavaScriptAction:
1329 state.isChecked = getOption(SettingsManager::Permissions_EnableJavaScriptOption, getUrl()).toBool();
1330
1331 break;
1332 case ActionsManager::EnableReferrerAction:
1333 state.isChecked = getOption(SettingsManager::Network_EnableReferrerOption, getUrl()).toBool();
1334
1335 break;
1336 case ActionsManager::ViewSourceAction:
1337 state.isEnabled = canViewSource();
1338
1339 break;
1340 case ActionsManager::InspectPageAction:
1341 state.isChecked = isInspecting();
1342 state.isEnabled = canInspect();
1343
1344 break;
1345 case ActionsManager::InspectElementAction:
1346 state.isEnabled = canInspect();
1347
1348 break;
1349 case ActionsManager::WebsitePreferencesAction:
1350 state.isEnabled = (!Utils::isUrlEmpty(getUrl()) && getUrl().scheme() != QLatin1String("about"));
1351
1352 break;
1353 case ActionsManager::ResetQuickPreferencesAction:
1354 state.isEnabled = !m_options.isEmpty();
1355
1356 break;
1357 default:
1358 break;
1359 }
1360
1361 return state;
1362 }
1363
getActiveFrame() const1364 WebWidget::LinkUrl WebWidget::getActiveFrame() const
1365 {
1366 return {};
1367 }
1368
getActiveImage() const1369 WebWidget::LinkUrl WebWidget::getActiveImage() const
1370 {
1371 return {};
1372 }
1373
getActiveLink() const1374 WebWidget::LinkUrl WebWidget::getActiveLink() const
1375 {
1376 return {};
1377 }
1378
getActiveMedia() const1379 WebWidget::LinkUrl WebWidget::getActiveMedia() const
1380 {
1381 return {};
1382 }
1383
getSslInformation() const1384 WebWidget::SslInformation WebWidget::getSslInformation() const
1385 {
1386 return SslInformation();
1387 }
1388
getStyleSheets() const1389 QStringList WebWidget::getStyleSheets() const
1390 {
1391 return {};
1392 }
1393
getDictionaries() const1394 QVector<SpellCheckManager::DictionaryInformation> WebWidget::getDictionaries() const
1395 {
1396 return SpellCheckManager::getDictionaries();
1397 }
1398
getFeeds() const1399 QVector<WebWidget::LinkUrl> WebWidget::getFeeds() const
1400 {
1401 return {};
1402 }
1403
getLinks() const1404 QVector<WebWidget::LinkUrl> WebWidget::getLinks() const
1405 {
1406 return {};
1407 }
1408
getSearchEngines() const1409 QVector<WebWidget::LinkUrl> WebWidget::getSearchEngines() const
1410 {
1411 return {};
1412 }
1413
getBlockedRequests() const1414 QVector<NetworkManager::ResourceInformation> WebWidget::getBlockedRequests() const
1415 {
1416 return {};
1417 }
1418
getOptions() const1419 QHash<int, QVariant> WebWidget::getOptions() const
1420 {
1421 return m_options;
1422 }
1423
getHeaders() const1424 QMap<QByteArray, QByteArray> WebWidget::getHeaders() const
1425 {
1426 return {};
1427 }
1428
getMetaData() const1429 QMultiMap<QString, QString> WebWidget::getMetaData() const
1430 {
1431 return {};
1432 }
1433
getCurrentHitTestResult() const1434 WebWidget::HitTestResult WebWidget::getCurrentHitTestResult() const
1435 {
1436 return m_hitResult;
1437 }
1438
getHitTestResult(const QPoint & position)1439 WebWidget::HitTestResult WebWidget::getHitTestResult(const QPoint &position)
1440 {
1441 Q_UNUSED(position)
1442
1443 return {};
1444 }
1445
getContentState() const1446 WebWidget::ContentStates WebWidget::getContentState() const
1447 {
1448 const QUrl url(getUrl());
1449
1450 if (url.isEmpty() || url.scheme() == QLatin1String("about"))
1451 {
1452 return ApplicationContentState;
1453 }
1454
1455 if (url.scheme() == QLatin1String("file"))
1456 {
1457 return LocalContentState;
1458 }
1459
1460 ContentStates state(RemoteContentState);
1461
1462 if (getOption(SettingsManager::Security_EnableFraudCheckingOption, url).toBool() && ContentFiltersManager::isFraud(url))
1463 {
1464 state |= FraudContentState;
1465 }
1466
1467 return state;
1468 }
1469
getPermission(FeaturePermission feature,const QUrl & url) const1470 WebWidget::PermissionPolicy WebWidget::getPermission(FeaturePermission feature, const QUrl &url) const
1471 {
1472 if (!url.isValid())
1473 {
1474 return DeniedPermission;
1475 }
1476
1477 QString value;
1478
1479 switch (feature)
1480 {
1481 case FullScreenFeature:
1482 value = getOption(SettingsManager::Permissions_EnableFullScreenOption, url).toString();
1483
1484 break;
1485 case GeolocationFeature:
1486 value = getOption(SettingsManager::Permissions_EnableGeolocationOption, url).toString();
1487
1488 break;
1489 case NotificationsFeature:
1490 value = getOption(SettingsManager::Permissions_EnableNotificationsOption, url).toString();
1491
1492 break;
1493 case PointerLockFeature:
1494 value = getOption(SettingsManager::Permissions_EnablePointerLockOption, url).toString();
1495
1496 break;
1497 case CaptureAudioFeature:
1498 value = getOption(SettingsManager::Permissions_EnableMediaCaptureAudioOption, url).toString();
1499
1500 break;
1501 case CaptureVideoFeature:
1502 value = getOption(SettingsManager::Permissions_EnableMediaCaptureVideoOption, url).toString();
1503
1504 break;
1505 case CaptureAudioVideoFeature:
1506 {
1507 const QString captureAudioValue(getOption(SettingsManager::Permissions_EnableMediaCaptureAudioOption, url).toString());
1508 const QString captureVideoValue(getOption(SettingsManager::Permissions_EnableMediaCaptureVideoOption, url).toString());
1509
1510 if (captureAudioValue == QLatin1String("allow") && captureVideoValue == QLatin1String("allow"))
1511 {
1512 value = QLatin1String("allow");
1513 }
1514 else if (captureAudioValue == QLatin1String("disallow") || captureVideoValue == QLatin1String("disallow"))
1515 {
1516 value = QLatin1String("disallow");
1517 }
1518 else
1519 {
1520 value = QLatin1String("ask");
1521 }
1522 }
1523
1524 break;
1525 case PlaybackAudioFeature:
1526 value = getOption(SettingsManager::Permissions_EnableMediaPlaybackAudioOption, url).toString();
1527
1528 break;
1529 default:
1530 return DeniedPermission;
1531 }
1532
1533 if (value == QLatin1String("allow"))
1534 {
1535 return GrantedPermission;
1536 }
1537
1538 if (value == QLatin1String("disallow"))
1539 {
1540 return DeniedPermission;
1541 }
1542
1543 return KeepAskingPermission;
1544 }
1545
getWindowIdentifier() const1546 quint64 WebWidget::getWindowIdentifier() const
1547 {
1548 return m_windowIdentifier;
1549 }
1550
getAmountOfDeferredPlugins() const1551 int WebWidget::getAmountOfDeferredPlugins() const
1552 {
1553 return 0;
1554 }
1555
canGoBack() const1556 bool WebWidget::canGoBack() const
1557 {
1558 return false;
1559 }
1560
canGoForward() const1561 bool WebWidget::canGoForward() const
1562 {
1563 return false;
1564 }
1565
canFastForward() const1566 bool WebWidget::canFastForward() const
1567 {
1568 return false;
1569 }
1570
canInspect() const1571 bool WebWidget::canInspect() const
1572 {
1573 return false;
1574 }
1575
canTakeScreenshot() const1576 bool WebWidget::canTakeScreenshot() const
1577 {
1578 return false;
1579 }
1580
canRedo() const1581 bool WebWidget::canRedo() const
1582 {
1583 return false;
1584 }
1585
canUndo() const1586 bool WebWidget::canUndo() const
1587 {
1588 return false;
1589 }
1590
canShowContextMenu(const QPoint & position) const1591 bool WebWidget::canShowContextMenu(const QPoint &position) const
1592 {
1593 Q_UNUSED(position)
1594
1595 return true;
1596 }
1597
canViewSource() const1598 bool WebWidget::canViewSource() const
1599 {
1600 return true;
1601 }
1602
isInspecting() const1603 bool WebWidget::isInspecting() const
1604 {
1605 return false;
1606 }
1607
isPopup() const1608 bool WebWidget::isPopup() const
1609 {
1610 return false;
1611 }
1612
isScrollBar(const QPoint & position) const1613 bool WebWidget::isScrollBar(const QPoint &position) const
1614 {
1615 Q_UNUSED(position)
1616
1617 return false;
1618 }
1619
hasOption(int identifier) const1620 bool WebWidget::hasOption(int identifier) const
1621 {
1622 return m_options.contains(identifier);
1623 }
1624
hasSelection() const1625 bool WebWidget::hasSelection() const
1626 {
1627 return false;
1628 }
1629
hasWatchedChanges(ChangeWatcher watcher) const1630 bool WebWidget::hasWatchedChanges(ChangeWatcher watcher) const
1631 {
1632 Q_UNUSED(watcher)
1633
1634 return false;
1635 }
1636
isAudible() const1637 bool WebWidget::isAudible() const
1638 {
1639 return false;
1640 }
1641
isAudioMuted() const1642 bool WebWidget::isAudioMuted() const
1643 {
1644 return false;
1645 }
1646
isFullScreen() const1647 bool WebWidget::isFullScreen() const
1648 {
1649 return false;
1650 }
1651
isWatchingChanges(ChangeWatcher watcher) const1652 bool WebWidget::isWatchingChanges(ChangeWatcher watcher) const
1653 {
1654 return m_changeWatchers.contains(watcher);
1655 }
1656
1657 }
1658