From 13118b35bfb03c8ce681b8b3a624d3274c5c50ee Mon Sep 17 00:00:00 2001 From: IceArmy Date: Thu, 6 Oct 2011 08:28:23 -0700 Subject: [PATCH 1/4] Avoid deleting a QWebPage inside its own signal emission. If Phantom.exit() is called inside the handler for loadFinished(), we end up in a situation that QWebPage is deleting itself during a signal emission. This used to be OK in QtWebKit 2.0 (Qt 4.7) but is not OK for QtWebKit 2.2 (upcoming Qt 4.8). http://code.google.com/p/phantomjs/issues/detail?id=251 Patch by Caio Marcelo de Oliveira Filho . --- python/pyphantomjs/webpage.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/python/pyphantomjs/webpage.py b/python/pyphantomjs/webpage.py index cfba42c0..1200cf15 100644 --- a/python/pyphantomjs/webpage.py +++ b/python/pyphantomjs/webpage.py @@ -93,10 +93,11 @@ class WebPage(QObject): self.setObjectName('WebPage') self.m_webPage = CustomPage(self) self.m_mainFrame = self.m_webPage.mainFrame() + self.m_webPage.mainFrame().setHtml(self.blankHtml) - self.m_mainFrame.javaScriptWindowObjectCleared.connect(self.initialized) - self.m_webPage.loadStarted.connect(self.loadStarted) - self.m_webPage.loadFinished.connect(self.finish) + self.m_mainFrame.javaScriptWindowObjectCleared.connect(self.initialized, Qt.QueuedConnection) + self.m_webPage.loadStarted.connect(self.loadStarted, Qt.QueuedConnection) + self.m_webPage.loadFinished.connect(self.finish, Qt.QueuedConnection) # Start with transparent background palette = self.m_webPage.palette() @@ -116,9 +117,6 @@ class WebPage(QObject): self.m_webPage.settings().setAttribute(QWebSettings.LocalStorageEnabled, True) self.m_webPage.settings().setLocalStoragePath(QDesktopServices.storageLocation(QDesktopServices.DataLocation)) - # Ensure we have a document.body. - self.m_webPage.mainFrame().setHtml(self.blankHtml) - # Custom network access manager to allow traffic monitoring self.m_networkAccessManager = NetworkAccessManager(self.parent(), args) self.m_webPage.setNetworkAccessManager(self.m_networkAccessManager) From 34b595d01d446603bed46569f31437b0df2f5c6d Mon Sep 17 00:00:00 2001 From: IceArmy Date: Mon, 17 Oct 2011 21:01:17 -0700 Subject: [PATCH 2/4] Remove unused javascript files --- python/pyphantomjs/filesystem-shim.js | 163 -------------------------- python/pyphantomjs/webpage-shim.js | 35 ------ 2 files changed, 198 deletions(-) delete mode 100644 python/pyphantomjs/filesystem-shim.js delete mode 100644 python/pyphantomjs/webpage-shim.js diff --git a/python/pyphantomjs/filesystem-shim.js b/python/pyphantomjs/filesystem-shim.js deleted file mode 100644 index 0a8a173c..00000000 --- a/python/pyphantomjs/filesystem-shim.js +++ /dev/null @@ -1,163 +0,0 @@ -/*jslint sloppy: true, nomen: true */ -/*global window:true,phantom:true,fs:true */ - -/* - This file is part of the PhantomJS project from Ofi Labs. - - Copyright (C) 2011 Ivan De Marino - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -// window.fs -// JavaScript "shim" to throw exceptions in case a critical operation fails. - -/** Open and return a "file" object. - * It will throw exception if it fails. - * - * @param path Path of the file to open - * @param mode Open Mode. A string made of 'r', 'w', 'a/+' characters. - * @return "file" object - */ -window.fs.open = function (path, mode) { - var file = window.fs._open(path, mode); - if (file) { - return file; - } - throw "Unable to open file '" + path + "'"; -}; - -/** Open, read and return content of a file. - * It will throw an exception if it fails. - * - * @param path Path of the file to read from - * @return file content - */ -window.fs.read = function (path) { - var f = fs.open(path, 'r'), - content = f.read(); - - f.close(); - return content; -}; - -/** Open and write content to a file - * It will throw an exception if it fails. - * - * @param path Path of the file to read from - * @param content Content to write to the file - * @param mode Open Mode. A string made of 'w' or 'a / +' characters. - */ -window.fs.write = function (path, content, mode) { - var f = fs.open(path, mode); - - f.write(content); - f.close(); -}; - -/** Return the size of a file, in bytes. - * It will throw an exception if it fails. - * - * @param path Path of the file to read the size of - * @return File size in bytes - */ -window.fs.size = function (path) { - var size = fs._size(path); - if (size !== -1) { - return size; - } - throw "Unable to read file '" + path + "' size"; -}; - -/** Copy a file. - * It will throw an exception if it fails. - * - * @param source Path of the source file - * @param destination Path of the destination file - */ -window.fs.copy = function (source, destination) { - if (!fs._copy(source, destination)) { - throw "Unable to copy file '" + source + "' at '" + destination + "'"; - } -}; - -/** Copy a directory tree. - * It will throw an exception if it fails. - * - * @param source Path of the source directory tree - * @param destination Path of the destination directory tree - */ -window.fs.copyTree = function (source, destination) { - if (!fs._copyTree(source, destination)) { - throw "Unable to copy directory tree '" + source + "' at '" + destination + "'"; - } -}; - -/** Move a file. - * It will throw an exception if it fails. - * - * @param source Path of the source file - * @param destination Path of the destination file - */ -window.fs.move = function (source, destination) { - fs.copy(source, destination); - fs.remove(source); -}; - -/** Removes a file. - * It will throw an exception if it fails. - * - * @param path Path of the file to remove - */ -window.fs.remove = function (path) { - if (!fs._remove(path)) { - throw "Unable to remove file '" + path + "'"; - } -}; - -/** Removes a directory. - * It will throw an exception if it fails. - * - * @param path Path of the directory to remove - */ -window.fs.removeDirectory = function (path) { - if (!fs._removeDirectory(path)) { - throw "Unable to remove directory '" + path + "'"; - } -}; - -/** Removes a directory tree. - * It will throw an exception if it fails. - * - * @param path Path of the directory tree to remove - */ -window.fs.removeTree = function (path) { - if (!fs._removeTree(path)) { - throw "Unable to remove directory tree '" + path + "'"; - } -}; - -window.fs.touch = function (path) { - fs.write(path, "", 'a'); -}; \ No newline at end of file diff --git a/python/pyphantomjs/webpage-shim.js b/python/pyphantomjs/webpage-shim.js deleted file mode 100644 index c4269974..00000000 --- a/python/pyphantomjs/webpage-shim.js +++ /dev/null @@ -1,35 +0,0 @@ -/*jslint sloppy: true, nomen: true */ -/*global window:true,phantom:true,fs:true */ - -/* - This file is part of the PhantomJS project from Ofi Labs. - - Copyright (C) 2011 Ariya Hidayat - Copyright (C) 2011 Ivan De Marino - Copyright (C) 2011 James Roe - Copyright (C) 2011 execjosh, http://execjosh.blogspot.com - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - From 3ea50c443fc1fe42e7373f87246f6823505f3434 Mon Sep 17 00:00:00 2001 From: IceArmy Date: Mon, 17 Oct 2011 22:44:19 -0700 Subject: [PATCH 3/4] Minimize down the with statements that use QPyFile --- python/pyphantomjs/config.py | 16 +++++++--------- python/pyphantomjs/csconverter.py | 6 ++---- python/pyphantomjs/phantom.py | 7 ++----- 3 files changed, 11 insertions(+), 18 deletions(-) diff --git a/python/pyphantomjs/config.py b/python/pyphantomjs/config.py index f8fb9aa3..558ad36a 100644 --- a/python/pyphantomjs/config.py +++ b/python/pyphantomjs/config.py @@ -31,8 +31,8 @@ class Config(QObject): def __init__(self, parent, jsonFile): super(Config, self).__init__(parent) - with codecs.open(jsonFile, encoding='utf-8') as fd: - json = fd.read() + with codecs.open(jsonFile, encoding='utf-8') as f: + json = f.read() self.settings = { 'cookiesFile': { 'mapping': 'cookies_file', 'default': None }, @@ -60,14 +60,12 @@ class Config(QObject): qWarning('Config file MUST be in JSON format!') return - with QPyFile(':/configurator.js') as f: - configurator = f.readAll() - webPage = QWebPage(self) - # add config object - webPage.mainFrame().addToJavaScriptWindowObject('config', self) - # apply settings - webPage.mainFrame().evaluateJavaScript(configurator.replace('%1', json)) + with QPyFile(':/configurator.js') as f: + # add config object + webPage.mainFrame().addToJavaScriptWindowObject('config', self) + # apply settings + webPage.mainFrame().evaluateJavaScript(f.readAll().replace('%1', json)) do_action('Config') diff --git a/python/pyphantomjs/csconverter.py b/python/pyphantomjs/csconverter.py index 2ac9ca6d..dcf05135 100644 --- a/python/pyphantomjs/csconverter.py +++ b/python/pyphantomjs/csconverter.py @@ -39,10 +39,8 @@ class CSConverter(QObject): self.m_webPage = QWebPage(self) with QPyFile(':/resources/coffee-script.js') as f: - script = f.readAll() - - self.m_webPage.mainFrame().evaluateJavaScript(script) - self.m_webPage.mainFrame().addToJavaScriptWindowObject('converter', self) + self.m_webPage.mainFrame().evaluateJavaScript(f.readAll()) + self.m_webPage.mainFrame().addToJavaScriptWindowObject('converter', self) def convert(self, script): self.setProperty('source', script) diff --git a/python/pyphantomjs/phantom.py b/python/pyphantomjs/phantom.py index 4e1928c3..f3411571 100644 --- a/python/pyphantomjs/phantom.py +++ b/python/pyphantomjs/phantom.py @@ -77,8 +77,7 @@ class Phantom(QObject): self.m_page.mainFrame().addToJavaScriptWindowObject('phantom', self) with QPyFile(':/bootstrap.js') as f: - bootstrap = f.readAll() - self.m_page.mainFrame().evaluateJavaScript(bootstrap) + self.m_page.mainFrame().evaluateJavaScript(f.readAll()) do_action('PhantomInitPost') @@ -143,9 +142,7 @@ class Phantom(QObject): moduleSourceFilePath = ':/modules/%s.js' % name with QPyFile(moduleSourceFilePath) as f: - moduleSource = f.readAll() - - return moduleSource + return f.readAll() @pyqtProperty(str) def libraryPath(self): From 5ffeef450ceaef7dca2fe2c8572b5657ea1c03ec Mon Sep 17 00:00:00 2001 From: IceArmy Date: Mon, 17 Oct 2011 23:32:55 -0700 Subject: [PATCH 4/4] cookie.value() didn't really need to be a string, since QSettings will take a QVariant anyways. --- python/pyphantomjs/cookiejar.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/pyphantomjs/cookiejar.py b/python/pyphantomjs/cookiejar.py index c5e353b1..3764df6e 100644 --- a/python/pyphantomjs/cookiejar.py +++ b/python/pyphantomjs/cookiejar.py @@ -33,7 +33,7 @@ class CookieJar(QNetworkCookieJar): settings.beginGroup(url.host()) for cookie in cookieList: - settings.setValue(str(cookie.name()), str(cookie.value())) + settings.setValue(str(cookie.name()), cookie.value()) settings.sync()