/* ============================================================ * QupZilla - WebKit based browser * Copyright (C) 2010-2012 David Rosca * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * ============================================================ */ #include "webpage.h" #include "webview.h" #include "tabwidget.h" #include "qupzilla.h" #include "downloadmanager.h" #include "webpluginfactory.h" #include "mainapplication.h" #include "ui_jsconfirm.h" #include "ui_jsalert.h" #include "ui_jsprompt.h" #include "widget.h" #include "globalfunctions.h" #include "pluginproxy.h" #include "speeddial.h" QString WebPage::UserAgent = ""; QString WebPage::m_lastUploadLocation = QDir::homePath(); WebPage::WebPage(WebView* parent, QupZilla* mainClass) : QWebPage(parent) , p_QupZilla(mainClass) , m_view(parent) , m_speedDial(mApp->plugins()->speedDial()) , m_fileWatcher(0) , m_runningLoop(0) , m_blockAlerts(false) , m_secureStatus(false) // , m_isOpeningNextWindowAsNewTab(false) { setForwardUnsupportedContent(true); setPluginFactory(new WebPluginFactory(this)); history()->setMaximumItemCount(20); connect(this, SIGNAL(unsupportedContent(QNetworkReply*)), this, SLOT(handleUnsupportedContent(QNetworkReply*))); // connect(this, SIGNAL(loadStarted()), this, SLOT(loadingStarted())); connect(this, SIGNAL(loadProgress(int)), this, SLOT(progress(int))); connect(this, SIGNAL(loadFinished(bool)), this, SLOT(finished())); connect(m_view, SIGNAL(urlChanged(QUrl)), this, SLOT(urlChanged(QUrl))); connect(mainFrame(), SIGNAL(javaScriptWindowObjectCleared()), this, SLOT(addJavaScriptObject())); connect(this, SIGNAL(printRequested(QWebFrame*)), this, SLOT(printFrame(QWebFrame*))); m_runningLoop = 0; } void WebPage::scheduleAdjustPage() { if (m_view->isLoading()) { m_adjustingScheduled = true; } else { mainFrame()->setZoomFactor(mainFrame()->zoomFactor() + 1); mainFrame()->setZoomFactor(mainFrame()->zoomFactor() - 1); } } void WebPage::urlChanged(const QUrl &url) { Q_UNUSED(url) m_adBlockedEntries.clear(); m_blockAlerts = false; } void WebPage::progress(int prog) { Q_UNUSED(prog) bool secStatus = sslCertificate().isValid(); if (secStatus != m_secureStatus) { m_secureStatus = secStatus; emit privacyChanged(sslCertificate().isValid()); } } void WebPage::finished() { progress(100); if (m_adjustingScheduled) { m_adjustingScheduled = false; mainFrame()->setZoomFactor(mainFrame()->zoomFactor() + 1); mainFrame()->setZoomFactor(mainFrame()->zoomFactor() - 1); } if (mainFrame()->url().scheme() == "file") { if (!m_fileWatcher) { m_fileWatcher = new QFileSystemWatcher(this); connect(m_fileWatcher, SIGNAL(fileChanged(QString)), this, SLOT(watchedFileChanged(QString))); } QString filePath = mainFrame()->url().toLocalFile(); if (!m_fileWatcher->files().contains(filePath)) { m_fileWatcher->addPath(filePath); } } else if (m_fileWatcher) { m_fileWatcher->removePaths(m_fileWatcher->files()); } QTimer::singleShot(100, this, SLOT(cleanBlockedObjects())); } void WebPage::watchedFileChanged(const QString &file) { if (mainFrame()->url().toLocalFile() == file) { triggerAction(QWebPage::Reload); } } void WebPage::printFrame(QWebFrame* frame) { p_QupZilla->printPage(frame); } //void WebPage::loadingStarted() //{ // m_adBlockedEntries.clear(); // m_blockAlerts = false; // m_SslCert.clear(); //} void WebPage::addJavaScriptObject() { if (mainFrame()->url().toString() != "qupzilla:speeddial") { return; } mainFrame()->addToJavaScriptWindowObject("speeddial", m_speedDial); m_speedDial->addWebFrame(mainFrame()); } void WebPage::handleUnsupportedContent(QNetworkReply* reply) { if (!reply) { return; } QUrl url = reply->url(); switch (reply->error()) { case QNetworkReply::NoError: if (reply->header(QNetworkRequest::ContentTypeHeader).isValid()) { DownloadManager* dManager = mApp->downManager(); dManager->handleUnsupportedContent(reply, this); return; } break; case QNetworkReply::ProtocolUnknownError: qDebug() << url << "ProtocolUnknowError"; QDesktopServices::openUrl(url); return; break; default: break; } qDebug() << "WebPage::UnsupportedContent error" << reply->errorString(); } void WebPage::setSSLCertificate(const QSslCertificate &cert) { // if (cert != m_SslCert) -- crashing on linux :-| m_SslCert = cert; } QSslCertificate WebPage::sslCertificate() { if (mainFrame()->url().scheme() == "https" && m_SslCert.subjectInfo(QSslCertificate::CommonName).remove("*").contains(QRegExp(mainFrame()->url().host()))) { return m_SslCert; } else { return QSslCertificate(); } } bool WebPage::acceptNavigationRequest(QWebFrame* frame, const QNetworkRequest &request, NavigationType type) { m_lastRequest = request; m_lastRequestType = type; QString scheme = request.url().scheme(); if (scheme == "mailto" || scheme == "ftp") { QDesktopServices::openUrl(request.url()); return false; } if (type == QWebPage::NavigationTypeFormResubmitted) { bool result = javaScriptConfirm(frame, tr("To show this page, QupZilla must resend request which do it again \n" "(like searching on making an shoping, which has been already done.)")); if (!result) { return false; } } // TabWidget::OpenUrlIn openIn= frame ? TabWidget::CurrentTab: TabWidget::NewTab; bool accept = QWebPage::acceptNavigationRequest(frame, request, type); // if (accept && openIn == TabWidget::NewTab) { // m_isOpeningNextWindowAsNewTab = true; // p_QupZilla->tabWidget()->addView(request.url(),tr("New tab"), openIn); // } return accept; } void WebPage::populateNetworkRequest(QNetworkRequest &request) { WebPage* pagePointer = this; WebView* webViewPointer = m_view; QVariant variant = qVariantFromValue((void*) pagePointer); request.setAttribute((QNetworkRequest::Attribute)(QNetworkRequest::User + 100), variant); request.setAttribute((QNetworkRequest::Attribute)(QNetworkRequest::User + 101), m_lastRequestType); variant = qVariantFromValue((void*) webViewPointer); request.setAttribute((QNetworkRequest::Attribute)(QNetworkRequest::User + 102), variant); } QWebPage* WebPage::createWindow(QWebPage::WebWindowType type) { // if (m_isOpeningNextWindowAsNewTab) // return 0; // m_isOpeningNextWindowAsNewTab = false; // qDebug() << type; // QWebView* view = new QWebView(); // view->show(); // return view->page(); Q_UNUSED(type); int index = p_QupZilla->tabWidget()->addView(QUrl(), tr("New tab"), TabWidget::CleanSelectedPage); return p_QupZilla->weView(index)->page(); } void WebPage::addAdBlockRule(const QString &filter, const QUrl &url) { AdBlockedEntry entry; entry.rule = filter; entry.url = url; if (!m_adBlockedEntries.contains(entry)) { m_adBlockedEntries.append(entry); } } void WebPage::cleanBlockedObjects() { QStringList findingStrings; foreach(AdBlockedEntry entry, m_adBlockedEntries) { if (entry.url.toString().endsWith(".js")) { continue; } findingStrings.append(entry.url.toString()); QUrl mainFrameUrl = mainFrame()->url(); if (entry.url.scheme() == mainFrameUrl.scheme() && entry.url.host() == mainFrameUrl.host()) { //May be relative url QString relativeUrl = qz_makeRelativeUrl(mainFrameUrl, entry.url).toString(); findingStrings.append(relativeUrl); if (relativeUrl.startsWith("/")) { findingStrings.append(relativeUrl.right(relativeUrl.size() - 1)); } } } QWebElement docElement = mainFrame()->documentElement(); QWebElementCollection elements; foreach(QString s, findingStrings) elements.append(docElement.findAll("*[src=\"" + s + "\"]")); foreach(QWebElement element, elements) element.setAttribute("style", "display:none;"); } QString WebPage::userAgentForUrl(const QUrl &url) const { if (UserAgent.isEmpty()) { UserAgent = QWebPage::userAgentForUrl(url); } return UserAgent; } bool WebPage::extension(Extension extension, const ExtensionOption* option, ExtensionReturn* output) { if (extension == ChooseMultipleFilesExtension) { return QWebPage::extension(extension, option, output); } const ErrorPageExtensionOption* exOption = static_cast(option); ErrorPageExtensionReturn* exReturn = static_cast(output); WebPage* erPage = qobject_cast(exOption->frame->page()); QString errorString; if (exOption->domain == QWebPage::QtNetwork) { switch (exOption->error) { case QNetworkReply::ConnectionRefusedError: errorString = tr("Server refused the connection"); break; case QNetworkReply::RemoteHostClosedError: errorString = tr("Server closed the connection"); break; case QNetworkReply::HostNotFoundError: errorString = tr("Server not found"); break; case QNetworkReply::TimeoutError: errorString = tr("Connection timed out"); break; case QNetworkReply::SslHandshakeFailedError: errorString = tr("Untrusted connection"); break; case QNetworkReply::TemporaryNetworkFailureError: errorString = tr("Temporary network failure"); break; case QNetworkReply::ProxyConnectionRefusedError: errorString = tr("Proxy connection refused"); break; case QNetworkReply::ProxyNotFoundError: errorString = tr("Proxy host name not found"); break; case QNetworkReply::ProxyTimeoutError: errorString = tr("Proxy connection timed out"); break; case QNetworkReply::ProxyAuthenticationRequiredError: errorString = tr("Proxy authentication required"); break; case QNetworkReply::ContentNotFoundError: errorString = tr("Content not found"); break; case QNetworkReply::ContentAccessDenied: if (exOption->errorString.startsWith("AdBlockRule")) { if (exOption->frame != erPage->mainFrame()) { //Content in