Search code examples
javascriptpythonqtpyqtqtwebkit

Strange browser description PyQt


I was trying to get browser description using JavaScript, and got strange result:

productSub: 20100101 # When I open it with my Mozila FF browser
productSub: 20030107 # when I open it with PyQt4

vendorSub: # nothing in here with my Mozila FF
vendorSub: Apple Computer, Inc. # with PyQt4 ( even though I don't have anything to do with Apple)

This is HTML/JS:

<!DOCTYPE HTML>
<html>
<head>
</head>
<body>
<p id="myp">Hi</p>

<script>
    body = document.getElementsByTagName('body')[0];
    var nav_div = document.createElement('div');
    nav_div.id = 'nav_div';
    for (para in navigator) {
        var para_p = document.createElement('p');
        var context = document.createTextNode(para + ': ' + navigator[para]);
        para_p.appendChild(context);
        para_p.id = para;
        nav_div.appendChild(para_p);
    }
    body.appendChild(nav_div);
</script>
</body>
</html>

And here is the Python/PyQt4 code:

#! /usr/bin/env python2.7

from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4.QtWebKit import *
import sys, signal


class MySettings(QWebPage):
    def userAgentForUrl(self, url):
        return 'Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:17.0) Gecko/20100101 Firefox/17.0'

class Opener(QWebView):
    def __init__(self):
        QWebView.__init__(self)
        url = QUrl('/home/john-the-ripper/JavaScript/w.html')
        self.setPage(MySettings())
        self.load(url)
        self.show()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    opener = Opener()
    # press Ctrl + C for exit
    if signal.signal(signal.SIGINT, signal.SIG_DFL):
        sys.exit(app.exec_())
    app.exec_()

As you can see I have defined user agent the same as it is in my machine:

userAgent: Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:17.0) Gecko/20100101 Firefox/17.0

Here is the result for PyQt4:

PyQt4

And Here is the result for my native browser Mozila Fire Fox:

FF

So the questions are:

  1. Why productSub appers to be different, even though I have defined it in userAgentForUrl()
  2. Why when I open this page with PyQt4, vendorSub is Apple Computer, Inc.

Solution

  • A possible workaround is by redefining the navigator object. For a start, connect the javaScriptWindowObjectCleared signal from the page's main frame to a slot:

    connect(myPage->mainFrame(), SIGNAL(javaScriptWindowObjectCleared()),
      this, SLOT(tweakNavigatorObject()));
    

    In your slot, execute some script (QWebFrame::evaluateJavaScript) which can totally redefine the object, e.g.

    window.navigator = {
      appCodeName: 'Mozilla',
      appName: 'Netscape',
      vendor: 'My Company'
    }
    

    JFYI, this is the trick I have used in PhantomJS to provide the ability to manipulate the global object before the page's script gets executed, useful e.g. to manipulate Math.random behavior and to detect user agent sniffing.