Skip to content
This repository has been archived by the owner on May 30, 2023. It is now read-only.

Download support vs. master commit around 2013-07 #11557

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/modules/webpage.js
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,8 @@ function decorateNewPage(opts, page) {
// Private callback for "page.open()"
definePageSignalHandler(page, handlers, "_onPageOpenFinished", "loadFinished");

definePageSignalHandler(page, handlers, "onFileDownloadError", "fileDownloadError");

phantom.__defineErrorSignalHandler__(page, page, handlers);

page.onError = phantom.defaultErrorHandler;
Expand Down Expand Up @@ -468,6 +470,8 @@ function decorateNewPage(opts, page) {
// @see https://developer.mozilla.org/en/DOM/window.prompt
definePageCallbackHandler(page, handlers, "onPrompt", "_getJsPromptCallback");

definePageCallbackHandler(page, handlers, "onFileDownload", "_getFileDownloadCallback");

page.event = {};
page.event.modifier = {
shift: 0x02000000,
Expand Down
4 changes: 2 additions & 2 deletions src/qt/mkspecs/win32-msvc2010/qmake.conf
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ QMAKE_CFLAGS = -nologo -Zm200 -Zc:wchar_t- -wd"4099"
QMAKE_CFLAGS_WARN_ON = -W3
QMAKE_CFLAGS_WARN_OFF = -W0
QMAKE_CFLAGS_RELEASE = -O2 -MT
QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO += -O2 -MT -Zi
QMAKE_CFLAGS_DEBUG = -Zi -MTd
QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO += -O2 -MT -Zi -Fd$(DESTDIR)$(QMAKE_TARGET).pdb
QMAKE_CFLAGS_DEBUG = -Zi -MTd -Fd$(DESTDIR)$(QMAKE_TARGET).pdb
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change should not be in this pull request.

QMAKE_CFLAGS_YACC =
QMAKE_CFLAGS_LTCG = -GL
QMAKE_CFLAGS_MP = -MP
Expand Down
113 changes: 112 additions & 1 deletion src/webpage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@

#define STDOUT_FILENAME "/dev/stdout"
#define STDERR_FILENAME "/dev/stderr"

#define MIN_BUFFER_SIZE 4096

/**
* @class CustomPage
Expand Down Expand Up @@ -225,6 +225,10 @@ public slots:
return newPage->m_customWebPage;
}

void fileDownloadRequested(const QString& url, const QVariantMap& responseData) {
emit m_webPage->fileDownloadRequested(QUrl(url), responseData);
}

private:
WebPage *m_webPage;
QString m_userAgent;
Expand All @@ -251,6 +255,7 @@ class WebpageCallbacks : public QObject
, m_filePickerCallback(NULL)
, m_jsConfirmCallback(NULL)
, m_jsPromptCallback(NULL)
, m_fileDownloadCallback(NULL)
{
}

Expand Down Expand Up @@ -290,6 +295,16 @@ class WebpageCallbacks : public QObject
return m_jsPromptCallback;
}

QObject *getFileDownloadCallback() {
qDebug() << "WebpageCallbacks - getFileDownloadCallback";

if (!m_fileDownloadCallback) {
m_fileDownloadCallback = new Callback(this);
}

return m_fileDownloadCallback;
}

public slots:
QVariant call(const QVariantList &arguments) {
if (m_genericCallback) {
Expand All @@ -303,6 +318,7 @@ public slots:
Callback *m_filePickerCallback;
Callback *m_jsConfirmCallback;
Callback *m_jsPromptCallback;
Callback *m_fileDownloadCallback;

friend class WebPage;
};
Expand Down Expand Up @@ -346,6 +362,7 @@ WebPage::WebPage(QObject *parent, const QUrl &baseUrl)
connect(m_customWebPage, SIGNAL(loadFinished(bool)), SLOT(finish(bool)), Qt::QueuedConnection);
connect(m_customWebPage, SIGNAL(windowCloseRequested()), this, SLOT(close()), Qt::QueuedConnection);
connect(m_customWebPage, SIGNAL(loadProgress(int)), this, SLOT(updateLoadingProgress(int)));
connect(m_customWebPage, SIGNAL(unsupportedContent(QNetworkReply*)), this, SLOT(downloadRequested(QNetworkReply*)));

// Start with transparent background.
QPalette palette = m_customWebPage->palette();
Expand All @@ -359,6 +376,7 @@ WebPage::WebPage(QObject *parent, const QUrl &baseUrl)
m_mainFrame->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff);
m_mainFrame->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAlwaysOff);

m_customWebPage->setForwardUnsupportedContent(true);
m_customWebPage->settings()->setAttribute(QWebSettings::OfflineStorageDatabaseEnabled, true);
if (phantomCfg->offlineStoragePath().isEmpty()) {
m_customWebPage->settings()->setOfflineStoragePath(QDesktopServices::storageLocation(QDesktopServices::DataLocation));
Expand Down Expand Up @@ -729,6 +747,18 @@ bool WebPage::javaScriptPrompt(const QString &msg, const QString &defaultValue,
return false;
}

QString WebPage::fileDownloadPrompt(const QUrl& url, const QVariantMap& responseData)
{
if (m_callbacks->m_fileDownloadCallback) {
QVariant res = m_callbacks->m_fileDownloadCallback->call(QVariantList() << url << responseData);
if (!res.isNull() && res.canConvert<QString>()) {
return res.toString();
}
}

return "";
}

void WebPage::finish(bool ok)
{
QString status = ok ? "success" : "fail";
Expand Down Expand Up @@ -1293,6 +1323,15 @@ QObject *WebPage::_getJsPromptCallback()
return m_callbacks->getJsPromptCallback();
}

QObject *WebPage::_getFileDownloadCallback()
{
if (!m_callbacks) {
m_callbacks = new WebpageCallbacks(this);
}

return m_callbacks->getFileDownloadCallback();
}

void WebPage::sendEvent(const QString &type, const QVariant &arg1, const QVariant &arg2, const QString &mouseButton, const QVariant &modifierArg)
{
Qt::KeyboardModifiers keyboardModifiers(modifierArg.toInt());
Expand Down Expand Up @@ -1580,4 +1619,76 @@ void WebPage::updateLoadingProgress(int progress)
m_loadingProgress = progress;
}

void WebPage::downloadRequested(QNetworkReply* networkReply)
{
QUrl downloadUrl = networkReply->url();
qDebug() << "WebPage - downloadRequested:" << downloadUrl;

QVariant header = networkReply->header(QNetworkRequest::ContentLengthHeader);
bool ok;
int size = header.toInt(&ok);
if (ok && size == 0)
return;

QVariantMap responseData;
responseData["filename"] = QFileInfo(downloadUrl.toString()).fileName();
responseData["size"] = size;
responseData["contentType"] = networkReply->header(QNetworkRequest::ContentTypeHeader).toString();

QString filename = fileDownloadPrompt(downloadUrl, responseData);

if (filename.isEmpty()) {
qDebug() << "WebPage - downloadRequested. File download aborted (filename is empty)";
networkReply->abort();
} else {
QString downloadingFilename = QFileInfo(downloadUrl.toString()).fileName();
QFileInfo fileInfo(filename);

if (fileInfo.isRelative()) {
fileInfo.makeAbsolute();
}

if (fileInfo.isDir()) {
// check if the target directory is writable
if (!fileInfo.isWritable()) {
emit fileDownloadError("Requested path is not writable");
networkReply->abort();
return;
}

m_downloadingFiles[networkReply] = fileInfo.path() + downloadingFilename;
}
else
m_downloadingFiles[networkReply] = fileInfo.filePath();

connect(networkReply, SIGNAL(finished()), this, SLOT(downloadFinished()));
}
}

void WebPage::downloadFinished()
{
QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());

if (reply && reply->error() == QNetworkReply::NoError && m_downloadingFiles.contains(reply)) {
qDebug() << "WebPage - downloadFinished";
QFile file(m_downloadingFiles[reply]);

if (!file.open(QIODevice::WriteOnly)) {
emit fileDownloadError("Error opening output file: " + file.errorString());
} else {
qint64 bufferSize = qMin<qint64>(MIN_BUFFER_SIZE, reply->size());
QByteArray buffer;
while (!(buffer = reply->read(bufferSize)).isEmpty()) {
file.write(buffer);
}
file.close();
}

m_downloadingFiles.remove(reply);

// We can safely mark this QNetworkReply for deleting later since Webkit will not handle it
reply->deleteLater();
}
}

#include "webpage.moc"
8 changes: 8 additions & 0 deletions src/webpage.h
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ public slots:
QObject *_getFilePickerCallback();
QObject *_getJsConfirmCallback();
QObject *_getJsPromptCallback();
QObject *_getFileDownloadCallback();
void _uploadFile(const QString &selector, const QStringList &fileNames);
void sendEvent(const QString &type, const QVariant &arg1 = QVariant(), const QVariant &arg2 = QVariant(), const QString &mouseButton = QString(), const QVariant &modifierArg = QVariant());

Expand Down Expand Up @@ -474,11 +475,16 @@ public slots:
void navigationRequested(const QUrl &url, const QString &navigationType, bool navigationLocked, bool isMainFrame);
void rawPageCreated(QObject *page);
void closing(QObject *page);
void fileDownloadRequested(const QUrl &url, const QVariantMap& responseData);
void fileDownloadFinished();
void fileDownloadError(const QString &error);

private slots:
void finish(bool ok);
void setupFrame(QWebFrame *frame = NULL);
void updateLoadingProgress(int progress);
void downloadRequested(QNetworkReply* networkReply);
void downloadFinished();

private:
QImage renderImage();
Expand All @@ -497,6 +503,7 @@ private slots:
QString filePicker(const QString &oldFile);
bool javaScriptConfirm(const QString &msg);
bool javaScriptPrompt(const QString &msg, const QString &defaultValue, QString *result);
QString fileDownloadPrompt(const QUrl& url, const QVariantMap& responseData);

private:
CustomPage *m_customWebPage;
Expand All @@ -513,6 +520,7 @@ private slots:
QPoint m_mousePos;
bool m_ownsPages;
int m_loadingProgress;
QMap<QNetworkReply*, QString> m_downloadingFiles;

friend class Phantom;
friend class CustomPage;
Expand Down