Compare commits

...

504 Commits

Author SHA1 Message Date
Vitaliy Filippov 2c0316f07d always use fontconfig 2015-02-15 12:57:28 +03:00
Vitaliy Filippov cef6c84e00 Make qphantom platform plugin static and adjust build scripts 2015-02-15 12:39:07 +03:00
Vitaliy Filippov f37c7e29e0 Remove QT source and make phantomjs compile with unmodified QT, fix binary encoding of web response 2015-02-07 01:48:33 +03:00
Ariya Hidayat d3cd0599c8 Issue #12897: README is updated with 2.0 info. 2015-01-31 21:13:44 -08:00
Ariya Hidayat a2912c216d Set version from `2.0.0-development` to `2.0.0`.
https://github.com/ariya/phantomjs/issues/12897
2015-01-23 18:19:52 -08:00
Ariya Hidayat 0352ddb502 Version 2.0.0: initial cut at the ChangeLog.
https://github.com/ariya/phantomjs/issues/12897
2015-01-23 17:00:59 -08:00
Paul Millar 05d7e3e77d remove hardcoded "PhantomJS is launching GhostDriver..." message
Apart from being undesirable that debugging messages are always
written to stdout, the information is redundant as a similar message
is logged at debug level.

https://github.com/ariya/phantomjs/issues/12681
2015-01-09 07:41:48 -08:00
Andrey Plotnikov cf246eb853 Cast maxDiskCacheSize to qint64 to allow disk cache be more than 2Gb.
https://github.com/ariya/phantomjs/issues/12303
2014-12-18 09:16:38 -08:00
Jacek Migdal 806da21e2b Fix passing date as argument to page.evaluate().
https://github.com/ariya/phantomjs/issues/12615
2014-12-11 20:43:46 -08:00
Jacek Migdal 32d20b4aa7 Port more tests from webpage-spec.
https://github.com/ariya/phantomjs/issues/12439
2014-12-11 20:38:35 -08:00
Jacek Migdal 0bf14a3d0c Don't rely on JSON.parse() for page.evaluate().
https://github.com/ariya/phantomjs/issues/12615
2014-12-10 22:53:53 -08:00
Jacek Migdal 3b8282cb2e Port the tests from webpage-spec.js
Callback, clip-rect, confirm, object, prompt, scroll-position,
viewport-size and window.

https://github.com/ariya/phantomjs/issues/12439
2014-12-07 16:59:11 -08:00
Zack Weinberg 50ae50e871 Add a command-line option --local-urls={true,false}
The default is 'true'.  When set 'false', file: and qrc: URLs are
treated as invalid (unknown scheme) rather than opening local files,
as requested in issue #12752.

In order to test this, I added a mechanism to test/run-tests.py
allowing individual tests to be annotated with command-line
options to pass to phantomjs or the script.
2014-11-21 15:51:35 +00:00
Vitaly Slobodin a65a487d99 Fix invalid directory path for Windows.
https://github.com/ariya/phantomjs/issues/12715
2014-11-16 17:02:26 -08:00
Vitaly Slobodin 12870d90ad Fix JPG image rendering.
To pass QString as a const char* we should call <QString>.toLocal8Bit().constData().

https://github.com/ariya/phantomjs/issues/12684
2014-11-14 08:22:52 -08:00
Ariya Hidayat eddb0db1d2 Port the tests for mousedown, mouseup, and mousemove events.
https://github.com/ariya/phantomjs/issues/12439
2014-10-10 06:40:42 -07:00
Ariya Hidayat 619225b1da Port the tests of keyup, keydown, and keypress events.
https://github.com/ariya/phantomjs/issues/12439
2014-10-09 07:16:59 -07:00
Ariya Hidayat ce66f290c3 Port the test of web page's zoom factor.
https://github.com/ariya/phantomjs/issues/12439
2014-10-08 06:51:16 -07:00
Ariya Hidayat 2cbb695490 Port the tests of the web page's setContent().
https://github.com/ariya/phantomjs/issues/12439
2014-10-02 22:31:49 -07:00
Ariya Hidayat bad1fee468 README: Note on PhantomJS 2.
https://github.com/ariya/phantomjs/issues/10448
2014-10-01 20:17:07 -07:00
Ariya Hidayat b68d9467a7 Port the tests of the cookiejar module.
https://github.com/ariya/phantomjs/issues/12439
2014-09-30 22:00:53 -07:00
Ariya Hidayat a5f0ff7433 Port the test for console.log multiple arguments.
https://github.com/ariya/phantomjs/issues/12439
2014-09-29 21:29:44 -07:00
Ariya Hidayat 7e8986cd3e Port test tests of CJK codecs.
https://github.com/ariya/phantomjs/issues/12439
2014-09-28 22:39:20 -07:00
Ariya Hidayat 7bcb9a8725 Add a test to demonstrate the problem with JSON-ification.
https://github.com/ariya/phantomjs/issues/12615
2014-09-27 13:22:12 -07:00
Ariya Hidayat 5768b705a0 Implement clearMemoryCache() on a web page to clear the cache.
Unfortunately, due to Qt and WebKit limitation, this is technically
clearing all the cache used by every web page instance. It is the
best we can have right now.

https://github.com/ariya/phantomjs/issues/10357
2014-09-25 07:09:33 -07:00
Ariya Hidayat 105bcb32a9 Fix the mismatch of test files and their contents.
https://github.com/ariya/phantomjs/issues/12439
2014-09-24 21:49:26 -07:00
Ariya Hidayat 51d5835942 System#os.version workaround for new(er) OS X versions.
In case Qt doesn't provide the information yet, deduce it from the OS
kernel version (e.g. 14.x.y for OS 10.10 Yosemite).

https://github.com/ariya/phantomjs/issues/12579
2014-09-23 07:51:36 -07:00
Ariya Hidayat 72c53b5476 System#os.version should know OS 10.9 Mavericks.
https://github.com/ariya/phantomjs/issues/12579
2014-09-22 20:46:51 -07:00
Ariya Hidayat 639e09bd3a Provide OS kernel version in system.os.
This is available via the new property called `release`. A very simple
example to demonstrate it:

  var system = require('system');
  console.log('Kernel release', system.os.release);

which will print (on OS X 10.7.5 Lion):

  Kernel release 11.4.2

https://github.com/ariya/phantomjs/issues/12587
2014-09-21 23:47:57 -07:00
Ariya Hidayat 7c61f8857d Port the tests of web page properties and functions.
https://github.com/ariya/phantomjs/issues/12439
2014-09-18 23:17:21 -07:00
Ariya Hidayat b36da277e9 Port the user agent test.
https://github.com/ariya/phantomjs/issues/12439
2014-09-17 21:57:42 -07:00
Ariya Hidayat 9c7753189f Speed-up the tests by reducing some time-outs.
Running all tests should finish in 22 seconds instead of 41 seconds.

https://github.com/ariya/phantomjs/issues/12439
2014-09-16 20:43:10 -07:00
Zack Weinberg 4d4aa42c94 Set SO_REUSEADDR on the test server's listening port.
This means you don't have to wait 30 seconds in between invocations of
run-tests.py.

Also, if the test server fails to bind its port, print the actual
OS-level error message rather than guessing what the problem is.

issue #12439
2014-09-16 21:00:52 +00:00
Zack Weinberg 3d4f89b41e Bug fixes to test-server Python response hook support.
* correctly fake a package to hold all the response-hook modules
* use StringIO correctly in the response hooks
* prevent .py(c) files in test/www/ from being accessed directly
* prevent test/www/__init__ from being treated as a response hook
* add a test case that makes sure the existing hooks _can_ return 200 OK

(issue #12439; buggy commit 4d60e94)
2014-09-16 20:56:27 +00:00
Ariya Hidayat 2e8f0e8f68 Minor test runner clean-up.
Unused imports are removed.
Ensure that the correct reference is used.

https://github.com/ariya/phantomjs/issues/12439
2014-09-15 21:38:36 -07:00
Zack Weinberg 767494dc35 Add support for selective test execution.
If there are any positional arguments to test/run-tests.py, they are matched
(verbatim, not as regular expressions) against each test's name.  Only those
tests whose names contain at least one of the positional arguments will be
run.  Thus, for instance, you can run just the webpage tests with

    ./test/run-tests.py module/webpage

or one specific test with

    ./test/run-tests.py exact/name/of/test.js

or the basics and standards tests with

    ./test/run-tests.py basics standards

If no tests at all match, run-tests.py will print "ALL TESTS SKIPPED" and
exit unsuccessfully.

Ongoing work on issue #12439.
2014-09-15 16:21:25 +00:00
Zack Weinberg 4d60e9450d Support Python scripts in test/www/.
Rather than add all the special URLs we'll ever want to run-tests.py,
the embedded HTTP server now supports scripts in test/www/.  If you
try to load http://localhost:9180/path and test/www/path doesn't exist
but test/www/path.py does, then test/www/path.py is loaded as a module.
That module must export one function, handle_request(), which is called
to produce the response.

handle_request() has the same semantics as
SimpleHTTPRequestHandler.send_head().  That is, it takes one argument,
the SimpleHTTPRequestHandler object, conventionally named 'req'.
It should call the send_response(), send_header(), and end_headers()
methods of that object as appropriate.  And it should return a readable
filelike whose contents are taken as the body of the response.

If either module import or handle_request() throws any exception, the
HTTP response will be a 500 Internal Server Error with body provided
by cgitb.

Ongoing work on issue #12439.
2014-09-15 16:21:17 +00:00
Zack Weinberg 2b2d52e343 Improvements to logic in FileHandler.translate_path.
We already have 'base_path' as a global variable, so use that (or rather,
a new derivative of that) instead of inspect.getfile(inspect.currentframe()).

Rather than splitting the path and then iterating over every component
trying to figure out if it's "special", take advantage of the fact that
posixpath.normpath() will reliably produce a path with all ../ and bare-/
components at the very beginning.  Preserve the distinction between paths
with and without a trailing /, as SimpleHTTPRequestHandler expects.

So that paths containing unusual (e.g. non-ASCII, non-UTF-8) segments can
safely be tested, unquote and then requote the entire path.  This means
that the *bytes* corresponding to the ASCII characters

  0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz -_./

are guaranteed to be unquoted, and all other *bytes* are guaranteed to be
%-quoted.  (Note especially that *whether or not* the tests are being run
on Windows, \ in the original URL will be represented as %5C, and will
*not* be treated as a pathname separator.)

So that the tests behave consistently whether or not the OS has a case-
sensitive filesystem, after the above transformation, lowercase the entire
path.

Ongoing work on issue #12439.
2014-09-15 16:21:04 +00:00
Zack Weinberg 1adbbe4830 Support globs in run-tests.py#TESTS.
This means that there is no longer a need to add every individual test
to the list; only new *directories* have to be mentioned.  New tests
can be added just by dropping .js files into appropriate directories.

Tests which are not meant to be run by default now live in tests/manual/.
Currently there is one such test, tests/manual/standards/ecma-test262.js,
which downloads and runs the ECMAScript conformance suite.

Ongoing work on issue #12439.
2014-09-15 16:17:27 +00:00
Ariya Hidayat 83f4baf8c6 Port the test to check for plugin non-existence.
https://github.com/ariya/phantomjs/issues/12439
2014-09-14 09:35:41 -05:00
Ariya Hidayat f85238322e Port the test to change the encoded URL of network request.
https://github.com/ariya/phantomjs/issues/12439
2014-09-13 20:00:21 -05:00
Ariya Hidayat 3b972fbfbb Port the test to change the URL of network request.
https://github.com/ariya/phantomjs/issues/12439
2014-09-12 23:29:40 -05:00
Ariya Hidayat dca6f77a36 Port the test for onRepaintRequested handler.
https://github.com/ariya/phantomjs/issues/12439
2014-09-11 09:57:07 -07:00
Ariya Hidayat d52df7a1cf Port the test to abort network request.
https://github.com/ariya/phantomjs/issues/12439
2014-09-11 09:57:03 -07:00
Ariya Hidayat f95ef19fcb Port the test to check for resource received upon error.
https://github.com/ariya/phantomjs/issues/12439
2014-09-10 21:29:07 -07:00
Ariya Hidayat f29b76bb7f Port the test for resource request error handling.
https://github.com/ariya/phantomjs/issues/12439
2014-09-09 23:08:16 -07:00
Ariya Hidayat 804f61bcf5 Speed-up the tests: default auto-exit timeout is set to 1 second.
This reduces the total test duration from 72 seconds to 54 seconds.

https://github.com/ariya/phantomjs/issues/12439
2014-09-08 08:04:06 -07:00
Ariya Hidayat f20835735c Port custom headers testing of web page.
The HTTP server launched by the test runner has a new endpoint called
/echo. This simply echoes back some information (current on the made
request, in the future it will be expanded to further information)
formatted as JSON. This echo system facilitates easy testing for request
header manipulation feature.

https://github.com/ariya/phantomjs/issues/12439
2014-09-07 21:13:59 -07:00
Ariya Hidayat 2c10f6095b Port loading tests of web page.
https://github.com/ariya/phantomjs/issues/12439
2014-09-06 22:58:02 -07:00
Ariya Hidayat 784a06c3a7 The test runner also launches an HTTP server.
The server runs on port 9180 and serves the content from test/www
directory. Any tests can use this base URL to load test content and
to exercise certain PhantomJS API.

https://github.com/ariya/phantomjs/issues/12439
2014-09-05 21:31:38 -07:00
Vitaly Slobodin 235d072db5 Cast malloc to wchar_t. This is required in C++.
https://github.com/ariya/phantomjs/issues/12543
https://github.com/ariya/phantomjs/issues/12236
2014-09-05 06:32:45 -07:00
Zack Weinberg ab2e4788c6 Set the terminate handler to std::abort. (#12541) 2014-09-04 15:45:19 -04:00
Ariya Hidayat e8598a849e Port the tests of JavaScript's date parsing.
https://github.com/ariya/phantomjs/issues/12439
2014-09-04 08:28:45 -07:00
Ariya Hidayat 729f12c7d8 Port the tests for error handling.
https://github.com/ariya/phantomjs/issues/12439
2014-09-03 23:15:11 -07:00
Ariya Hidayat c883a80caf Port a few basic tests of global objects.
https://github.com/ariya/phantomjs/issues/12439
2014-09-02 22:28:53 -07:00
Ariya Hidayat 3274001e07 Remove the deprecated phantom.scriptName.
The use of phantom.scriptName has been deprecated since System#args was
introduce (version 1.5, March 2012). Any old scripts need to migrate to
System#args.

https://github.com/ariya/phantomjs/issues/12529
2014-09-01 08:11:28 -07:00
Ariya Hidayat 6c6059fd91 Remove the deprecated phantom.args.
The use of phantom.args has been deprecated (see commit 545a3f7)
since a long time ago (version 1.5, March 2012). Any old scripts
need to switch to use System#args instead.

https://github.com/ariya/phantomjs/issues/12527
2014-08-31 10:05:19 -07:00
Zack Weinberg f4eb3645f2 Make ciphersuite selection configurable; match Chromium by default. (#12524)
New option --ssl-ciphers takes a colon-separated list of OpenSSL
cipher names and sets the client cipher list to exactly that list.

The default for this option is arranged to match Chromium 35, which
has had its cipher selection optimized for the modern Web
(see https://briansmith.org/browser-ciphersuites-01.html for
rationales).  (Newer versions are the same except that they also add
ChaCha20-based ciphersuites, which OpenSSL 1.0.1 hasn't yet picked up.)
2014-08-30 20:49:58 -04:00
Zack Weinberg e8cddbfe7b Enable support for modern SSL (#12524).
* --ssl-protocol= option now accepts 'tlsv1.2', 'tlsv1.1', 'tlsv1.0'
   and 'default' as well as the existing 'tlsv1', 'sslv3', and 'any'.

 * The default is now none of the above, but rather QSsl::SecureProtocols,
   which means "whatever subset of ANY is still considered secure and also
   supported by the OpenSSL library in use".  (As of this writing, Qt's idea
   of "still considered secure" includes everything from SSLv3 on up, which
   is technically wrong -- SSLv3 has known breaks -- but we can live with.
   Qt currently doesn't have a way to select "TLSv1.0 and up".)
2014-08-30 20:49:38 -04:00
Ariya Hidayat 488a130799 A true OS X build fix for CrashHandler.
As suggested by ZackW.

https://github.com/ariya/phantomjs/issues/12236
2014-08-30 09:14:07 -07:00
Zack Weinberg 9afcf3c23d Explicitly suppress video and audio when building QtWebkit. (#12518)
This mostly matters when system sqlite is selected; that has the side
effect of enabling pkg-config which in turn causes QtWebkit to detect
the presence of system GStreamer and/or QtMultimedia and turn video on.
This way, the build is consistent across the board.
2014-08-30 07:02:21 -07:00
Zack Weinberg c64b1c078c More adjustments to system library usage on Unix (incl. Darwin) (#12518).
The affected libraries are fontconfig, freetype, harfbuzz, libpng, libjpeg,
sqlite, pcre, and zlib.

* On Darwin, by default, fontconfig is disabled and all of the other
  libraries are bundled.
* On non-Darwin, by default, fontconfig is enabled and system-provided
  freetype, libpng, libjpeg, and zlib are used.  Harfbuzz, pcre, and sqlite
  continue to be bundled.

* Individual libraries from the above list may now be enabled or disabled
  on the build.sh command line with e.g. --freetype=system or
  --freetype=bundled.

* The existing --system-qtdeps, --system-qt, --system-qtwebkit options
  have been renamed --qtdeps=system, --qt=system, --qtwebkit=system
  respectively.  New option --qtdeps=bundled forces all available
  bundled libraries to be used.

Also:

* Slight adjustments to organization of preconfig.sh.
* Can now disable PulseAudio and ALSA.
* Directly link OpenSSL instead of loading it at runtime.
* Clarify the pkg-config situation (it must be enabled if and only if
  sqlite comes from the system).
2014-08-30 07:02:21 -07:00
Zack Weinberg 0693711b0a Make it possible to disable ALSA and PulseAudio in qtbase. (#12518)
Cherry-picked configure script changes from upstream Qt5.3.
2014-08-30 07:02:21 -07:00
Ariya Hidayat a680ed41b2 Temporary OS X build fix for CrashHandler.
https://github.com/ariya/phantomjs/issues/12236
2014-08-29 21:40:02 -07:00
Zack Weinberg 858972e7ef Convert Utils into a namespace and remove dead code.
Post-cleanup for #12236.
2014-08-28 11:42:09 -04:00
Zack Weinberg 2ab57b875e Improve handling of crash dumps (issue #12236).
* If the environment variable PHANTOMJS_DISABLE_CRASH_DUMPS
   is set to any value, do not initialize Breakpad.

 * On Mac and Linux, if the environment variable TMPDIR is set,
   put the crash dumps there instead of in /tmp.

 * On Windows, %TEMP% was already being honored, but streamline
   the code for that.

 * Move the code that initializes Breakpad, and the code to print
   the crash messages, to their own module (src/crashdump.{h,cpp})
   and RAII class (CrashHandler).

 * Better wording of the crash message, particularly in the case where
   Breakpad failed to write a minidump file; update URL of crash-reporting
   guide.

 * Generally less repetitive code.  (Still way too many #ifdefs.)
2014-08-28 11:41:50 -04:00
Ariya Hidayat 2c0364b082 Port the tests of 'system' module.
https://github.com/ariya/phantomjs/issues/12439
2014-08-27 22:57:13 -07:00
Ariya Hidayat 7317724723 Fix consistent crash on OS X when rendering to PDF format.
By implementing a dummy platform native interface (for now, it may be
extended in the near future), QPlatformPrinterSupportPlugin will avoid
the path of loading the printer support plugin
(QCocoaPrinterSupportPlugin on OS X).

Related upstream bug (QCocoaPrinterSupportPlugin problem with static build):
https://bugreports.qt-project.org/browse/QTBUG-33109

https://github.com/ariya/phantomjs/issues/12500
2014-08-26 23:25:01 -07:00
Ariya Hidayat 4bc91b1bf0 A revamped test runner.
This Python script serves as a master test runner. It will run each test
script with a fresh instance of PhantomJS. The exit code of each script
determines its success or failure.

The existing tests (run-tests.js) are wrapped as one of the test
scripts. This permits a gradual migration to the new test system.

https://github.com/ariya/phantomjs/issues/12439
2014-08-25 21:13:32 -07:00
Ariya Hidayat 3a9fc49679 Enable even more tests (to 322 specs).
https://github.com/ariya/phantomjs/issues/10448
2014-08-24 20:24:39 -07:00
Ariya Hidayat 0cd703085d Reenable some more tests.
Now that the failing tests are isolated (among other, PDF crashing of
https://github.com/ariya/phantomjs/issues/12500), more tests should be
enabled. Going from 270 specs to 316 specs.

https://github.com/ariya/phantomjs/issues/10448
2014-08-24 20:00:04 -07:00
Ariya Hidayat 5ec80ff09c Enable more system module tests.
https://github.com/ariya/phantomjs/issues/12496
2014-08-24 19:33:53 -07:00
Ariya Hidayat 8cabfed4b3 Remove GIF format for screen capture export (render).
This is to reduce maintenance burden.  A GIF representation of a web
page can be produced by converting its PNG capture. There are numerous
third-party tools which can do the job better (optimized palette,
minimized loss, etc).

https://github.com/ariya/phantomjs/issues/12480
2014-08-23 09:20:20 -07:00
Ariya Hidayat 51c8c9cc62 Fix OS X stdout, stdin, and stderr.
To prevent unintended macro expansion, don't use the name
stdout/stdin/stderr in the native System object. Those properties are
achieved by shadowing it in the module interface (JavaScript side).

https://github.com/ariya/phantomjs/issues/12496
2014-08-22 07:56:40 -07:00
Milian Wolff 9e832a1569 Disable the phantom QPA on Windows.
It cannot, nor should it, be selected on windows machines. There, we
stick to the Windows QPA which is required to get a lot of things up
and running, like an eventloop, socket integration etc. pp.

There was code in the phantom QPA to make it compile, but it never
actually worked since a lot of things where missing (such as
instantiating QWindowsContext among others).

https://github.com/ariya/phantomjs/issues/12494
2014-08-22 16:35:26 +02:00
Vitaliy Slobodin 22e74549a3 Disable colorized output in tests on Windows.
https://github.com/ariya/phantomjs/issues/12484
2014-08-20 20:57:09 -07:00
Marcel Duran 3be7005a17 run-jasmine example: Ensure exit code is always returned.
https://github.com/ariya/phantomjs/pull/12486
2014-08-20 20:56:15 -07:00
Zack Weinberg 1e7829db97 Fix crash on exit if pages have been closed (#12482)
Regression from #12431: the loop to clear all surviving pages
neglects to check for entries in `m_pages` which have already
been closed, fully destructed, and therefore replaced by NULL
pointers.
2014-08-20 14:38:45 -04:00
Ariya Hidayat b5626bff97 Add a simple test for exit behavior.
https://github.com/ariya/phantomjs/issues/12431
https://github.com/ariya/phantomjs/issues/12439
2014-08-20 05:51:19 -07:00
Milian Wolff a9809996b1 Stop processing of JavaScript after phantom.exit().
This code:

    console.log("Hello World!");
    phantom.exit();
    console.log("Meh, noone should see me!");

currently produces this unexpected output:

    Hello World!
    Meh, noone should see me!

This patch fixes it to only output the first line, by loading a blank
page on phantom.exit(). Direct deletion of the web page can trigger
crashes, so this is a safe workaround.

https://github.com/ariya/phantomjs/issues/12431
2014-08-20 05:50:30 -07:00
Ariya Hidayat 77c47044cf Remove misc references to CoffeeScript.
https://github.com/ariya/phantomjs/issues/12410
2014-08-19 20:37:06 -07:00
Artem 5e018bd650 Update sleepsort.js
https://github.com/ariya/phantomjs/pull/12344
2014-08-19 20:35:06 -07:00
Ariya Hidayat a6f6130767 Travis CI can't build PhantomJS anymore.
https://github.com/ariya/phantomjs/issues/11880
2014-08-19 20:30:22 -07:00
Zack Weinberg 26934f32a9 Add a -v/--verbose option to run-tests.{sh,js}.
The newer ConsoleReporter is very quiet by default, which is nice, but
this provides a way to get something more like the older one-line-per-test
output.

 #12230 (Test suite improvements).
2014-08-19 20:24:28 -07:00
Zack Weinberg b524d53d36 Add ability to run tests selectively.
* Anything on the command line after "run-tests.sh" will be understood
   as a regular expression (if there is more than one argument, they are
   concatenated, with spaces in between) and only the tests whose "full
   names" match that regexp will be run.  The full name of a test is the
   "describe" string plus a space plus the "it" string.  Note well that,
   unlike the test-runner output, there is no colon in there.

 * run-tests.sh and run-tests.js now correctly handle being invoked from
   an arbitrary directory; the cwd does not have to be the project root.

 * Shell portability fixes for run-tests.sh.

 #12230 (Test suite improvements).
2014-08-19 20:24:28 -07:00
Zack Weinberg 6fb347d296 Fix jasmine.ConsoleReporter.specFailureDetails.
The new Jasmine includes a version of this formerly external add-on, but it
is buggy and doesn't print details of failing tests.

 #12230 (Test suite improvements).
2014-08-19 20:24:27 -07:00
Zack Weinberg e6b67bddc5 Import Jasmine 1.3.1.
The newer jasmine-console behavior requires minor adjustments to the
 ConsoleReporter we create in run-tests.js.  Also, en passant fix for
 a bug in the final callback: exiting with status equal to the number
 of failed tests does not work, because the _exit() system call takes
 only the low eight bits of the value passed.  If a test run happened
 to have 256 failing tests, the old code would have spuriously exited
 successfully.  Instead, just exit(1) if any tests fail.

 #12230 (Test suite improvements).
2014-08-19 20:24:27 -07:00
Zack Weinberg 7102e87bf4 Eliminate console spam during normal test execution.
Three tests were (potentially) dumping text to console.log during the
run, which they should never do.

Fixing that revealed that one of them, the test for interrupting a
long-running JS script, was not actually testing what it was supposed
to test. Fixing *that* revealed that the long-running-script hook is
broken and does not actually interrupt JS infinite loops; that test
has been temporarily disabled.

 #12230 (Test suite improvements).
2014-08-19 20:24:27 -07:00
Zack Weinberg 406f736e14 Do not use github.com in tests.
Two tests were spuriously failing because they tried to load pages on
`github.com` that were no longer structured as expected.  Use a local
webserver instead.

 #12230 (Test suite improvements).
2014-08-19 20:24:27 -07:00
Craig Teegarden f245d3ed22 update modernizr to 2.8.2 - specifically shows phantomjs supports "legacyflexbox" instead of the current "flexbox"
https://github.com/ariya/phantomjs/issues/12273
2014-08-19 20:18:46 -07:00
Zack Weinberg 9bbff95a57 Correction to fontconfig usage on Unix-not-OSX.
The PhantomJS QPA hardcoded usage of QFontconfigDatabase on
Unix-not-OSX, causing build failures in "bundle all the libraries" mode.
Use QGenericUnixFontDatabase instead, which is QFontconfigDatabase if
fontconfig is enabled, and QBasicFontDatabase if it isn't.  This means
that the bundled-qtdeps build will use only the fonts bundled with Qt,
and won't be able to find them on a machine that doesn't have the source
tree, which is suboptimal, but at least this makes the bundled-qtdeps
build complete successfully again.

Part of issue #12467.
2014-08-19 16:44:12 -04:00
Ariya Hidayat 2681756efd Obsolete links to any wiki page.
The documentation has been using GitHub pages for a while already.

https://github.com/ariya/phantomjs/issues/10627
2014-08-19 07:27:39 -07:00
Zack Weinberg 30a4a01bca 80-column compliance for build.sh messages.
Cosmetic fix as part of issue #12467.
2014-08-19 07:20:50 -07:00
Zack Weinberg 8d23afb782 Add --system-qtdeps build mode.
In this mode, system-provided libraries will be used for all of
Qt's dependencies, but Qt and QtWebkit themselves are still the
bundled copies.  This mode actually works.

Now that this mode exists, disable fontconfig in the "everything
bundled" mode, because it drags in the system freetype and several
other system libraries.  (There is no bundled fontconfig.)

Part of issue #12467.
2014-08-19 07:20:49 -07:00
Zack Weinberg 4246ed0533 Correct SQLITE3SRCDIR setting.
This is how we arrange for QtWebkit to use QtBase's bundled copy of
sqlite; without it, QtWebkit will attempt to use a system-provided
library instead, and if headers are unavailable, the build will fail.

Part of issue #12467.
2014-08-19 07:20:49 -07:00
Zack Weinberg e9e6f30e69 Add option to build against system qtbase but bundled qtwebkit.
As with the system-qtwebkit option, this does not actually work at this
point, but it enables experimentation toward getting it to work.

Part of issue #12467.
2014-08-19 07:20:49 -07:00
Zack Weinberg 9254f6855e Rationalize handshake between build.sh and preconfig.sh.
* build.sh now handles building qt and qtwebkit.
 * preconfig.sh is now only responsible for accumulating arguments
   to pass to qt's configure script.
 * preconfig.sh doesn't have command line arguments of its own;
   anything on its command line will be passed directly to qt's
   configure script.
 * first pass of adjustments to the qt configure parameters
   to try to get a more static build - unfortunately, system
   sqlite, libz, libpng, and libexpat are still getting pulled
   in somehow (mostly via fontconfig, I think).

Part of issue #12467.
2014-08-19 07:20:49 -07:00
Zack Weinberg 615f33c9c4 Add capability to build PhantomJS against system Qt/Webkit.
Invoking build.sh with --system-qtwebkit will skip the build of Qt and
QtWebkit and use the qmake in $PATH to build PhantomJS proper.

This doesn't actually *work* at the moment because the bundled
copy of Webkit has patches not yet merged upstream, but it's still
useful to have for testing purposes.

Part of issue #12467.
2014-08-19 07:20:48 -07:00
Zack Weinberg 5b5e63af23 Better Qt version check.
* Allow any patchlevel of Qt 5.3.x.
 * Do it in the master .pro file instead of main.cpp; this makes the build
   fail immediately rather than after compiling a bunch of stuff.

Part of issue #12467.
2014-08-19 07:20:48 -07:00
Zack Weinberg b81d7aec0a Update .gitignore for Qt 5.3.
* Ignore src/phantomjs_plugin_import.cpp, which is now created during
   the build.
 * Add leading slashes to a bunch of files that should not be ignored if
   they crop up in subdirectories.

Part of issue #12467.
2014-08-19 07:20:48 -07:00
Vitaliy Slobodin 0c8eb88c15 Add build script for Windows 2014-08-18 23:35:27 +04:00
John Gozde de2a19da9c Use Array.prototype.slice in window.callPhantom.
window.callPhantom formerly used Array.prototype.splice for cloning
its arguments to the internal _phantom.call. This relied on
non-standard behaviour of the splice method when only a single
argument was passed to it (it requires 2 arguments).

The correct method for cloning the arguments array is to use
Array.prototype.slice, which accepts a single argument (index) and
returns a new array from the specified index.

https://github.com/ariya/phantomjs/issues/12306
2014-08-18 00:15:08 -07:00
Petteri Räty a86ae1948c Fix rasterize example exit status on failure.
https://github.com/ariya/phantomjs/issues/11911
2014-08-17 23:23:05 -07:00
Ariya Hidayat fbe8eefc29 Launcher for ECMA-262 test suite (test262.ecmascript.org).
https://github.com/ariya/phantomjs/issues/12439
2014-08-16 20:46:28 -07:00
Ariya Hidayat 25ddf566e7 Fix path handling when running the build process.
https://github.com/ariya/phantomjs/issues/12433
2014-08-16 13:22:10 -07:00
Mike McQuaid 0a8b13403f preconfig.sh: don't require ICU on OSX
This isn't needed for the full build, only QtWebKit which has it's own ways of finding the system ICU.

https://github.com/ariya/phantomjs/issues/10448
2014-08-16 11:18:27 -07:00
Ariya Hidayat f532b73cb2 More tests for the arguments object.
https://github.com/ariya/phantomjs/issues/11845
https://github.com/ariya/phantomjs/issues/11558
https://github.com/ariya/phantomjs/issues/11746
https://github.com/ariya/phantomjs/issues/10315

https://github.com/ariya/phantomjs/issues/12439
2014-08-15 22:42:23 -07:00
Ariya Hidayat 3c9cf90d12 Remove website/ directory.
The web site has been based on GitHub pages for 2.5 years already.
2014-08-15 22:42:22 -07:00
Ariya Hidayat eca1081b6e Remove patches/ since they are for 1.x only.
https://github.com/ariya/phantomjs/issues/10448
2014-08-15 22:42:21 -07:00
Milian Wolff aa0300607c Stop early when QtBase or QtWebKit failed to compile.
Currently, the build script will continue to try to build PhantomJS
even when either QtBase or QtWebKit failed to compile. In such a
case, the script should return early and emit an error message.

https://github.com/ariya/phantomjs/issues/12433
2014-08-15 21:54:56 -07:00
Milian Wolff 4bf75c50b0 Simplify Env code by reusing QProcessEnvironment.
This gets rid of the custom parse code and slims down the API.

https://github.com/ariya/phantomjs/issues/12424
2014-08-15 21:49:46 -07:00
Ariya Hidayat 3136898976 Some tests for JavaScript's Function.
https://github.com/ariya/phantomjs/issues/12439
https://github.com/ariya/phantomjs/issues/10522
2014-08-09 11:53:19 -07:00
Ariya Hidayat bbdaa9e884 A simple assertion for the fortcoming revamped test system.
https://github.com/ariya/phantomjs/issues/12439
2014-08-09 10:59:22 -07:00
Vitaly Slobodin 28045aaf6b Merge pull request #12430 from KDAB/remove_coffeescript_test
Remove CoffeeScript references from unit tests
2014-08-08 18:24:26 +04:00
Vitaly Slobodin 2ebe5fd8a8 Merge pull request #12428 from KDAB/cleanup_qt5merge
Fixup wrong merge: remove src/qt/src
2014-08-08 18:24:02 +04:00
Milian Wolff 0c55c0a9e0 Remove CoffeeScript references from unit tests
https://github.com/ariya/phantomjs/issues/12429
2014-08-06 15:08:24 +02:00
Milian Wolff 514972db80 Fixup wrong merge: remove src/qt/src
This reapplies the patch of issue #11590 and drops the patch
from issue #11264. The former is still valid, while the latter
is hopefully resolved properly in Qt5 (see e.g. this:
https://bugs.webkit.org/show_bug.cgi?id=69419).

https://github.com/ariya/phantomjs/issues/12427
2014-08-06 15:00:34 +02:00
Ariya Hidayat 48fabe0646 Remove CoffeeScript support.
https://github.com/ariya/phantomjs/issues/12410
2014-07-30 01:29:21 -07:00
Ariya Hidayat 64b6fd2f4b ChangeLog for 1.9.7.
https://github.com/ariya/phantomjs/issues/11919
2014-07-30 01:29:20 -07:00
Ariya Hidayat 20a73a6d40 Update ChangeLog for 1.9.6.
https://github.com/ariya/phantomjs/issues/11905
2014-07-30 01:29:20 -07:00
Ariya Hidayat dc8d3c7052 Update ChangeLog for 1.9.3.
https://github.com/ariya/phantomjs/issues/11904
2014-07-30 01:29:19 -07:00
Ariya Hidayat 13e788f2c1 Travis CI: Get more dependencies for building Qt 5.
https://github.com/ariya/phantomjs/issues/11880
https://github.com/ariya/phantomjs/issues/10448
2014-07-28 06:51:35 -07:00
Ariya Hidayat 53edf23e8f Reintroduce silent mode for building PhantomJS 2.
https://github.com/ariya/phantomjs/issues/11880
https://github.com/ariya/phantomjs/issues/10448
2014-07-28 06:18:10 -07:00
Ariya Hidayat e2682edf48 Disable some failing and/or crashing unit tests.
Also, reorder the tests since webpage-spec.js seems to be sensitive to
any previously executed tests.

https://github.com/ariya/phantomjs/issues/10448
2014-07-28 03:33:13 -07:00
Ariya Hidayat 1bf54d8776 Correct the unit tests of PhantomJS version.
https://github.com/ariya/phantomjs/issues/10448
2014-07-27 17:10:30 -07:00
Ariya Hidayat 125c8d3d49 Qt 5 base: Fix permissions of some files.
https://github.com/ariya/phantomjs/issues/10448
2014-07-27 07:47:55 -07:00
Vitaliy Slobodin cf12fc4a23 Long live PhantomJS 2!
https://github.com/ariya/phantomjs/issues/10448
2014-07-27 07:47:34 -07:00
Vitaly Slobodin d10b8dc583 Merge pull request #12287 from zackw/expose-http-status-to-onresourceerror
Expose HTTP status and reason to onResourceError (#12252).
2014-07-15 10:12:55 +04:00
Vitaly Slobodin 4393627a80 Merge pull request #12313 from Vitallium/remove-nullptr-warning
Variables QT_GCC_* are undefined for QPA.
2014-07-15 10:10:18 +04:00
Vitaliy Slobodin c166662c0d Variables QT_GCC_* are undefined for QPA. 2014-06-15 18:19:02 +04:00
Vitaly Slobodin 05277b2d84 Merge pull request #12300 from artkoshelev/proxysetuprefactoring
Replace proxy initialization with existing method
2014-06-15 12:19:22 +04:00
Artem Koshelev 00afabc993 Replace proxy initialization with existing method
Since we have setProxy() method, we can replace the existing code
block in Phantom::init() with simple method call getting rid of
duplicated code.
2014-06-10 16:56:29 +04:00
Zack Weinberg d65601fe90 Expose HTTP status and reason to onResourceError (#12252). 2014-06-03 20:52:44 -04:00
Sven Eckelmann 13ad8a134e Use correctly rendered pdf for webpage-spec-renders tests
The last reference test.pdf in the tests was using a complete different region
of the input "image.jpg" because the used phantomjs version used to generate it
had a bug. This bug was fixed in 833eb824f5bae07f1b157d6757e7e3c98343f812
("Don't scale the unit px to 1/2.54 points for PDFs") and
1daa2eb4dd49efb848ff96e37f298a774520cc9b ("Disable page shrinking for pdf
printing to create accurate output").

The new version should now use the same region of the input image as the other
generated files for the gif, jpg and png tests. The only difference is the
extra height is still displayed on a second page but this is currently expected
by phantomjs.

https://github.com/ariya/phantomjs/issues/11590 ("page.paperSize is not
accurate for .pdf")
2014-05-31 08:23:32 -07:00
Sven Eckelmann b4e295cc97 Disable page shrinking for pdf printing to create accurate output
PDFs are not rendered like PNG or other image formats by phantomjs because it
uses the printer functionality of Qt+Webkit. But Webkit uses some printer
"optimization" to save paper by shrinking the output. Such shrinking results in
too small content on a page.

https://github.com/ariya/phantomjs/issues/11590 ("page.paperSize is not
accurate for .pdf")
2014-05-31 08:23:24 -07:00
Sven Eckelmann 800fbe8452 Don't scale the unit px to 1/2.54 points for PDFs
The unit px is one point inside the HTML source page but phantomjs handles it
without reason as 1/2.54 points. This makes the page smaller than expected when
trying to render a page as PDF.

https://github.com/ariya/phantomjs/issues/11590 ("page.paperSize is not
accurate for .pdf")
2014-05-31 08:23:13 -07:00
Ivan De Marino 62fbad4814 Adding IRC #phantomjs notif. to TravisCI build 2014-05-10 01:28:11 +01:00
Eric Heydenberk ccdd86f47f Add missing RPM spec file names; update changelog.
Issue #11262 https://github.com/ariya/phantomjs/issues/11262
2014-04-22 21:38:38 -07:00
Artem Koshelev 3c5302d567 Example of runtime proxy setup
https://github.com/ariya/phantomjs/issues/10803
2014-04-17 23:02:43 -07:00
Thomas Schlage 9da842df2b Added setProxy function
https://github.com/ariya/phantomjs/issues/10803
2014-04-17 23:02:15 -07:00
Dmitry Mazuro 4d2fedf243 Use SVG version of travis build status badges
https://github.com/ariya/phantomjs/issues/11880
2014-04-07 22:01:46 -07:00
Richard Harris 7d3f3f0819 Fix harfbuzz assertions using patch from Chromium.
Exotic text (e.g. attempting to render a binary file such as .zip
or .exe as a webpage) can trigger an assertion failure in the
Harfbuzz code. Chromium developers also noticed this issue and
committed a patch to fix it:

http://lists.freedesktop.org/archives/harfbuzz/2009-August/000354.html

This patch has not been accepted by upstream, but this (old) version
of Harfbuzz has been abandoned and superceded by Harfbuzz-NG.

Issue #11264
2014-04-07 21:58:36 -07:00
Ivan De Marino e9c77252ee Merge branch 'master' of https://github.com/pauloalem/phantomjs into pauloalem-master 2014-03-29 11:28:50 +00:00
petercoles d831dea8c8 Update example
Since this example was written the phantomjs home page has been redesigned and the targeted ID no longer exists. This tweaks the example so that it can again find content to report.
2014-03-29 11:09:51 +00:00
Ivan De Marino e9a47eddee Changing Travis CI build list into a table 2014-03-09 19:25:54 +00:00
Ivan De Marino 8f685818aa Fixed tests that dealt with manipulating request URLs.
Related to #11952.

Those tests use "http://phantomjs.org" as fixture.
The website "/images" directory has been renamed "/img",
breaking the tests.

Maybe not the greatest way to go about it, but
for now it will do. We probably need to have fixtures
served by a local server.
2014-03-09 01:02:49 +00:00
Ivan De Marino 77b5de1362 Run PhantomJS's tests as part of TravisCI
Related to #11952.
2014-03-09 01:02:49 +00:00
Ivan De Marino ba5998f74e Making GhostDriver test "quiet-er" (and parallel)
Also, trying to get the exit status of those tests reported, in case they fail.

Related to #11952.
2014-03-09 01:02:21 +00:00
Ivan De Marino 1797c146f1 Adding "test/ghostdriver-test" to run in Travis CI
Related to issue #11880
2014-03-08 23:37:47 +00:00
Adrian Chung 300f28cc5d Add example for how to post a json request to HTTP server
https://github.com/ariya/phantomjs/issues/11969
2014-02-19 21:40:02 -08:00
Rikke Simonsen bda8838698 Fix for crash bug caused by Iframe NULL reference
https://github.com/ariya/phantomjs/issues/10947
https://github.com/ariya/phantomjs/issues/11103
https://github.com/ariya/phantomjs/pull/11984
2014-02-19 21:30:11 -08:00
paulo alem 15d0636b70 Runner for jasmine 2
The old script needed some updates in order to support the new jasmine lib
2014-02-14 19:27:14 -02:00
Ivan De Marino 9940e8b25e Travis CI: Adding comments to ".travis.yml".
Related to issue #11880
2014-02-02 21:25:05 +00:00
Ivan De Marino 0765f9bdd2 Travis CI: trying to make the build more "resilient".
Related to issue #11880.
2014-02-02 21:00:53 +00:00
Ivan De Marino 06672a03aa Add links to "travis ci" to README file.
Linking branches "master" and "1.9" for now.
2014-02-02 19:58:36 +00:00
Ivan De Marino 056aa50c19 Importing GhostDriver 1.1.1.
Yes, 1.1.0 has just been imported.
But the key feature in 1.1.1 is Session Isolation in WebDriver: something that has been requested many times,
particularly when using GhostDriver with Selenium Grid.
2014-01-12 21:08:21 +00:00
Trevor North 18b8a4d444 Update table page break improvements patch
Includes the following fixes taken from trvrnrths-qt:
- Ensure we have a first cell to measure when checking required table
  height
- Handle page break edge case with exactly fitting last table row
  In the case where the last table row on a page fitted exactly no
  extra offset was afforded to the next row. This resulted in no
  space being left for the painting of the table header on the next
  page.
- Fix segfault when checking heights for pagination if table body does
  not have a cell at 0,0

See https://github.com/ariya/phantomjs/pull/11291 and
https://github.com/ariya/phantomjs/pull/11490.
2014-01-10 20:56:52 -08:00
Ariya Hidayat 42b3a86bcd OS X: Unsafe patch to fix selectable text on PDF output.
https://github.com/ariya/phantomjs/pull/11723
https://github.com/ariya/phantomjs/pull/11509
2014-01-10 16:18:08 -08:00
Joseph Rollinson 244cf251cd Adds support for multiple Cookie Jars.
Previously, there was a single global cookie jar shared between all web pages.
Now, one can have separate cookie jars for different web pages.

Makes CookieJar a normal class, not a singleton.
Moves many public CookieJar methods to public slots.
Adds default cookie jar to Phantom.
Adds the CookieJar module that provides access to cookie jars in javascript.
Adds cookie jar module tests.

Usage:
var jar = require('cookiejar').create();
var webpage = require('webpage').create();
webpage.cookieJar = jar;
...
webpage.close();
jar.close();

JS API changes:
Webpage:
    var jar = page.cookieJar; -- assigns 'jar' the given webpage's cookie jar.
    page.cookiejar = jar; -- sets 'jar' as the given webpage's cookie jar.
CookieJar:
    var jar = require('cookiejar').create(path)
        creates a cookie jar with persistent storage at the given file path
        (path not mandatory).
    var cookies = jar.cookies; -- assign's 'jar' the list of cookies in the
        cookie jar.
    jar.cookies = [c1, c2]; -- sets the cookie jar's cookies as the ones in the
        list.
    jar.addCookie(cookie) -- adds cookie 'cookie' to the cookie jar.

https://github.com/ariya/phantomjs/issues/11417
2014-01-10 16:12:39 -08:00
Vasyl Vavrychuk 3ae9d38d40 fixed test suite 'WebPage render image'
Previously the test suite 'WebPage render image' made a series of
webpage.open without waiting them to complete. This effected next
runned tests because on load handlers for pages were fired after
'WebPage render image' test finish.

https://github.com/ariya/phantomjs/issues/11780
2014-01-09 17:47:11 -08:00
Ashish Kulkarni 3ed2f68909 Implement "page-break-inside: avoid" for non-floating block elements.
This patch is taken from https://bugs.webkit.org/show_bug.cgi?id=5097#c17

It was originally part of PR #211 but was possibly overlooked in PR #344
(when the other two patches got reapplied after the QT source import).
2014-01-07 08:46:18 -08:00
Ariya Hidayat 6b45113cfe QWidget: Fix unused parameter warning when there's no Graphics View.
This reduces the amount of repetitive compiler warnings.

https://github.com/ariya/phantomjs/issues/11880
2014-01-06 23:27:34 -08:00
Ariya Hidayat 266ef0da59 Travis CI: Silent build.
https://github.com/ariya/phantomjs/issues/11880
2014-01-06 22:35:02 -08:00
Ariya Hidayat 46eb122ba3 Travis CI: Ensure that the build script executable.
https://github.com/ariya/phantomjs/issues/11880
2014-01-06 17:08:48 -08:00
Ariya Hidayat e533587107 Travis CI: Packages installation needs a priviliged access.
https://github.com/ariya/phantomjs/issues/11880
2014-01-06 16:59:50 -08:00
Ariya Hidayat 23f31391af Travis CI: Fix the build directives.
https://github.com/ariya/phantomjs/issues/11880
2014-01-06 16:45:33 -08:00
Ariya Hidayat e897ab8bb2 Travis CI: Ensure packages are cached for faster setup.
https://github.com/ariya/phantomjs/issues/11880
2014-01-06 16:42:56 -08:00
Ariya Hidayat aa388a05ef First attempt on using Travis CI.
https://github.com/ariya/phantomjs/issues/11880
2014-01-06 16:34:23 -08:00
James McParlane dca15d7ff6 Added onRepaint callback to webpage API.
Enables subscription to RepaintRequested events.
When the callback is invoked the time that the repaint was requested as well as the x,y and width,height of the repainted rectangle are provided as parameters.
Usage: page.onRepaint = function(time, x, y, width, height) { }

https://github.com/ariya/phantomjs/issues/11793
2014-01-06 23:05:30 +00:00
Ivan De Marino 9bfe22b428 Merge pull request #11784 from vvavrychuk/parse-error
fix lack of parse time errors location info
2014-01-06 11:30:29 -08:00
Ivan De Marino a9a219e74b Importing GhostDriver 1.1.0 in PhantomJS.
CHANGELOG for v1.1.0 (https://github.com/detro/ghostdriver/issues?labels=1.1.0&state=closed)

JavaScript Driver (Core)
* ENHANCEMENT: `/maximize` window will set the window size to 1336x768,
currently most common resolution online (see http://gs.statcounter.com/#resolution-ww-monthly-201307-201312)
* ENHANCEMENT #275: Implemented Browser and Network (HAR) Logging types
* FIXED #284: Attempt to wait for Page to Load if input causes form submit
* FIXED #291: Throw exception when attempting to set invalid timeout value
* FIXED #259: Fix issue regarding mouse clicks
* ENHANCEMENT #290: Enabled support for "Keep Alive" HTTP connections
* ENHANCEMENT #262: Allow access to PhantomJS API from WebDriver (Driver part)
* ENHANCEMENT #293: Import Selenium 2.39.0 WebDriver Atoms

Java Binding
* MINOR #251: Minor compilation issues for Binding
* ENHANCEMENT #262: Allow access to PhantomJS API from WebDriver (Java Binding part)

Tested using GhostDriver validation tests (https://github.com/detro/ghostdriver/tree/master/test).

https://github.com/ariya/phantomjs/pull/11877
2014-01-04 14:44:04 -08:00
Ariya Hidayat b70ff8929c Fix warning of obsolete userSpaceScaleFactor on OS X 10.9 (Mavericks).
Related upstream bug: https://bugreports.qt-project.org/browse/QTBUG-28574

Issue #1162 https://github.com/ariya/phantomjs/issues/11612
2014-01-03 20:41:00 -08:00
Ariya Hidayat b67866b612 Fix CoreText performance note on OS X 10.9 (Mavericks).
Upstream Qt bug: https://bugreports.qt-project.org/browse/QTBUG-32789
Upstream patch: https://codereview.qt-project.org/#patch,all,70097,4.
Upstream commit: https://qt.gitorious.org/qt/qt/commit/98352b964f

https://github.com/ariya/phantomjs/issues/11418
2014-01-03 20:40:53 -08:00
Ivan De Marino 9b0132712b Merge pull request #11868 from bradleyboy/click-modifier-fix
Pass modifier to mouse events for click/dblclick
2014-01-01 11:04:44 -08:00
Brad Daily 7659f2551c Adding tests for #11867
This tests mousedown, mouseup, click, and doubleclick for clicks with
modifier events. The mousedown/mouseup tests pass in 1.9.2, the
click/doubleclick do not. All pass with a build from this branch.
2014-01-01 13:47:33 -05:00
Ben Cox 18b342d3e7 Update some grammar on the README.md
Replaces the "a, b, c, d" with the more grammatically correct "a, b, c, and d"
2014-01-01 09:44:33 -08:00
Ivan De Marino e1ae72a866 Merge pull request #11866 from bmarkovic/patch-1
Added bitmap size and clipping to rasterize.js
2014-01-01 08:18:42 -08:00
Brad Daily e40ebb93d7 Pass modifier to mouse events for click/dblclick
A fix for the issue described here:

https://github.com/ariya/phantomjs/issues/11867
2014-01-01 11:06:11 -05:00
Bojan Markovic 54c1611801 Added bitmap size and clipping to rasterize.js
Added support for defining window/viewport size and eventual clipping to bitmap rasterization similar to how it is used with paper output.
2014-01-01 13:14:19 +01:00
Aaron Stone 3d80670e22 Handle script language in debug mode too.
f919121a35
2013-12-15 22:27:26 -08:00
Aaron Stone 176d435901 REPL is only valid for javascript updates.
https://github.com/ariya/phantomjs/issues/11744
2013-12-15 22:27:10 -08:00
Oleg Plakhotniuk f4128d7ede Select monospace font family properly.
CSS style "font-family: monospace" should select monospace font.

https://github.com/ariya/phantomjs/issues/11764
2013-12-13 07:34:49 -08:00
Aaron Stone 4ca640c5e7 Reject script-language values other than javascript and coffeescript
https://github.com/ariya/phantomjs/issues/11744
2013-12-13 06:58:20 -08:00
Aaron Stone 394e2f8699 Add option --script-language to explicitly set javascript or coffeescript
https://github.com/ariya/phantomjs/issues/11744
2013-12-13 06:58:04 -08:00
Francisco de Borja Lopez Río d5eaf41063 Set proper jobs number and library paths before building in OpenBSD
https://github.com/ariya/phantomjs/issues/10996
2013-12-05 07:30:02 -08:00
Martin Popelak 8f8de58752 Update of reference for mongoose license
As it seems that project Mongoose has been relicensed from MIT to GPL2. The link provided is leading to the new licensing agreement but as today version 3.1 of Mongoose is used which is licensed under MIT therefore correct reference to a license should be provided.

https://github.com/ariya/phantomjs/issues/10718
2013-12-05 07:27:53 -08:00
Vitaliy Slobodin efcc6c7861 Define the new page callback for interrupting a long-running JavaScript
Issues:
https://github.com/ariya/phantomjs/issues/11198
https://github.com/ariya/phantomjs/issues/11183
https://github.com/ariya/phantomjs/issues/11189
2013-11-23 22:09:39 -08:00
Vasyl Vavrychuk c8e4215097 fix lack of parse time errors location info
Location information of parse time error is given to javaScriptError not
with stack by with separate lineNumber and sourceID arguments. Put this info
to stack if it is empty so that it will be visible to user.

https://github.com/ariya/phantomjs/issues/11640
2013-11-24 01:43:10 +02:00
Vitaliy Slobodin 6a01a8dece Upgrade to Qt 4.8.5
https://github.com/ariya/phantomjs/issues/11452
2013-10-19 07:52:31 -07:00
Max Edmands 94e63bfa04 Fix typo in the cookie jar debug message. 2013-10-19 07:52:01 -07:00
Vitaliy Slobodin 23df8811a1 REPL returns empty object on enumerating properties on a simple JavaScript type (Number, String, Logical).
We should not to do that.

Issue:
https://github.com/ariya/phantomjs/issues/11622
2013-10-07 20:33:52 -07:00
Mike McQuaid fe6a967bad Fix Clang compilation
Already merged in Qt: b82b8bfa81

Issue #11611 https://github.com/ariya/phantomjs/pull/11611
2013-10-01 07:38:40 -07:00
Ariya Hidayat 2691540711 Getting ready for 1.9.2.
Issue #11452: https://github.com/ariya/phantomjs/issues/11452
2013-09-08 07:25:43 -07:00
hexid b1e181176e Add require.paths support
Issues: https://github.com/n1k0/casperjs/issues/462 https://github.com/ariya/phantomjs/issues/11339
2013-09-01 07:53:08 -07:00
Morgan Roderick 7431cbf229 CONTRIBUTING.md: convenient => confident
Minor correction to language use in CONTRIBUTING.md
2013-08-15 12:05:41 +02:00
Ivan De Marino 73bb560840 Import GhostDriver v1.0.4
Issues in this release: https://github.com/detro/ghostdriver/issues?labels=1.0.4&state=closed
See GhostDriver Changelog for more details.
2013-07-25 23:24:53 +01:00
Dmitry Parshin 8114d44a28 fixed compile errors for no-JIT configuration
Issue #11475 https://github.com/ariya/phantomjs/issues/11475
2013-07-24 23:38:44 -07:00
Richard Harris 4989445e71 Fix harfbuzz assertions using patch from Chromium.
Exotic text (e.g. attempting to render a binary file such as .zip
or .exe as a webpage) can trigger an assertion failure in the
Harfbuzz code. Chromium developers also noticed this issue and
committed a patch to fix it:

http://lists.freedesktop.org/archives/harfbuzz/2009-August/000354.html

This patch has not been accepted by upstream, but this (old) version
of Harfbuzz has been abandoned and superceded by Harfbuzz-NG.

Issue #11264
2013-07-24 23:34:45 -07:00
Vitaliy Slobodin 1a25383307 Use Qt::transparent to resolve graphical artifacts with images with transparent background.
We need to use QImage::Format_ARGB32_Premultiplied on Windows to preserve a text hinting and antialiasing. Using the function `qRgba()` leads to wrong pixel values on a target image. Since, `QImage::fill(uint pixel)` doesn't handle the QImage::Format_ARGB32_Premultiplied format, so we need to use the another overload `QImage::fill(const QColor &color)`

Issues:
https://github.com/ariya/phantomjs/issues/11276
https://github.com/ariya/phantomjs/issues/11007
https://github.com/ariya/phantomjs/issues/11366
2013-06-24 01:07:24 +04:00
Vitaliy Slobodin b1cb3a00bd Merge pull request #11425 from Vitallium/master
Fix typo in the `loadurlwithoutcss` example
2013-06-23 00:45:30 -07:00
Vitaliy Slobodin fdec25ac4c Fix typo in `loadurlwithoutcss` example
Issue: https://github.com/ariya/phantomjs/issues/11321
2013-06-23 11:28:51 +04:00
Ivan De Marino 6ba33cbcab Merge pull request #11422 from detro/ghostdriver-dev
WebServer Headers for Request are treated case-insensitive
2013-06-21 15:55:25 -07:00
Ivan De Marino c466d8aeef WebServer Headers for Request are treated case-insensitive
To achieve this, Request Headers are stored in both "original" and "lowercase".
In this way we don't mangle with the request object we have received, while
still be able to handle headers when NOT in the classic "Camel-Case" format.

Fixes #11421.
2013-06-21 23:51:05 +01:00
Ariya Hidayat edf2d90a11 Patch for table page break improvement.
From d78182d3a6451522f239ee1ecbb71863eb053792 Mon Sep 17 00:00:00 2001
From: Artem Baranovskiy <likejavascript@gmail.com>
Date: Mon, 6 May 2013 08:01:01 +0400
Subject: [PATCH] Table page-break improvements

See issue #11291 https://github.com/ariya/phantomjs/pull/11291
2013-06-08 21:40:55 -07:00
Ariya Hidayat 644f379588 Include all the changes from 1.9.1. 2013-06-08 02:20:42 -07:00
Ariya Hidayat b4c4429e86 Unit tests: reduce the flakiness of loading progress tests.
For whatever reason, swapping the order with the render() tests solve the
intermittent random failures. Also, split the tests between loading
start and finish checks (to better recognize which one is failing, if
there is a failure), also make the tests more asynchoronous.

https://github.com/ariya/phantomjs/issues/11091
2013-06-08 02:18:31 -07:00
Ariya Hidayat 01587211cb Unit test: secure connection check becomes async.
Issue #10882: https://github.com/ariya/phantomjs/issues/10882
2013-06-08 02:05:07 -07:00
Ariya Hidayat 44c3d6080d Unit tests: robustify the tests of PDF, GIF, PNG, JPEG rendering.
Issue #10973 https://github.com/ariya/phantomjs/issues/10973
2013-06-08 02:04:59 -07:00
Ariya Hidayat 9f1f56bc3b Unit tests: terminate any web servers after finishing the tests.
Issue #11163: https://github.com/ariya/phantomjs/issues/11163
Issue #11243: https://github.com/ariya/phantomjs/issues/11243
2013-06-08 02:04:48 -07:00
Ariya Hidayat f57fa468ab Unit test: tweak secure connection check.
The main wikipedia page can be slow to load and thus triggers the timeout.
Let's use the fast Google site so that we don't get flaky outcome.

Issue #10882: https://github.com/ariya/phantomjs/issues/10882
2013-06-08 02:04:39 -07:00
Bryan Bishop fb8edb7c72 Fix minor typos in preconfig.sh.
One is a typo, while the other is grammar-related.

fixes #11388

https://github.com/ariya/phantomjs/issues/11388
2013-06-05 18:07:42 -05:00
Vitaliy Slobodin 4d916971b3 Fix including http:// in the proxy URL:
The proxy host parsed incorrectly, when it was typed with a scheme (http or https).
Now proxy can be specified with the scheme.

Fix invalid type conversion:
m_proxyPort converts to its ASCII representation.
Use `QString::number` to include a proxy port properly.

Issues:
https://github.com/ariya/phantomjs/issues/11117
https://github.com/ariya/phantomjs/issues/10811
2013-05-29 00:38:15 +04:00
Vitaliy Slobodin 639e8c85b2 Make QNetworkReplyHandler deliver content asynchronously
when its load type is set to SynchronousLoad.

Issue #11338: https://github.com/ariya/phantomjs/issues/11338
Upstream bug: https://bugs.webkit.org/show_bug.cgi?id=62808
2013-05-20 19:49:23 -07:00
Ariya Hidayat fa238856f9 third-party.txt: Include OpenSSL.
Issue #11269 https://github.com/ariya/phantomjs/issues/11269
2013-05-20 19:49:22 -07:00
Ariya Hidayat 9aa0705d3c Update ChangeLog. 2013-05-20 00:20:14 -07:00
Alex Alvarez 3bd7a3dfa6 Netsniff.js example should exit with an error when fails to load the adress
Issue #11333 https://github.com/ariya/phantomjs/issues/11333
2013-05-19 22:29:31 -07:00
Alex Alvarez 2f851086e4 Netsniff.coffee example should exit with an error when fails to load the adress
Issue #11333 https://github.com/ariya/phantomjs/issues/11333
2013-05-19 22:28:09 -07:00
Jan Minar 320608662d Reword for better English 2013-05-19 18:16:09 -07:00
Vitaliy Slobodin 0726a8e2bb Fix crash when calling QObject::disconnect for QNetworkReplyWrapper
Fix it by watching the QNetworkReply's destroyed() signal and avoid the dangling pointer
instead. The QNetworkReply doesn't need to be aborted in this case anyway.

Issue #11252: https://github.com/ariya/phantomjs/issues/11252
Upstream bug: https://bugs.webkit.org/show_bug.cgi?id=116035
2013-05-19 12:01:33 -07:00
Ariya Hidayat 706e928e78 Update ChangeLog. 2013-05-15 00:03:39 -07:00
Eric Heydenberk f1472b54d1 Update RPM spec changelog
- Describe %files change
- Fix year in timestamp in previous changelog entry

Issue #11262 https://github.com/ariya/phantomjs/issues/11262
2013-05-13 23:34:35 -07:00
Eric Heydenberk dff8ce2526 Update rpm spec file names
- Add missing example files
- Alphabetize names

Issue #11262 https://github.com/ariya/phantomjs/issues/11262
2013-05-13 23:33:51 -07:00
Vitaliy Slobodin 5528d75c9d Network request header manipulation
Issue: https://github.com/ariya/phantomjs/issues/11299 (#11299)

User should be able  to manipulate HTTP headers per each network request, not only using global setting page.customHeaders.
2013-05-13 22:48:58 -07:00
Vitaliy Slobodin f8e79fb8c6 Limit the maximum request post size to 10 MB (megabytes).
std::numeric_limits<qint64>::max is too big for QByteArray (throws Out of Memory exception).
Set up the limit like it was done in Google Chrome
Ref: https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/Source/core/inspector/NetworkResourcesData.cpp

Related to issue #10158 https://github.com/ariya/phantomjs/issues/10158
2013-05-13 22:41:15 -07:00
Ivan De Marino 23515550d5 MINOR: Reorder initialisation order in NAM constr.
`m_resourceTimeout` is declared before of other
private variables, and the compiler was complaining
the initialisation order could not be respected.
This caused annoying (but innocuous) warnings at compile time.
2013-04-30 22:57:58 +01:00
Andrew Galloni 3ae632e704 ChangeUrl to accept an encoded string
Issue #11243: https://github.com/ariya/phantomjs/issues/11243.
2013-04-29 07:07:53 -07:00
Robin Helgelin f72f2962d1 Updated rpm spec file to work with 1.9.
Issue #10939: https://github.com/ariya/phantomjs/issues/10939
2013-04-29 07:05:48 -07:00
execjosh 39bec1ce17 Synchronize std{in,out,err} encoding with `Terminal`
See #11234 https://github.com/ariya/phantomjs/pull/11234
Spin off from #11168 https://github.com/ariya/phantomjs/pull/11168
2013-04-29 07:00:47 -07:00
execjosh b159144a48 Teach `File` how to change its encoding
If a `File` is in "text" mode, then it has an encoding.  This
encoding defaults to UTF-8; however, it can be set only at time of
construction (by using `fs.open`).

This modification allows the user to change the encoding on-the-fly
for "text" mode `File` instances.

See #11234 https://github.com/ariya/phantomjs/pull/11234
Spin off from #11168 https://github.com/ariya/phantomjs/pull/11168
2013-04-29 07:00:19 -07:00
execjosh 3d874d9e0d Make `Terminal` emit a signal upon encoding change
See #11234 https://github.com/ariya/phantomjs/pull/11234
Spin off from #11168 https://github.com/ariya/phantomjs/pull/11168
2013-04-29 06:58:44 -07:00
Ariya Hidayat c07a2efa33 Update ChangeLog. 2013-04-22 22:39:02 -07:00
execjosh f8a905c8b0 Link with text codec plugins on mac and linux
Fixes [#10249](https://github.com/ariya/phantomjs/issues/10249)
2013-04-22 22:35:56 -07:00
execjosh d925a510d9 Improve WebPage CJK support tests.
This is for issue #10249: https://github.com/ariya/phantomjs/issues/10249.
2013-04-22 22:35:08 -07:00
Vitaliy Slobodin 3edcabef9f Fix compilation with MSVC 2010
Issue #10158: https://github.com/ariya/phantomjs/issues/10158
This bug introduced by the marco max( ) defined in <windef.h>.
It replaces max( ) with another statement but still preceeded by numberic_limits<Type>::
The workaround is to use the parenthesis
2013-04-13 20:17:12 -07:00
Vitaliy Slobodin 78242e5d6c Fix command line option typo
Issue #11219: https://github.com/ariya/phantomjs/issues/11219
2013-04-12 23:12:20 -07:00
execjosh 36ab7194e4 Use UTF-8 encoding for std{in,out,err}
This fixes issue #11162.

`File` constructor takes a `QTextCodec *`, codec; but, if codec is
`NULL`, then it assumes "binary" mode, which causes non-ASCII
characters to be converted to NUL (`\0`) in `File::write`.

This change passes the codec for UTF-8 to the `File` constructor for
the `std{in,out,err}` instances, thus opening them in *text mode*.
2013-04-12 23:10:25 -07:00
execjosh 8042f3b92c Flush in `File::write` when in unbuffered "text" mode
If the wrapped `QFile` was opened with `QIODevice::Unbuffered`, any
writes should be unbuffered.  However, as currently implemented,
using `QTextStream` when the `File` is in "text" mode causes all
reads/writes to be buffered.

This modification forces a flush in `File::write` if the wrapped
`QFile` was opened with `QIODevice::Unbuffered`.

Necessary to fix issue #11162 https://github.com/ariya/phantomjs/issues/11162.
2013-04-12 23:10:08 -07:00
Ariya Hidayat 24078b56c7 Update ChangeLog. 2013-03-31 03:08:26 -07:00
Ariya Hidayat 0bc2eb418e Temporarily call this branch as version 1.10.
Issue #10448 https://github.com/ariya/phantomjs/issues/10448#issuecomment-15689386
2013-03-31 03:06:50 -07:00
Pavel fcdd274f2e Show postData in onResourceRequested callback.
Issue #10158 https://github.com/ariya/phantomjs/issues/10158
2013-03-31 02:54:37 -07:00
Vitaliy Slobodin 47dc82681d Fire `onResourceReceived` callback when the resource error occured.
Issue #11163: https://github.com/ariya/phantomjs/issues/11163
2013-03-31 02:39:53 -07:00
Vitaliy Slobodin 9ca45ed62e Fix loading modules from an absolute path on Windows.
Don't check the module path using Linux-style path checking.

Issue #11165: https://github.com/ariya/phantomjs/issues/11165
2013-03-25 19:01:32 -07:00
Ariya Hidayat da71c5fbdd Issue #10939: Mention 1.9 as the new stable.
https://github.com/ariya/phantomjs/issues/10939
2013-03-20 22:38:03 -07:00
Ariya Hidayat bb1a407e8d ChangeLog: Always mention the code names. 2013-03-20 22:38:03 -07:00
Ariya Hidayat bda3355060 Issue #10939: Get ready for version 1.9.0.
https://github.com/ariya/phantomjs/issues/10939
2013-03-20 22:23:51 -07:00
Ariya Hidayat 08bbd324d1 Update ChangeLog.
https://github.com/ariya/phantomjs/issues/10939
2013-03-20 22:22:59 -07:00
Ariya Hidayat 9ef69005d4 ChangeLog: Modify the issue numbers to match the new issue tracker.
https://github.com/ariya/phantomjs/issues/10939
2013-03-20 20:32:24 -07:00
DjinnS b5345bc133 netsniff example: Exclude Data URI from HAR.
Fixes issue #10740.

https://github.com/ariya/phantomjs/issues/10740
2013-03-20 20:24:59 -07:00
Jonathan Wilkins 9f9053ec44 Add support for specifying non-default CA certificate bundles.
This is done via SSL_CERT_DIR and --ssl-certstore.

Fixes issue #10916.

https://github.com/ariya/phantomjs/issues/10916
2013-03-20 08:27:54 -07:00
Tom Aizenberg 52883ced68 WebPage: network timeout setting.
Fixes issue #11129.

https://github.com/ariya/phantomjs/issues/11129
2013-03-19 22:57:26 -07:00
Laurent Jouanneau b16a5348a9 WebPage: new constants for modifiers keys
Declares in event.modifiers all constants needed for the fifth
parameter of sendEvent.

http://code.google.com/p/phantomjs/issues/detail?id=1056
https://github.com/ariya/phantomjs/issues/11056
2013-03-18 22:24:02 -07:00
Ariya Hidayat 63dc1e2c8f Add a patch to disable touch event support.
This is from https://github.com/ariya/phantomjs/pull/408.
See also issue #10375 for some related discussion.

https://github.com/ariya/phantomjs/issues/10375
2013-03-18 22:00:16 -07:00
Max Desyatov 0147fcbc07 Support for specifying request body encoding for WebPage::openUrl
Added a simple test in test/webpage-spec.js

Test data from http://code.google.com/p/phantomjs/issues/detail?id=1043
2013-03-18 21:43:22 -07:00
Max Desyatov 357dbf46d2 Support for specifying request body encoding for WebPage::openUrl
doesn't break existing functionality and currently supports only
"utf-8" and "utf8" encodings

Fixes http://code.google.com/p/phantomjs/issues/detail?id=1043
2013-03-18 21:43:00 -07:00
Ivan De Marino 6989188fa0 Merge pull request #11146 from detro/ghostdriver-dev
Importing GhostDriver v1.0.3
2013-03-18 02:22:46 -07:00
Ivan De Marino 78d90641df Importing new GhostDriver 1.0.3.
See the https://github.com/detro/ghostdriver/ project for details.
2013-03-18 09:20:50 +00:00
Ivan De Marino 005db037cf Tests for the new "page.loading" property.
This commit provides the unit tests for the new property, as asked by
Ariya in #11091.
2013-03-18 09:19:41 +00:00
Ivan De Marino 9740990990 New "page.loading" and "page.loadingProgress".
Now you can know about the Page Loading Progress
using 2 property:
- [bool] page.loading
- [int: 0-100] page.loadingProgress

Implements #1091: http://code.google.com/p/phantomjs/issues/detail?id=1091
2013-03-17 16:24:47 +00:00
Ariya Hidayat 9af1f09f58 Change issue tracker link to point to the new one.
From now on, it's https://github.com/ariya/phantomjs/issues.

For the details, check this mailing-list discussion:
https://groups.google.com/d/msg/phantomjs/It04OsP7csU/Vw2cmJkAILUJ
2013-03-16 09:19:25 -07:00
Ariya Hidayat 9df52bb752 Update ChangeLog.
Also, includes changes from 1.8.x.

http://code.google.com/p/phantomjs/issues/detail?id=863
https://code.google.com/p/phantomjs/issues/detail?id=939
2013-03-02 21:52:45 -08:00
Ariya Hidayat d42c4002c4 examples/follow: Update Twitter handles.
https://code.google.com/p/phantomjs/issues/detail?id=1082
2013-03-02 21:33:36 -08:00
Ariya Hidayat 1c80f7306e Update ChangeLog.
http://code.google.com/p/phantomjs/issues/detail?id=939
2013-02-24 19:51:26 -08:00
Alexander James Phillips 5d6b8240f7 page_events example should show requests and navigate to step2url
http://code.google.com/p/phantomjs/issues/detail?id=1028
2013-02-24 16:18:05 -08:00
Dody Suria Wijaya 58566bbe76 Fix concurrent issue on render_multi_url example
webkit (thus phantomjs) load() does not call loadFinished at the expected timing when running concurrently. The example is changed to run non-concurrently as a work around.

Issue: http://code.google.com/p/phantomjs/issues/detail?id=1021
2013-02-24 10:26:42 -08:00
Vitaliy Slobodin fed209c546 Allocate JsNetworkRequest on the stack to avoid leaking it.
https://code.google.com/p/phantomjs/issues/detail?id=539
2013-02-24 09:00:49 -08:00
Vitaliy Slobodin 212e4b7cd9 Reworked api for canceling network requests. Added experimental API for changing the url of the network request.
Issue:
http://code.google.com/p/phantomjs/issues/detail?id=539

Stub
2013-02-24 09:00:07 -08:00
Capi Etheriel ca27a8eab1 Use fs.write in the example for clarity.
https://code.google.com/p/phantomjs/issues/detail?id=1082
2013-02-24 08:56:38 -08:00
Ivan De Marino 04368c6af8 HOTFIX: @Vitalliumm discovered a typo in CookieJar
Original message: https://twitter.com/vitalliumm/status/301220038323613697
This was affecting date comparison/espiration in the
CookieJar.

Typical case of "I have no idea how it did work so far".

http://code.google.com/p/phantomjs/issues/detail?id=1068
2013-02-12 07:34:57 -08:00
Ariya Hidayat fef171e14f Renew the weather example with OpenWeatherMap service.
Google "secret" Weather API is shutdown. Let's use the crowd-sourced
OpenWeatherMap to supply the weather data (albeit there is no forecast
available).

http://code.google.com/p/phantomjs/issues/detail?id=794
2013-02-05 00:27:20 -08:00
Juliusz Gonera 2d42b52c67 Make require.stub() optionally accept a factory function
require.stub() can now accept a factory function instead of an object
so that stubbed modules are initialized lazily:

require.stub('zlib', function() {
    // initialized once, when zlib first required
    return {
        createGzip: function() { ... }
    };
});

http://code.google.com/p/phantomjs/issues/detail?id=1044
2013-02-05 00:04:17 -08:00
Julian Szulc 1e5638678d Fix ignoring ssl errors on synchronous xhrs
disabling peer verify in ssl configuration when ignore-ssl-errors is set

issue http://code.google.com/p/phantomjs/issues/detail?id=985
2013-02-05 00:01:50 -08:00
James M. Greene 1604b4d6c1 Updated help output to prefer true/false to yes/no
Similarly, I updated the API Reference too:
7cddd19676

This arguably makes more sense to PhantomJS's typical audience of web developers.
2013-02-04 23:58:10 -08:00
James M. Greene e6ae4cca6d Adding the whole 'bin' folder to '.gitignore'
On Windows, there are 3 files produced in the 'bin' folder and none of them should be checked in.
2013-01-29 00:02:23 -06:00
Ariya Hidayat 43ab20d4ae Prevent possible crash on pages with iframes.
In some cases, setupFrame() has not been invoked (due to the queued
signal-slot connection) after the frame is destroyed and thus leads
to the crash. We prevent this from happening by making sure it is a
direct connection instead and therefore setupFrame() will be executed
as soon as possible.

Investigation + patch by Vitaliy Slobodin <vitaliy.slobodin@gmail.com>.

http://code.google.com/p/phantomjs/issues/detail?id=947
2013-01-28 21:13:47 -08:00
Jeff Boulter ec6b242a9f Fixed the CreationDate value format when creating PDFs.
This was confusing Adobe Reader and not allowing it to save PDFs.

This bug appears to have been introduced in commit 08fc50d149 which was applying the patch from http://qt.gitorious.org/qt/qt/merge_requests/706 but missed two lines.

This should fix issue http://code.google.com/p/phantomjs/issues/detail?id=663 .
2013-01-25 00:12:06 -08:00
Matthew Barr fe78d4d9fe Updated rpm spec file to work with 1.8.
http://code.google.com/p/phantomjs/issues/detail?id=1012
2013-01-25 00:04:20 -08:00
bongole 0734811514 Add rendering to stdout and stderr.
This feature renders PDF, GIF and other format supported by Qt to
stdout or stderr.

*NOTE*
"/dev/stdout" and "/dev/stderr" are converted to System::stdout and
System::stderr on Windows.

Issue: https://code.google.com/p/phantomjs/issues/detail?id=973
2013-01-21 21:44:18 -08:00
Vitaliy Slobodin 6d81933941 Pass the resource URL to the resourceError handler.
http://code.google.com/p/phantomjs/issues/detail?id=997
2013-01-21 21:42:10 -08:00
Ariya Hidayat 797b47ae81 Update ChangeLog.
http://code.google.com/p/phantomjs/issues/detail?id=939
2013-01-17 21:48:06 -08:00
Ivan De Marino 7e7325c0f5 Fixing up indentation for our Jasmine test specs.
Just getting rid of an itch of mine.
2013-01-17 23:52:47 +00:00
Ivan De Marino 12bb24f418 FIX: 'resource request errors' close the server.
The test "should handle resource request errors"
was not closing the server at the end of the test,
interfering with the successive tests.
2013-01-17 23:47:41 +00:00
Ivan De Marino 4dec091ac2 FIX: Check file exist when attempting upload.
Both "page.uploadFile()" and "onFilePicker = function() {}" check file exists before accepting them.
If file don't exists, they are "ignored".

Fixes issue #941: https://code.google.com/p/phantomjs/issues/detail?id=941
2013-01-17 23:45:34 +00:00
Vitaliy Slobodin a7a3928af9 Fix compilation on Windows.
We need to include QtCore/qt_windows.h on Windows since Q_PID mapped to
_PROCESS_INFORMATION, but _PROCESS_INFORMATION not defined.

Issue:
http://code.google.com/p/phantomjs/issues/detail?id=219
2013-01-16 08:00:52 -08:00
James M. Greene 1a487d2bbf Added myself to the copyright list 2013-01-16 08:00:51 -08:00
James M. Greene 360dc3a30c Corrected default value for disk-cache help
Fixes http://code.google.com/p/phantomjs/issues/detail?id=908
2013-01-16 08:00:51 -08:00
Ariya Hidayat 34ed1169f3 Record more changes for the upcoming 1.9.
http://code.google.com/p/phantomjs/issues/detail?id=939
2013-01-09 20:35:00 -08:00
Ariya Hidayat d58eae54d7 Ensure we describe onNavigationRequested behavior properly.
http://code.google.com/p/phantomjs/issues/detail?id=562
2013-01-09 20:26:55 -08:00
Ariya Hidayat aaca7774c9 Vagrant setup: Don't clone PhantomJS into Git build directory.
http://code.google.com/p/phantomjs/issues/detail?id=963
2013-01-09 01:03:27 -08:00
Oleg Pudeyev 26e51f4b8a -ldl is needed only on Linux, not on all Unices.
In particular on FreeBSD there is no -ldl as the respective
functionality is in -lc.

http://code.google.com/p/phantomjs/issues/detail?id=597
2013-01-09 00:07:36 -08:00
Oleg Pudeyev c3c17a5364 Use hw.ncpu sysctl on FreeBSD to determine processor count.
Patch by Mike Meyer.

http://code.google.com/p/phantomjs/issues/detail?id=597
2013-01-09 00:07:14 -08:00
Oleg Pudeyev 52e67c5aa7 Use bash from PATH rather than hardcoded in /bin.
E.g. FreeBSD has bash in /usr/local.

http://code.google.com/p/phantomjs/issues/detail?id=597
2013-01-09 00:06:58 -08:00
Ariya Hidayat 69bf72bca7 Setup Vagrant to build Linux packages on CentOS 5.
The goal is to use old glibc so that it can reach more audience (in
particular, RHEL and CentOS users).

Also, we don't compress the executable (using UPX) so that it can be
inspected with ldd. Bonus: no more decompression overhead, faster
startup.

http://code.google.com/p/phantomjs/issues/detail?id=963
2013-01-05 09:35:27 -08:00
Ariya Hidayat aa907343b9 Record more changes for the upcoming 1.9.
http://code.google.com/p/phantomjs/issues/detail?id=939
2013-01-04 23:44:36 -08:00
Vitaliy Slobodin 09e929d599 Allow to abort network requests.
Issue: http://code.google.com/p/phantomjs/issues/detail?id=230
2013-01-04 23:39:23 -08:00
Vitaliy Slobodin fd700b0702 New WebPage callback: onResourceError.
This callback is invoked when the WebPage was unable to request the resource

Issue: http://code.google.com/p/phantomjs/issues/detail?id=954
2013-01-04 21:24:30 -08:00
execjosh d906bc3819 Automate lazy generation of REPL completion lists
All invokable methods, slots, signals, and properties visible from
JavaScript, but which do not start with an underscore, are lazily
(only when necessary) added to the completion list through dynamic
reflection.

This leverages `QMetaObject` for reflection of `QObject`s.  As such,
there is now no need to inherit `REPLCompletable` and it has been
removed.

http://code.google.com/p/phantomjs/issues/detail?id=943
2013-01-04 21:23:58 -08:00
Ariya Hidayat d0fe6864a9 Mac OS X: Fix possible crash when using some TrueType fonts.
This is just a workaround. We simply avoid removing the custom font
(intentionally leak it, a small price to pay) because otherwise it will
invalidate Qt's font cache, which in turns trigger the crash at
CoreText's CTFontCopyGraphicsFont.

http://code.google.com/p/phantomjs/issues/detail?id=690
2012-12-30 21:17:40 -08:00
Ariya Hidayat 2a2b6e455c Mac OS X: Add a manual test for the crash with TrueType fonts.
http://code.google.com/p/phantomjs/issues/detail?id=690
2012-12-30 21:17:39 -08:00
execjosh f52044cd31 Emulate spawn and execFile from node.js's child_process module
This is a rudimentary implementation of the following methods
from [node.js's `child_process` module][1]:

 *  `spawn`
 *  `execFile`

The examples are relevant only for *nix operating systems...

The following methods are Not Yet Implemented™:

 *  `exec`
 *  `fork`

[1]: http://nodejs.org/docs/v0.8.16/api/child_process.html

http://code.google.com/p/phantomjs/issues/detail?id=219
2012-12-29 01:03:08 +09:00
Ariya Hidayat 83e8152dd6 Collect some changes for the upcoming 1.9.
http://code.google.com/p/phantomjs/issues/detail?id=939
2012-12-25 22:37:00 -08:00
Ariya Hidayat 98ce8922c6 ChangeLog: Add missing window.location fix.
http://code.google.com/p/phantomjs/issues/detail?id=863
2012-12-25 22:36:53 -08:00
execjosh 836719f72e Implement CommonJS IO/A read([n Number])
The [IO/A spec][1] for `read` is as follows:

> Read up to n bytes from the stream, or until the end of the stream
> has been reached. [If] n is null, reads up to the block size of the
> underlying device, or up to 1024 bytes if the block size is not
> discernible. If n is not specified, this method always reads the
> full stream until its end is reached. ...

Since discovering the block size of the underlying device is
non-trivial, we will just default to 1024.

**NOTE**

The initial implementation of `File::read()` saves the current
(original) position, seeks to the beginning of the stream,
`readAll`s to the end, and then resets to the original position.

  I think that this behavior is unexpected and should be changed--it
should read from the current position to the end of the stream and
stay there.  The user should explicitly `seek` to the beginning of
the stream when necessary.

  With the current implementation, the user should note that the
position *will not change* after calling `read()` with no arguments.

[1]: http://wiki.commonjs.org/wiki/IO/A#Instance_Methods

http://code.google.com/p/phantomjs/issues/detail?id=938
2012-12-25 20:46:14 -08:00
execjosh 6bc3a93118 Add `seek` method to `File` class
This method is necessary for random-access streams.  It will also be
helpful in the future when implementing the [IO/A spec][1].

[1]: http://wiki.commonjs.org/wiki/IO/A#Instance_Methods

http://code.google.com/p/phantomjs/issues/detail?id=937
2012-12-25 13:11:20 -08:00
execjosh f6c87221a7 Implement system.std{in,out,err}
See [issue 333][1] and pull request #192.

**Caveat**

`File::read` currently takes no parameters and is equivalent to a
"`readAll`".  This will be changed later to match [IO/A Spec's
`Stream#read`][2]; but, should still be noted.

[1]: http://code.google.com/p/phantomjs/issues/detail?id=333
[2]: http://wiki.commonjs.org/wiki/IO/A#Instance_Methods
2012-12-25 03:41:34 -08:00
Ken Collins e3517f108a Add Mocha-PhantomJS
This project has gotten a pretty good following over the past few months. Would be great to have it in the list.
2012-12-24 17:06:34 -05:00
Ariya Hidayat d7652abc11 Unix packaging: Fix UPX detection for binary compression.
As pointed out by Cristian Ciupitu, our UPX detection logic was broken.
This is now fixed by using `type` to look for the executable.

http://code.google.com/p/phantomjs/issues/detail?id=928
2012-12-23 14:36:24 -08:00
Ariya Hidayat 3f42fb230f Linux: Ensure we use 72 dpi.
For our QPA/Lighthouse platform screen, apparently we need to specify the
physical screen size because otherwise the default 100 dpi will be used.

This also brings font rendering on headless Linux to 72 dpi.

http://code.google.com/p/phantomjs/issues/detail?id=659
2012-12-23 12:03:10 -08:00
Ariya Hidayat fac15407e8 Call the development branch as version 1.9. 2012-12-23 08:57:37 -08:00
execjosh 3458d4d507 Use fs.join(...) instead of fs.separator
http://code.google.com/p/phantomjs/issues/detail?id=361
2012-12-22 23:06:20 -08:00
execjosh 03500e6b55 Implement fs.{split(path),join(...),{to,from}NativeSeparators}
For fs.{split,join} specs, see: http://wiki.commonjs.org/wiki/Filesystem/A#Paths_as_Text

http://code.google.com/p/phantomjs/issues/detail?id=361
2012-12-22 23:05:46 -08:00
Vitaliy Slobodin fc7a5b7b9f Add a bunch of gitignores for Windows 2012-12-22 22:36:04 -08:00
Ariya Hidayat c33b916cfb More 1.8 materials.
http://code.google.com/p/phantomjs/issues/detail?id=863
2012-12-21 22:12:05 -08:00
Ivan De Marino d998c59358 Importing GhostDriver v1.0.2.
Changes listed here: https://github.com/detro/ghostdriver/issues?labels=1.0.2&page=1&state=closed
2012-12-19 19:29:54 -08:00
Ariya Hidayat 8836398825 Generalize WebServer binary data handling into a real encoding support.
http://code.google.com/p/phantomjs/issues/detail?id=505
2012-12-17 23:12:48 -08:00
Sebastian Krzyszkowiak f70a6ab4ee Add test case for WebServerResponse::setEncoding
http://code.google.com/p/phantomjs/issues/detail?id=505
2012-12-17 19:27:19 -08:00
Sebastian Krzyszkowiak 78e72312dc Implement WebServerResponse::setEncoding in order to allow binary encoding to be sent.
Fixes http://code.google.com/p/phantomjs/issues/detail?id=505
2012-12-17 19:27:06 -08:00
Ivan De Marino 302050e0ce Fixing typo in GhostDriver 1.0.1 2012-12-17 19:15:43 -08:00
Ariya Hidayat 9a8b84a293 More changes for 1.8.
http://code.google.com/p/phantomjs/issues/detail?id=863
2012-12-16 23:16:37 -08:00
Ariya Hidayat 9c0888d54d Fix potential hang in the example scripts due to missing exit() call.
Patch by Jônatas Pedraza <jonatas.nona@gmail.com> and Vivek Galatage
<vivekgalatage@gmail.com>.

http://code.google.com/p/phantomjs/issues/detail?id=922
2012-12-16 23:02:44 -08:00
David Burrows 15fe514025 Increase maximum number of redirects in line with modern browsers.
Modern browser mostly limit re-directs to 20. The current limit in  PhantomJS is 10 which is not in line with most browsers. This patch is a simple increase of gMaxRedirections from 10 to 20.

http://code.google.com/p/phantomjs/issues/detail?id=849
2012-12-16 22:21:07 -08:00
qubird f6a91a8813 New WebPage#setContent api - makes possible to specify location along with content
http://code.google.com/p/phantomjs/issues/detail?id=909
2012-12-16 15:43:10 -08:00
Ariya Hidayat daae36c3ba Some changes for 1.8.
http://code.google.com/p/phantomjs/issues/detail?id=863
2012-12-16 14:48:28 -08:00
fastclemmy 3b2a1c27a1 Update examples/pizza.coffee.
Guess the DOM has changed a little. No more class .address but an (incorrectly used) <address> tag instead. (same pull request as the vanilla JS example)

http://code.google.com/p/phantomjs/issues/detail?id=921
2012-12-16 14:20:57 -08:00
fastclemmy 8f14ef027e Fix examples/pizza.js.
Guess the DOM has changed a little. No more class .address but an (incorrectly used) <address> tag instead.

http://code.google.com/p/phantomjs/issues/detail?id=921
2012-12-16 14:19:57 -08:00
Ivan De Marino 027aa93b18 Importing GhostDriver version `1.0.1`.
Changes are documented here:
https://github.com/detro/ghostdriver/issues?labels=1.0.1&state=closed.

https://github.com/detro/ghostdriver/issues/130
2012-12-16 13:55:58 -08:00
Ivan De Marino f5652e5110 Fix "--webdriver-selenium-grid-hub" CLI parameter.
I had forgotten to update the option parsing code,
and the option was never picked.

Related issue: [GhostDriver #130](https://github.com/detro/ghostdriver/issues/130).
2012-12-13 23:45:54 -08:00
Vitaliy Slobodin 04b74f99fd Enable WOFF file support.
Background:
WOFF format requires that WebKit should be compiled with zlib.

Related issues:
http://code.google.com/p/phantomjs/issues/detail?id=592
2012-12-12 21:42:58 -08:00
Jon Leighton eb3c9caa6e Upgrade to Qt 4.8.4
http://code.google.com/p/phantomjs/issues/detail?id=918
2012-12-12 21:42:45 -08:00
Jon Leighton 66ab9a1113 Fix memory leak on linux
We were previously adding the certificates on each instantiation of
NetworkAccessManager, causing memory consumption to grow unbounded.

I have also removed the Qt version check. It's unnecessary as we only
build against a fixed Qt version.

https://code.google.com/p/phantomjs/issues/detail?id=882
2012-12-12 21:25:26 -08:00
Vitaliy Slobodin 5eb0f64e6b Fix window.location.
Description:
Web Page can't navigate to a relative url using the property 'window.location'.

Upstream bug:
https://bugs.webkit.org/show_bug.cgi?id=47978

Issues:
http://code.google.com/p/phantomjs/issues/detail?id=632
http://code.google.com/p/phantomjs/issues/detail?id=530
2012-12-12 17:03:37 +04:00
James M. Greene 31dd714a22 Added getters for the WebPage#onError and phantom.onError properties
Fixes http://code.google.com/p/phantomjs/issues/detail?id=910
2012-12-11 21:57:25 -08:00
Jon Leighton 487fbf3035 Enable multiple files to be uploaded to a file input
Obviously, the input must have the multiple attribute for this to work.

The API is:

    page.uploadFile('#file_input', ['file1', file2'])

I haven't implemented support for multiple files in the page.filePicker
API because I couldn't work out how to get a return value of an array
of strings through the JS/C++ bridge.

https://code.google.com/p/phantomjs/issues/detail?id=256
2012-12-11 21:41:02 -08:00
James M. Greene e8380e42d7 Added CoffeeScript examples where missing, minor other fixes
Added CoffeeScript examples where missing, minor other fixes such as spacing standardization (2 spaces is the standard in CoffeeScript via Ruby). Also a small set of minor JS example fixes and additional comments.

Fixes http://code.google.com/p/phantomjs/issues/detail?id=907
2012-12-06 14:29:37 -06:00
James M. Greene 4c285c419d Removed an invalid spec file and an invalid spec include.
Fixes http://code.google.com/p/phantomjs/issues/detail?id=906
2012-12-06 08:27:55 -08:00
James M. Greene f61635f2d4 Adding 'WebPage#close' calls where appropriate in example scripts.
Fixes http://code.google.com/p/phantomjs/issues/detail?id=903
2012-12-06 08:27:06 -08:00
James M. Greene c9f9b5a14b Added getters for all of the WebPage signal//callback handlers.
Fixes http://code.google.com/p/phantomjs/issues/detail?id=899
2012-12-05 23:43:50 -06:00
Ariya Hidayat a777797942 Stub for 1.8 changes.
http://code.google.com/p/phantomjs/issues/detail?id=863
2012-12-04 08:41:40 -08:00
Jan Schaumann 94e1f40ad9 Add a spec file to allow creation of an rpm from the (previously built) binary.
http://code.google.com/p/phantomjs/issues/detail?id=897
2012-11-30 22:31:50 -08:00
Milian Wolff fd653fe61f Properly use bottom margin to calculate the footer height.
http://code.google.com/p/phantomjs/issues/detail?id=894
2012-11-29 13:42:18 +01:00
Ivan De Marino 4caa71a6b7 Importing latest GhostDriver, tag "1.0.0".
http://code.google.com/p/phantomjs/issues/detail?id=49
2012-11-27 08:00:45 -08:00
Ivan De Marino ffa9fab316 Embedding GhostDriver into PhantomJS(!!!)
Finally. After so much work, this is finally a reality.
To launch PhantomJS in "Remote WebDriver mode":

```bash
$ phantomjs --webdriver=OPTIONAL_IP:OPTIONAL_PORT
```

Also, GhostDriver brings along support for Selenium Grid: now PhantomJS can register itself to a Selenium Grid HUB.
Just launch it in Webdriver Mode with the following extra options:
```bash
$ phantomjs --webdriver=OPTIONAL_IP:OPTIONAL_PORT --webdriver-selenium-grid-hub=http://url.to.selenium.grid.hub:port
```

http://code.google.com/p/phantomjs/issues/detail?id=49
2012-11-27 07:58:34 -08:00
Ivan De Marino 2dcccc8968 First import of `ghostdriver.qrc` & related files.
http://code.google.com/p/phantomjs/issues/detail?id=49
2012-11-27 07:58:13 -08:00
Vitaliy Slobodin 63dd36205f Don't perform on-demand loading of root certificates on Linux
Description:
Qt is performing loading on-demand of root certificates on Linux, which causing SSL errors.

Issue:
http://code.google.com/p/phantomjs/issues/detail?id=882
2012-11-24 16:41:03 +04:00
Milian Wolff 2d778f687e Repeat thead and tfoot when table contains page breaks.
This was already done in https://github.com/ariya/phantomjs/pull/211
but somehow got lost when the Qt source tree was imported.

Note that I even improved this patch a bit to also properly repaint
the borders of cells in thead/tfoot.

http://code.google.com/p/phantomjs/issues/detail?id=615
2012-11-22 15:39:07 +01:00
Milian Wolff 5c87852c32 Prevent page breaks in table rows.
This was part of a previous PhantomJS release but got reverted
when the Qt source tree was imported. See the old pull request
here: https://github.com/ariya/phantomjs/pull/211

http://code.google.com/p/phantomjs/issues/detail?id=880
2012-11-22 15:38:58 +01:00
Ivan De Marino 9ba13ba989 Implementing "goBack", "goForward" and "go".
Completing work for [Issue #808](http://code.google.com/p/phantomjs/issues/detail?id=808).
2012-11-18 16:11:25 -08:00
Vitaliy Slobodin 40a14b72b1 Restore dirty line logic in RenderInline::destroy.
WebKit upstream fix: http://trac.webkit.org/changeset/86060
WebKit upsteam bug: https://bugs.webkit.org/show_bug.cgi?id=60448

Related issues:
http://code.google.com/p/phantomjs/issues/detail?id=704
http://code.google.com/p/phantomjs/issues/detail?id=703
http://code.google.com/p/phantomjs/issues/detail?id=675
http://code.google.com/p/phantomjs/issues/detail?id=689
http://code.google.com/p/phantomjs/issues/detail?id=532
http://code.google.com/p/phantomjs/issues/detail?id=851
2012-11-14 11:28:58 -08:00
Ariya Hidayat 559afcd4e8 Bump the version.
http://code.google.com/p/phantomjs/issues/detail?id=863
2012-11-10 01:45:54 -08:00
Ariya Hidayat 59dbd77ef5 Ask for a confirmation before initiating the build.
Although it is mentioned in http://phantomjs.org/build.html, many people
are not aware this, they compile from source (even if a binary package
is available) and get shocked to realize the build takes ages.
The build script is thus modified to give the initial warning.

Unattended build is still possible, just use --confirm flag.

http://code.google.com/p/phantomjs/issues/detail?id=862
2012-11-10 00:11:14 -08:00
Ariya Hidayat 7b84e43a10 Merge remote-tracking branch 'JamesMGreene/ExposeProcessId' 2012-11-08 06:24:32 -08:00
James M. Greene 280305797e Exposing the Process ID (PID) via the System module.
`require('system').pid` should return your PhantomJS instance's Process ID.

http://code.google.com/p/phantomjs/issues/detail?id=769
2012-11-06 11:49:55 -06:00
Ivan De Marino eadb03a978 Adding "page.onFilePicker" callback.
This addresses [Issue #843](http://code.google.com/p/phantomjs/issues/detail?id=843).
Important: this doesn't change the ability to use
"page.uploadFile", that will keep working as expected.
2012-11-03 18:41:18 +00:00
Ivan De Marino 1fa9c04845 Reworking code related to Issue #800.
This addresses [Issue #842](http://code.google.com/p/phantomjs/issues/detail?id=842).
2012-11-03 14:38:23 +00:00
Ivan De Marino 7c7d1f961c Adding "date" detection to `detectType`
Addresses [Issue #800](http://code.google.com/p/phantomjs/issues/detail?id=800)
2012-11-03 14:38:22 +00:00
Ivan De Marino 4c5e96d17f FIX: Multiple "onCallback" handlers registered.
Addresses [Issue #807](http://code.google.com/p/phantomjs/issues/detail?id=807)
2012-11-03 14:38:22 +00:00
Ivan De Marino b113993314 MINOR: Avoid frame switching if already there.
Useless to change frame if it's already the right one.
Makes it clearer what is going on when debugging.
2012-11-03 14:38:22 +00:00
Ivan De Marino 3fe308bf8c Adding Navigation methods.
Addresses [Issue #808](http://code.google.com/p/phantomjs/issues/detail?id=808)

* back()        [method]
* canGoBack     [property - boolean]
* forward()     [method]
* canGoForward  [property - boolean]
* reload()      [method]
* stop()        [method]

This is to fill a small gap we ought to deal with.
IMPORTANT: this API is asynchronous. Events
like "onLoadStarted" and "onLoadFinished" are
ideal to monitor the activity of those methods.
2012-11-03 14:38:22 +00:00
Ivan De Marino 9cf6cbe818 MINOR: Fixing typo - "splice !== slice" 2012-11-03 14:38:21 +00:00
Ivan De Marino d5eb657ecc More Douglas Crockford remedials.
Addresses [Issue #800](http://code.google.com/p/phantomjs/issues/detail?id=800)
2012-11-03 14:38:21 +00:00
Ivan De Marino e31528adfe "onLoadFinished" works regardless of "page.open"
Addresses [Issue #801](http://code.google.com/p/phantomjs/issues/detail?id=801)
2012-11-03 14:38:21 +00:00
Ivan De Marino 60ced2ccb6 Provide "detectType" inspired by D. Crockford
Addresses [Issue #800](http://code.google.com/p/phantomjs/issues/detail?id=800)
2012-11-03 14:38:21 +00:00
Ivan De Marino 3f874067f5 Add properties "page.title" and "page.frameTitle"
Addresses [Issue #799](http://code.google.com/p/phantomjs/issues/detail?id=799)
2012-11-03 14:38:21 +00:00
Jim Evans 42bf8b36d8 Making webserver module read request bodies and write response bodies using UTF-8 2012-11-03 14:38:21 +00:00
Jim Evans 395af9cada Correcting keycodes sent for lowercase characters
http://code.google.com/p/phantomjs/issues/detail?id=852
2012-11-02 20:41:57 -07:00
Jim Evans c2df526110 Fixing sending of double-click events
http://code.google.com/p/phantomjs/issues/detail?id=848
2012-11-01 07:18:40 -07:00
Ivan De Marino f2628b32fe Fix compilation issue on Ubuntu.
Reported [here](https://github.com/ariya/phantomjs/commit/402a8d9753395edffb4811aa1834ff31a051e27#commitcomment-2079231).
Conversion from `NULL` to `QVariant()` doesn't work implicitly on Ubuntu.

http://code.google.com/p/phantomjs/issues/detail?id=835
2012-10-31 20:38:16 -07:00
Vitaliy Slobodin f3d920908a QSslConfiguration: SSLv3 should be the default value
http://code.google.com/p/phantomjs/issues/detail?id=174
2012-10-29 06:36:11 -07:00
Vitaliy Slobodin b834f2a590 Allow to specify the SSL protocol for a requests.
http://code.google.com/p/phantomjs/issues/detail?id=174
2012-10-29 06:36:08 -07:00
Jim Evans 380c56e672 Adding test for sendEvent with modifier key
http://code.google.com/p/phantomjs/issues/detail?id=835
2012-10-28 20:58:51 -07:00
Jim Evans f402a8d975 Implementing modifier keys in sendEvent()
http://code.google.com/p/phantomjs/issues/detail?id=835
2012-10-28 20:56:46 -07:00
Johan Sköld b7ca845327 Gave page a maxAuthAttempts setting.
QtWebKit normally loops infinitely trying to authenticate when it receives a
401 code, preventing all callbacks (onLoadFinished, onResourceReceived, etc).
This commit changes it to only try a set amount of times before aborting.

https://code.google.com/p/phantomjs/issues/detail?id=826
2012-10-24 00:02:59 -07:00
Vitallium 35c1971595 Fix parsing dates in ISO8601 format.
Issues:
http://code.google.com/p/phantomjs/issues/detail?id=187
http://code.google.com/p/phantomjs/issues/detail?id=267
2012-10-24 00:00:58 -07:00
Ivan De Marino e521dc16e7 Adding a simple example to help understand events.
Lots of discussions on the ML could be easily put
to rest if people could run something like this
and see the result.
It's not a real fix or improvement, just a "cute"
example and as such I didn't raise a "proper"
issue.
2012-10-16 21:50:53 -07:00
Ariya Hidayat 4f17d94afd Update the link to the crash reporting guide.
http://code.google.com/p/phantomjs/issues/detail?id=576
2012-09-28 08:03:25 -07:00
Vitaliy Slobodin 2403c00e59 Added version info for Windows
http://code.google.com/p/phantomjs/issues/detail?id=797
2012-09-24 07:57:01 -07:00
Ariya Hidayat 8ba3c52d50 Stop potential crash by guarding the access to the page.
Based on the work from Shawn Krisman (krisman.shawn@gmail.com).

http://code.google.com/p/phantomjs/issues/detail?id=719
2012-09-24 07:33:48 -07:00
Ariya Hidayat 63e06cbcbf Revert breaking behavior in commit ecda224233.
Keeping the page alive instead of destroying causes unexpected behavior
compared to version 1.6 and earlier. See the discussion:
https://groups.google.com/d/topic/phantomjs/C84fmd21LDk/.

http://code.google.com/p/phantomjs/issues/detail?id=719
2012-09-24 07:31:27 -07:00
Ariya Hidayat f29827f201 README: Clarify capture-able contents.
http://code.google.com/p/phantomjs/issues/detail?id=764
2012-09-23 22:37:17 -07:00
Ariya Hidayat 9a0f8d0e3a Point to the new wiki.
http://code.google.com/p/phantomjs/issues/detail?id=764
2012-09-23 22:34:12 -07:00
Ariya Hidayat 703a4d14e4 Breakpad symbol tool: Make sure it builds on Mac.
https://code.google.com/p/phantomjs/issues/detail?id=576
2012-09-23 22:20:35 -07:00
Ariya Hidayat 5e91e5355d Blazing Star.
http://code.google.com/p/phantomjs/issues/detail?id=764
2012-09-22 21:29:20 -07:00
Ariya Hidayat b9e1ced36f Bracing for "Blazing Star".
http://code.google.com/p/phantomjs/issues/detail?id=764
2012-09-22 20:24:58 -07:00
Ariya Hidayat e5b040ed1a Advertise the migrated wiki pages. 2012-09-22 19:58:04 -07:00
Ariya Hidayat 7921cb00e1 Remove non-working weather example.
The example stops working since the request is blocked. It needs a
rewrite to use a different service.

http://code.google.com/p/phantomjs/issues/detail?id=794
2012-09-22 13:39:19 -07:00
Ariya Hidayat 58f970a30d Remove outdated Debian control files.
Rather than advertising wrong info (PyPhantomJS etc), debian/ is
removed until new up-to-date content is prepared.

http://code.google.com/p/phantomjs/issues/detail?id=793
2012-09-21 07:51:14 -07:00
Ivan De Marino 32e23339bd Fixing issue with CookieJar not loading at boot.
* Using the "QTimer::singleShot" bites back in the ass
* The "script" takes priority and runs before the SLOT is actually invoked

Why was I using a Timer?
Not sure anymore: it must have slipped in while I was trying to work out
all the other issues I had with QNetworkCookieJar, and I left it there.

http://code.google.com/p/phantomjs/issues/detail?id=790
2012-09-21 07:39:12 -07:00
Ariya Hidayat 8ab4209e0f More changes for the upcoming 1.7.
http://code.google.com/p/phantomjs/issues/detail?id=764
2012-09-21 00:31:51 -07:00
Ian Oxley e85140e80f Non-zero exit code if any test fails.
In the callback function passed to `waitFor`, the call to `page.evaluate`
returns a 1 or 0, and this is then passed to `phantom.exit` (with a 1
indicating at least one test failed, 0 indicating all tests passed).

http://code.google.com/p/phantomjs/issues/detail?id=792
2012-09-21 00:12:52 -07:00
Ian Oxley 1dbd371540 Added 'tests passed' message.
If all tests pass, a message indicating this is output to the console.

http://code.google.com/p/phantomjs/issues/detail?id=792
2012-09-21 00:12:30 -07:00
Ian Oxley be767ee983 Test failure CSS selectors changed.
Changed the CSS selectors used to identify failed tests.

The old selector was `div.jasmine_reporter > div.suite.failed`,
but this no longer seems to match any elements.

The new selector is `.results > #details > .specDetails.failed`. For each
failing test the `.description` and `.resultMessage.fail` elements are
used to output the failures to the console.

http://code.google.com/p/phantomjs/issues/detail?id=792
2012-09-21 00:11:43 -07:00
Ian Oxley 2662d5875b Changed CSS selector used when checking for whether tests have finished.
When using the jasmine 1.2.0 standalone version, `.runner .description`
doesn't seem to match any elements.

I noticed pending tests can be found using the CSS selector
`.symbolSummary .pending`, so changed the testFx callback to check
that no elements are left matching this selector.

http://code.google.com/p/phantomjs/issues/detail?id=792
2012-09-21 00:11:24 -07:00
Shawn Krisman ecda224233 Revert "Fix crash on exit (Issues #136, #148 and #149)"
This reverts commit 5acaa6b42d.

Conflicts:

	src/phantom.cpp
	src/phantom.h

removed m_page deletion.

http://code.google.com/p/phantomjs/issues/detail?id=719
2012-09-21 00:07:09 -07:00
Ariya Hidayat 9f8056334e Keep ARGB32 premultiplied format for Windows for the time being.
http://code.google.com/p/phantomjs/issues/detail?id=785
2012-09-21 00:05:18 -07:00
Ariya Hidayat 18ca114111 Windows: Use ARGB32 premultiplied to have better font rendering.
Thanks to Vitaliy Slobodin for the analysis.

http://code.google.com/p/phantomjs/issues/detail?id=785
2012-09-20 23:52:05 -07:00
Ariya Hidayat cab2635e66 Make the key enums as part of WebPage instance.
This way, we don't add anything into phantom object.

http://code.google.com/p/phantomjs/issues/detail?id=492
2012-09-20 23:44:06 -07:00
Jon Leighton e7c37d4a2b Fix --help and --version
https://code.google.com/p/phantomjs/issues/detail?id=789
2012-09-19 21:56:56 +01:00
Ariya Hidayat 0d63e9c0a8 Contribution guide: highlight various aspects of communication.
http://code.google.com/p/phantomjs/issues/detail?id=783
2012-09-18 18:23:19 -07:00
Ariya Hidayat 9a25f31715 Merge pull request #319 from detro/ghostdriver-dev
GhostDriver Development Branch - Master Push #4
2012-09-18 18:08:07 -07:00
Ivan De Marino 26583740c8 Made the "Callbacks injection" recursive.
Before this, only the first level of child frames had the possibility to use
the Callbacks object. Now is injected recursively in all of them.

This is an extension of coverage for [Issue #683](http://code.google.com/p/phantomjs/issues/detail?id=683).
2012-09-18 22:46:14 +01:00
Ivan De Marino e5ebcf90df Git-ignoring debugging-helper on mac 2012-09-18 14:57:59 +01:00
Ivan De Marino b1185cd22a Redesign the Cookies API (part 2)
Addresses [Issue #761](http://code.google.com/p/phantomjs/issues/detail?id=761).

This is a combination of 5 commits.

1. Date in Cookie can be set via "seconds since epoch" as well.

* In addition to the current string format, we can now set cookies via integer of msec since epoch
* Expiration date can be set via "expires" or "expiry" option ("expires" has priority)
* Returned cookie will contain "expires" as string and "expiry" as msec since epoch

I believe this can simplify code that uses cookies and it doesn't change the functionality.

2. Applying the "--debug" command line options as early as possible.

3. Fixing bug and behaviour in the CookieJar

* It's not possible to set a cookie without a domain: will default to the domain of the page it's set on
* "page.clearCookies()" was broken
* "cookiejar.deleteCookie("name", url)" reimplemented because deleting via "expiration" doesn't work

4. Improving (and more fixing) in the CookieJar

* Purging Session or Expired Cookies now works
* Added boolean return values to inform if the requested cookie operation succeeded
* Timestamps for "expiry/expires" in Milliseconds, as JS does by default
* Improved detection that a cookie has been accepted or rejected by the cookiejar

NOTE: Unfortunately, the Qt provided QNetworkCookieJar is a very limited
and not extremely well designed solution. It doesn't provide any "nice
and clean" CRUD API, and you are only left with a SET/GET to deal with.
Mechanism to understand when and when not a cookie is added are hidden,
and require extra work in the sub-class (our CookieJar) to fill the gap.

5. Methods on the "phantom" object to manipulate the CookieJar.

* phantom.cookies (array of JSON/Cookies)
* phantom.cookiesEnabled (boolean)
* phantom.addCookie
* phantom.deleteCookie
* phantom.clearCookies

Those methods operate on the CookieJar directly and have no URL restriction.
In other words, if page P1 can see set of cookies C1, and page P2 can see set of
cookies C2, "phantom.cookies" can see (i.e. operate upon) both C1 and C2.
2012-09-18 08:42:13 +01:00
Ariya Hidayat 64fa65edaf More changes for the upcoming 1.7.
http://code.google.com/p/phantomjs/issues/detail?id=764
2012-09-18 00:41:20 -07:00
Ariya Hidayat 22c8e5610f Fix the link to the contribution guide.
http://code.google.com/p/phantomjs/issues/detail?id=783
2012-09-17 23:41:23 -07:00
Ariya Hidayat 2c4e95ad3e Use GitHub contributing guide feature.
See https://github.com/blog/1184-contributing-guidelines.

http://code.google.com/p/phantomjs/issues/detail?id=783
2012-09-17 23:37:18 -07:00
Zhaolong 62584ce7d4 Remove the dirty link hack for a static PhantomJS + MSVC.
http://code.google.com/p/phantomjs/issues/detail?id=753
2012-09-17 22:13:40 -07:00
Ryan Cumming 23fe144a39 Treat all args after the script name as script args
This fixes CapserJS which builds a command line like this:
phantomjs bin/bootstrap.js --casper-path=~/capserjs --cli

That works on Phantom 1.6 but not on master due to the qcommandline
port.

Fix by extending qcommandlne to take a ParameterFence flag which causes
it to treat any options after a parameter as arguments. Switch
"scriptname" to use that so the 1.6 behaviour is restored.

http://code.google.com/p/phantomjs/issues/detail?id=55
2012-09-17 22:05:42 -07:00
Harry Waye 4f7df7073a Maintain m_currentFrame as opposed to using QWebPage's currentFrame().
Currently focused frame made available with page.focusedFrameName and page.switchToFocusedFrame.

http://code.google.com/p/phantomjs/issues/detail?id=683
2012-09-17 21:59:05 -07:00
Ariya Hidayat e33bfedb9a Merge pull request #317 from Vitallium/fix-missing-ico-plugin-win
Rendering ICO images on Windows.
2012-09-17 21:58:07 -07:00
Vitaliy Slobodin af49821cf4 Render ICO images on Windows.
ICO images are not rendered on Windows due to missing ICO plugin.

Issue: http://code.google.com/p/phantomjs/issues/detail?id=779
2012-09-17 10:46:49 +04:00
Ariya Hidayat 1558c07a76 Merge pull request #314 from JakubOboza/patch-1
Update src/config.cpp
2012-09-14 04:10:31 -07:00
Jakub 1ab5c66df8 Update src/config.cpp
This is a patch to resolve issue i reported in ticket 773 <http://code.google.com/p/phantomjs/issues/detail?id=773>. 
I did build it and run tests seems to be working fine.

I hope this helps a bit :) Also i'm sending friday hugs to everyone on the team.
2012-09-14 12:05:52 +02:00
Ariya Hidayat 795d067f4f Mocha tests can run with PhantomJS.
See https://github.com/metaskills/mocha-phantomjs.
2012-09-13 21:41:09 -07:00
Ariya Hidayat 27d6f908e4 README: Mention the Contribution Guide as early as possible. 2012-09-08 07:04:13 -07:00
Ariya Hidayat 3479beb894 Enumerate some important changes for the upcoming 1.7.
http://code.google.com/p/phantomjs/issues/detail?id=764
2012-09-07 21:12:59 -07:00
Ivan De Marino bd21373732 Redesign the Cookies API
Addresses [Issue #761](http://code.google.com/p/phantomjs/issues/detail?id=761).

This is a squash of 5 commits.

1. Complete reimplementation of the CookieJar and the Cookie API - Part 1.

The save/load mechanism is inspired by the Qt Demo "browser".
More info: http://doc.qt.nokia.com/4.7-snapshot/demos-browser.html

2. Making the CookieJar a singleton.

We need to have multiple NetworkAccessManager to monitor the network activity of the page,
but we also need to maintain 1 CookieJar: in this way we now have a shared bucket of Cookies.

3. Exposing the new Cookies API to the JS space.

* Updated the completions.
* Ensured backward compatibility of the API.
* It's now possible to "phantom.cookieEnabled = false" to disable cookies completely.
* New methods: addCookie, deleteCookie, clearCookies

4. Provided some internal Doc for the new Cookies API

5. Ensuring the "page.deleteCookie(name)" method works only if a cookie name is given.
2012-09-07 00:03:03 -07:00
Ivan De Marino 5cb68a1585 Cleaning up some useless TODO left in the code. 2012-09-05 23:31:31 -07:00
Ivan De Marino 6217d6b960 Adding "url" and some frame-related Q_PROPERTIES
* url - current page url
* frameUrl - current frame url
* frameContent - current frame HTML content
* framePlainText - current frame content in Plain Text (no tags)

Fixes [Issue #758](http://code.google.com/p/phantomjs/issues/detail?id=758)
2012-09-05 21:14:59 -07:00
Ivan De Marino 5b25c6feea Adding support for more Mouse Events.
Support for Mouse Events: Left-click, Right-Click, Middle-Click and Double-Click.
Addresses [Issue 712](http://code.google.com/p/phantomjs/issues/detail?id=712)
2012-09-04 09:49:25 -07:00
Ivan De Marino 70d1ff8392 Adding and Removing appropriate auto-completions (REPL). 2012-09-04 09:49:25 -07:00
Ivan De Marino a65be87642 Fixing wrong parameters manipulations in "page.evaluateAsync". 2012-09-04 09:49:24 -07:00
Ivan De Marino 733d21042b Adding property "page.ownsPages".
When set to "true", any page that gets created, is
owned by the "page" that control it's lifetime.
Also, the pages can be found in the "page.pages[]" array.

Default value is "true".

Addresses [Issue #151](http://code.google.com/p/phantomjs/issues/detail?id=151)
2012-09-04 09:49:24 -07:00
Ivan De Marino 27dc699919 Added "page.close()" and "page.onClosing = function(page){}" callback.
* Addresses [Issue 678](http://code.google.com/p/phantomjs/issues/detail?id=678)
* "page.close()" deprecated "page.release()"
* the callback "onClosing(page)" gets back the reference to the closing page - that can be ideal to have 1 handler for all the page that close
* It works both when closing directly the page, or if the page closes by itself
* If parent closes, child close too

Tests provided.
2012-09-04 09:49:24 -07:00
Ariya Hidayat 0a0fa917ff Add the missing local storage change in Lavender.
http://code.google.com/p/phantomjs/issues/detail?id=598
http://code.google.com/p/phantomjs/issues/detail?id=300
2012-09-04 08:04:26 -07:00
Ariya Hidayat 2e96c7c359 Ensure QCommandLine builds with VS 2010.
The fix is from Vitaliy Slobodin <vitaliy.slobodin@gmail.com>

http://code.google.com/p/phantomjs/issues/detail?id=55
2012-09-04 08:01:33 -07:00
Ariya Hidayat 93686d8306 Allow bypassing automatic use and detection of system proxy.
Pass the command-line option --proxy-type=none to completely bypass any proxy.

http://code.google.com/p/phantomjs/issues/detail?id=580
2012-09-03 18:20:02 -07:00
Ariya Hidayat 4d95cf2783 Show a warning when requesting a secure resource without SSL support.
Special thanks to Thiago Maciera for the tip on "https" scheme.

http://code.google.com/p/phantomjs/issues/detail?id=484
2012-09-03 16:15:49 -07:00
Ivan De Marino b3a0eeff87 Fix handling of boolean values in Config.cpp
http://code.google.com/p/phantomjs/issues/detail?id=55
2012-09-03 13:44:21 -07:00
Ariya Hidayat 3b161b914a Add 'isSSLSupported' to the system module.
http://code.google.com/p/phantomjs/issues/detail?id=484
2012-09-03 06:50:34 -07:00
Ariya Hidayat 08bd78f7b9 Use QCommandLine for command-line options handling.
http://code.google.com/p/phantomjs/issues/detail?id=55
2012-09-03 06:02:05 -07:00
Ariya Hidayat 094d3381e8 Build QCommandLine.
http://code.google.com/p/phantomjs/issues/detail?id=55
2012-09-03 06:02:00 -07:00
Ariya Hidayat a5eb729c9d Modify QCommandLine to suit our needs better.
Allow null shortname for options.
Do not include params in the help text.

http://code.google.com/p/phantomjs/issues/detail?id=55
2012-09-03 06:01:36 -07:00
Ariya Hidayat 614259df0e Import QCommandLine 0.3.0 into our source tree.
http://code.google.com/p/phantomjs/issues/detail?id=55
2012-09-03 05:48:58 -07:00
neraliu 4e1735c899 Implement in-memory cookies storage for CookieJar.
http://code.google.com/p/phantomjs/issues/detail?id=603

Squashed commit of the following:

commit 2087320b9549aa2bba53d73e8a681133e5b4fe96
Author: neraliu <neraliu@gmail.com>
Date:   Sat Jul 14 20:55:17 2012 +0800

    Improve the readability of the function CookieJar::setCookies and CookieJar::cookies.

commit 7ef076e9df488c8f82863cb9c6e31350af5eaad8
Author: neraliu <neraliu@gmail.com>
Date:   Fri Jul 13 18:08:07 2012 +0800

    Fix the indentation problem in the file cookiejar.cpp.
    Remove some commented code segment in cookiejar.cpp.

commit d8fd7f49eb1ba0fb47c27aec9b3dcd36ca14f301
Author: neraliu <neraliu@gmail.com>
Date:   Fri Jul 13 18:04:41 2012 +0800

    Simplify the implementation of CookieJar::setCookiesFromUrl to use the same security policy of QNetworkCookieJar::setCookiesFromUrl in QtWebkit

commit f5e34d2b787bb9714c45a8ad0baff8b5282d3249
Author: neraliu <neraliu@gmail.com>
Date:   Fri Jul 13 17:20:38 2012 +0800

    Simplify the implementation of CookieJar::cookiesForUrl to use the same security policy of QNetworkCookieJar::cookiesForUrl in QtWebkit.

commit 5b10e3788cce7bd69bb71c7ee06f0b49e1e92228
Author: Nera Liu <neraliu@gmail.com>
Date:   Mon Jun 25 10:56:32 2012 +0800

    Remove the clearAllCookies() api by allowing to clear cookies by page.cookies = [] Javascript syntax.

commit a1f12b2913b6f3a3f11a2d22b5eb8c35bf62bf48
Author: Nera Liu <neraliu@gmail.com>
Date:   Sun Jun 24 21:48:49 2012 +0800

    Implement in-memory cookies storage for CookieJar allowing dynamic cookie manipulation via Javascript for issue 603.

    Add sanity check for the in-memory cookies storage for CookieJar.

    http://code.google.com/p/phantomjs/issues/detail?id=603
2012-09-03 04:30:49 -07:00
Jim Evans 55a660f35a Only define _HAS_TR1=0 for Visual Studio 2008 and below.
It is already defined in Visual Studio 2010 and later.

http://code.google.com/p/phantomjs/issues/detail?id=744
2012-09-01 12:08:34 -07:00
Jim Evans e7499d0b33 Windows: Adding static build settings.
(Q_NODLL Q_DECL_IMPORT QT_STATIC_BUILD STATIC) to DEFINES list for WebKit build
to quiet linker warnings.

http://code.google.com/p/phantomjs/issues/detail?id=744
2012-09-01 12:08:05 -07:00
Jim Evans d2c3a078ab Suppressing warning C4099, C4100, C4189.
C4900 (Object declared as a struct is defined as a class), C4100 (A formal
parameter to a function is not referenced in the function body), and
C4189 (A variable is declared and initialized, but not used).

http://code.google.com/p/phantomjs/issues/detail?id=744
2012-09-01 12:07:09 -07:00
Jim Evans b8c28cd42a Removed now-unneeded copy of JavaScriptCore and WebCore object files to different location.
Also replaced single backslash with double backslash in OPENSSL_LIBS variable so paths will be properly escaped.

http://code.google.com/p/phantomjs/issues/detail?id=744
2012-09-01 12:06:35 -07:00
Ilya Grigorik fafa01d6ba Add missing pageref attribute to HAR and end-time.
http://code.google.com/p/phantomjs/issues/detail?id=733

Squashed commit of the following:

commit c6b984442c8631ac13308f5d72fd35973bd964d1
Author: Ilya Grigorik <ilya@igvita.com>
Date:   Sun Aug 26 12:23:03 2012 -0700

    add onLoad to pageTimings

commit d2bb53cd7340e920c62bed557bef4e3a1cdc62b2
Author: Ilya Grigorik <ilya@igvita.com>
Date:   Sun Aug 26 12:01:57 2012 -0700

    add mising pageref attr to each entry
2012-08-28 09:17:54 -07:00
Jim Evans 11e8bb1fcd Fixing Windows-specific path issues with loading of modules
http://code.google.com/p/phantomjs/issues/detail?id=721
2012-08-24 05:21:23 -07:00
Ariya Hidayat 0ea2aa0c35 Explicit mentions of third-party code.
http://code.google.com/p/phantomjs/issues/detail?id=718
2012-08-19 12:02:01 -07:00
Ariya Hidayat ae7f39b4ef Add breakpad support for Windows.
Squashed commit of the following:

commit 947ee621067258adc5af382b496868ea6da6a589
Author: Vitaliy Slobodin <vitaliy.slobodin@gmail.com>
Date:   Fri Aug 17 10:34:34 2012 +0400

    Format code according to http://qt-project.org/wiki/Qt_Coding_Style

commit 5aaaa5338370c77dbd7bf7026949b637da536216
Author: Vitaliy Slobodin <vitaliy.slobodin@gmail.com>
Date:   Thu Aug 16 13:12:05 2012 +0400

    Add breakpad support for Windows (crashdumps).
    Issue: http://code.google.com/p/phantomjs/issues/detail?id=576
2012-08-19 00:26:56 -07:00
Ariya Hidayat be5fe36b98 Merge pull request #300 from jonleighton/crash_text
Link to the crash reporting guide
2012-08-04 11:32:02 -07:00
Jon Leighton 1d23a11bd7 Link to the crash reporting guide 2012-08-04 15:08:37 +01:00
Alessandro Portale f6a26033c9 Make the msvc linker happy again.
http://code.google.com/p/phantomjs/issues/detail?id=424
2012-08-03 01:15:34 -07:00
Ariya Hidayat b3b3578a1f Point to the new download info.
http://code.google.com/p/phantomjs/issues/detail?id=662
2012-08-01 01:23:54 -07:00
Ariya Hidayat c191a00277 Better support for OS X Mountain Lion.
require('system').os.version should give "10.8 (Mountain Lion)".

http://code.google.com/p/phantomjs/issues/detail?id=688
2012-07-31 23:37:53 -07:00
Ariya Hidayat c4de69fcaa Qt: Detect Mountain Lion.
Upstream commit: http://qt.gitorious.org/qt/qt/commit/665355e0ba.

http://code.google.com/p/phantomjs/issues/detail?id=688
2012-07-31 23:34:53 -07:00
Ariya Hidayat 9ca88ea681 Better support for Windows 8.
require('system').os.version should give "8" for Windows 8.

http://code.google.com/p/phantomjs/issues/detail?id=684
2012-07-30 05:07:50 -07:00
Ariya Hidayat 5f88a6b95f Qt: Support Windows 8.
Do not display "Qt: Untested Windows..." when running on Windows 8.

Upstream commit: http://qt.gitorious.org/qt/qt/commit/af7e859a3f.

http://code.google.com/p/phantomjs/issues/detail?id=684
2012-07-30 05:07:41 -07:00
Ariya Hidayat c3b30ac136 Windows: Link to multithreaded static run-time library.
As suggested by Alessandro, this gets rid of run-time requirement of MSVC
run-time library.

http://code.google.com/p/phantomjs/issues/detail?id=424
2012-07-27 20:59:34 -07:00
Ariya Hidayat 5bafcd4f8c Isolate static Windows build to MSVC only.
http://code.google.com/p/phantomjs/issues/detail?id=424
2012-07-27 20:59:20 -07:00
Ariya Hidayat d57c8cc0f7 Fix the right compiler define to isolate the static codec on Windows.
http://code.google.com/p/phantomjs/issues/detail?id=645
http://code.google.com/p/phantomjs/issues/detail?id=598
http://code.google.com/p/phantomjs/issues/detail?id=424
2012-07-27 20:59:01 -07:00
Ariya Hidayat 89593bd63d Isolate codec tricks to Windows for now.
http://code.google.com/p/phantomjs/issues/detail?id=645
http://code.google.com/p/phantomjs/issues/detail?id=598
http://code.google.com/p/phantomjs/issues/detail?id=424
2012-07-27 20:58:40 -07:00
Ariya Hidayat b11c6de9ab WIP: Get the PhantomJS+Qt build for MSVC working.
http://code.google.com/p/phantomjs/issues/detail?id=598
http://code.google.com/p/phantomjs/issues/detail?id=424
2012-07-27 20:58:15 -07:00
Ariya Hidayat 5f1a636583 Changes for 1.6.1.
http://code.google.com/p/phantomjs/issues/detail?id=598
2012-07-27 18:16:26 -07:00
Ariya Hidayat 1602394efb detectsniff example: Fix usage text.
http://code.google.com/p/phantomjs/issues/detail?id=680
2012-07-25 01:37:25 -07:00
Ariya Hidayat 281d291cfb Use the new Twitter handle for the examples.
http://code.google.com/p/phantomjs/issues/detail?id=609
2012-07-15 02:13:35 -07:00
Ariya Hidayat 8d0a0b28ed Some more info on X11-less. 2012-07-15 02:11:50 -07:00
Ariya Hidayat b2af7929fb Use the new Twitter handle. 2012-07-15 02:05:08 -07:00
Jon Leighton 31157fbb98 Make static build work on Linux.
Previously, a static build would produce three separate files:
QtWebKit.a, libjscore.a and libwebcore.a. These seem to have
dependencies on each other and this caused the build errors on Linux.

This change means that the sources of jscore and webcore are both built
directly into the QtWebKit.a target. libjscore.a and libwebcore.a are no
longer built. It is then possible to create a static binary on Linux.

http://code.google.com/p/phantomjs/issues/detail?id=413
2012-07-14 23:32:31 -07:00
Ivan De Marino 0ce4dcd719 Provide more "JS-like" API for the current Frame-Switching API.
This addresses issue [#654](http://code.google.com/p/phantomjs/issues/detail?id=654).
2012-07-13 23:35:25 -07:00
Ivan De Marino 8d2384fd29 Tests for the "new" Frame-Switching API
http://code.google.com/p/phantomjs/issues/detail?id=654
2012-07-13 23:35:10 -07:00
Ariya Hidayat b54612bf68 Fix compile for the event handling.
http://code.google.com/p/phantomjs/issues/detail?id=492
2012-07-13 10:41:38 -07:00
Milian Wolff 1b2a84df9c Make Qt::Key accessible via phantom.keys.
We use the Qt Meta Object system to create an easily accessible QVariantMap
representation of the Key enumerator, such that we can now write something
like for example

page.sendEvent(keypress, phantom.keys.Backspace);

http://code.google.com/p/phantomjs/issues/detail?id=492
2012-07-13 10:32:03 -07:00
Milian Wolff bf6fd70c88 Properly handle strings, chars and umlauts in key[press,down,up] events.
http://code.google.com/p/phantomjs/issues/detail?id=492
2012-07-13 10:32:03 -07:00
Nicolas Perriault 11044a8fbd added tests for new keyboard events
http://code.google.com/p/phantomjs/issues/detail?id=492
2012-07-13 10:32:03 -07:00
Nicolas Perriault 25c48d2ed5 draft implementation of keyboard events
http://code.google.com/p/phantomjs/issues/detail?id=492
2012-07-13 10:31:33 -07:00
Ivan De Marino 5f0ed88a90 Handling "window opening" in PhantomJS.
This addresses [Issue #151](http://code.google.com/p/phantomjs/issues/detail?id=151).

Summary of the new API:
- page.pages[]
- page.pagesWindowName[]
- page.getPage(windowName)
- page.windowName
- page.onPageCreated = function(newPage) { ... }

The page object created by the user holds responsibility of the "child" pages it creates.
If a page closes (i.e. window.close()) or a call to "page.pages[i].release()" is done,
the array "page.pages[]" will automatically update to contain only the pages still open.
2012-07-13 09:56:47 -07:00
Ivan De Marino ea83351da3 Tests for the new "window opening" API
http://code.google.com/p/phantomjs/issues/detail?id=151
2012-07-13 09:56:10 -07:00
Ivan De Marino f869e8408d Sorting out the "web server" module.
Doesn't need a reference to the Config object (for now).
2012-07-13 09:55:52 -07:00
Ivan De Marino 0b04f0a672 Removing unnecessary casting from the "Env" class. 2012-07-13 09:55:45 -07:00
Ivan De Marino 008019ae10 Fixed an annoying FileSytem test that was wrongly designed (by me).
http://code.google.com/p/phantomjs/issues/detail?id=611
2012-07-13 09:52:35 -07:00
Ariya Hidayat 6ce27bbefa Version bump needs a unit test adjustment. 2012-07-13 09:38:57 -07:00
Ariya Hidayat 0632658afe Add a simple example to show how the module system works.
http://code.google.com/p/phantomjs/issues/detail?id=47
2012-07-13 07:58:05 -07:00
Juliusz Gonera 0ce2974ff7 Include the browser version of CoffeeScript too
This is still needed so that injectJs() methods work with CoffeeScript
and so that the main script file can be in CoffeeScript.

It causes duplication of code and some consideration is needed as to
how we could refactor the old inject code so that it uses modules
underneath. Lots of the module functionality written in JS could replace
the old C++ code (CSConverter, most functions in Utils).

http://code.google.com/p/phantomjs/issues/detail?id=47
2012-07-12 23:14:53 -07:00
Juliusz Gonera a02cf63984 Add support for CoffeeScript modules
Instead of using a C++ wrapper, I used a Node version of CoffeeScript
with a small JS wrapper (src/modules/_coffee-script.js). This way, since
the module system is similar enough to the Node.js module system, I only
need to require CoffeeScript in bootstrap.js and all the support for
.coffee is added by CoffeeScript itself.

To include a newer version of CoffeeScript in the source tree, see
tools/import-coffee-script.sh.

http://code.google.com/p/phantomjs/issues/detail?id=47
2012-07-12 23:14:13 -07:00
Juliusz Gonera 2555cb448c Refactor loading of native PhantomJS modules
Now PhantomJS modules are loaded just like any other modules, which
means they should be able to require other native modules inside them if
needed.

http://code.google.com/p/phantomjs/issues/detail?id=47
2012-07-12 23:14:13 -07:00
Juliusz Gonera 15204cb8ae Run modules in an empty context
Previously `this` in modules was set to the global `window` object. Now it
is set to an empty object instead.

http://code.google.com/p/phantomjs/issues/detail?id=47
2012-07-12 23:14:13 -07:00
Juliusz Gonera 5015dbec2a Remove old module tests
New module tests contain all the tests from the old ones.

http://code.google.com/p/phantomjs/issues/detail?id=47
2012-07-12 23:14:12 -07:00
Juliusz Gonera 893108ad11 Fix stack trace when module is not found
The stack trace was missing when an error was thrown because of a
missing module. This should not be the case anymore.

http://code.google.com/p/phantomjs/issues/detail?id=47
2012-07-12 23:14:12 -07:00
Juliusz Gonera ba3eabb29e Refactor nativeRequire() and restructure bootstrap.js
nativeRequire() has been refactored so that native modules are also
wrapped in Module objects. Additionally, native modules are also
cached and included in stack traces if an error occures inside them.

Phantom::loadModuleSource() has been renamed to
Phantom::readNativeModule() so that it's clear that it's used only to
load native modules.

Finally, all the require() code has been move after setting error
handlers in bootstrap.js so that if an error occurs in the require()
code, the stack trace is printed.

http://code.google.com/p/phantomjs/issues/detail?id=47
2012-07-12 23:14:12 -07:00
Juliusz Gonera b22e995337 Fix indentation to 4 spaces in new require() tests
http://code.google.com/p/phantomjs/issues/detail?id=47
2012-07-12 23:14:12 -07:00
Juliusz Gonera fdd727e5da Add Phantom::loadModule
Instead of trying to use sourceId to determine what module threw an
error, we now load module's source code using modified
QWebFrame::evaluateJavaScript and leverage PhantomJS's stack traces.

http://code.google.com/p/phantomjs/issues/detail?id=47
2012-07-12 23:14:12 -07:00
Juliusz Gonera 70925a873b Add test for .stack in errors thrown in modules
We want to be sure that the stack contains module file path.

http://code.google.com/p/phantomjs/issues/detail?id=47
2012-07-12 23:14:12 -07:00
Juliusz Gonera 2cfffa029a Merge phantomjs-nodify's require() and fix tests
Most of the tests passed after merging almost unchanged phantomjs-nodify
code, some needed small changes. The one that is still failing is for
CoffeeScript modules.

http://code.google.com/p/phantomjs/issues/detail?id=47
2012-07-12 23:14:12 -07:00
Juliusz Gonera 945a4c0f8c Add require() tests and comment buggy test in fs-spec-03.js
http://code.google.com/p/phantomjs/issues/detail?id=47
2012-07-12 23:14:12 -07:00
Jon Leighton 7892ff3b3e Deploy script improvements.
http://code.google.com/p/phantomjs/issues/detail?id=599

Squashed commit of the following:

commit 2cdcf8a47567f3c067958383843cccf858af531c
Author: Jon Leighton <j@jonathanleighton.com>
Date:   Sat Jul 7 19:37:38 2012 +0100

    Make lib-bundling/brandelf optional in deploy/package.sh

    This configuration has had some problems and we don't wish to use it in
    the official packages.

    Enable it with --bundle-libs.

commit 2a2155a4e1f5873aa8624859cead9d66750747f4
Author: Jon Leighton <j@jonathanleighton.com>
Date:   Sat Jul 7 19:24:40 2012 +0100

    notify user if upx is missing

commit 9656a99df0ff101150276dc88e0127f68041f617
Author: Jon Leighton <j@jonathanleighton.com>
Date:   Sat Jul 7 19:23:36 2012 +0100

    stripping symbols after upx probably doesn't work, reorder that

commit c5f425dc17069c89e7d2ff274309006c728ffab4
Author: Jon Leighton <j@jonathanleighton.com>
Date:   Sat Jul 7 19:17:07 2012 +0100

    fix logical fail
2012-07-08 17:42:58 -07:00
Jon Leighton 1bcacde12c Increase VM memory. Necessary for linking on 64-bit build.
http://code.google.com/p/phantomjs/issues/detail?id=599
2012-07-07 08:03:02 -07:00
Ariya Hidayat c0e8aa996f Merge branch 'master' of github.com:ariya/phantomjs 2012-07-07 08:00:30 -07:00
Ariya Hidayat 940e0089ba Merge pull request #291 from jonleighton/static_inspector
Fix remote inspector when building statically.
2012-07-07 08:00:07 -07:00
Jon Leighton 95186c653e Fix remote inspector when building statically.
For some reason, it seems that checking CONFIG(static) inside
src/phantomjs.pro is not reliable. That caused the STATIC_BUILD define
not to be set, and hence Q_INIT_RESOURCE would never get called in
main.cpp.

Instead of using Q_INIT_RESOURCE, let's just compile the resources
directly into the phantomjs binary. This means we don't need to detect
whether Qt is linked statically or dynamically.

https://code.google.com/p/phantomjs/issues/detail?id=430
2012-07-07 15:38:04 +01:00
Ariya Hidayat 13d929f3dc Merge branch 'master' of github.com:ariya/phantomjs 2012-07-05 09:21:04 -07:00
Ariya Hidayat 516c70b4fd Merge pull request #289 from detro/master
Version bump
2012-07-04 08:00:28 -07:00
Ivan De Marino 7409ec62d0 Bumping version to "1.7.0 (development)" 2012-07-03 22:50:11 +01:00
Ariya Hidayat df0f70f0b7 Merge pull request #284 from jonleighton/deploy2
Deploy fixes
2012-06-29 07:48:02 -07:00
Jon Leighton e05c887c96 Use zip for the OS X package
Requested by @ariya, who was concerned that .tar.bz2 might be confusing to
OS X users who are not well-versed in UNIX.
2012-06-29 14:54:39 +01:00
Jon Leighton 5f510967db Fix the top-level folder name in the packaged symbol tarball. 2012-06-29 14:44:10 +01:00
Jon Leighton a714bab04b Fix symbols generation on Linux
We are linking against e.g. libQtCore.so.4 rather than
libQtCore.so.4.8.2, and this affects symbol generation. (I am not sure
if this changed at some point, but this change should make it generate
the correct symbol files regardless.)

Also makes it less dependent on the Qt version.
2012-06-29 14:31:53 +01:00
Jon Leighton 13c1c164d9 Don't build the deploy in debug mode.
Debug mode turns off all optimisations. This make PhantomJS considerably
slower.

Instead, we build in 'release' mode, but generate debugging symbols at
the same time.

This may present some problems analysing crashes, if the optimisations
make that difficult. However, in my testing I was able to get useful
debug output even with optimisations enabled. So we should see how we go
- if it becomes a problem we can produce seperate debug binaries with no
optimisations.

https://code.google.com/p/phantomjs/issues/detail?id=599
2012-06-29 14:27:48 +01:00
Ariya Hidayat 59f6bb9496 ChangeLog fix: it's onPrompt and not onAlert.
Thanks to Ryuichi Okumura <okuryu@gmail.com> for the notice.

http://code.google.com/p/phantomjs/issues/detail?id=598
2012-06-26 08:20:00 -07:00
Ariya Hidayat ca7e8bb8f3 Merge pull request #281 from detro/master
Forgot to update completions for renderBase64
2012-06-25 01:47:40 -07:00
Ivan De Marino 5ad891c2f3 Forgot to update completions for renderBase64 2012-06-24 19:40:41 -07:00
Ariya Hidayat 3da512370e Lavender.
http://code.google.com/p/phantomjs/issues/detail?id=598
2012-06-20 23:28:26 -07:00
Ariya Hidayat 91d31ffe9e Fix Twitter-related examples to work with the new site.
http://code.google.com/p/phantomjs/issues/detail?id=609
2012-06-20 22:55:04 -07:00
13546 changed files with 93852 additions and 2937724 deletions

50
.gitignore vendored
View File

@ -2,7 +2,6 @@
*.pro.user*
*.xcodeproj
Makefile*
bin/phantomjs
*~
*.moc
moc_*
@ -11,15 +10,52 @@ qrc_*
*.swp
*.pyc
*.a
debian/*.debhelper
debian/files
debian/*.log
debian/*.substvars
debian/*/
/debian/*.debhelper
/debian/files
/debian/*.log
/debian/*.substvars
/debian/*/
/deploy/qt-*.tar.gz
/deploy/Qt-*
/symbols
/src/qt/qtc-debugging-helper
/src/phantomjs_plugin_import.cpp
# ignore ctags
/tags
tools/dump_syms.app/
/tools/dump_syms.app/
# Ignore Visual Studio temporary files, build results, etc
*.suo
*.user
*.sln.docstates
*_i.c
*_p.c
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.log
*.sdf
*.vcxproj
*.vcxproj.filters
*.lib
*.prl
*.intermediate.manifest
# Build results
[Dd]ebug*/
[Rr]elease/
bin/
*.class
build/
.gradle/

29
.travis.yml Normal file
View File

@ -0,0 +1,29 @@
language: cpp
compiler:
- gcc
cache: apt
before_install:
- sudo apt-get -yqq update #< Suggested by the Travis CI doc
- sudo apt-get -fyq install #< Fixes inconsistency of packages installed previously
install:
- sudo apt-get -yq install build-essential chrpath libssl-dev libfontconfig1-dev sqlite3 libsqlite3-dev ruby gperf bison flex libicu48 libicu-dev #< Build Dependencies
before_script:
- chmod +x ./build.sh
- chmod +x ./test/run-tests.sh
- chmod +x ./test/run-tests-ghostdriver.sh
script:
- ./build.sh --confirm --silent #< Build
- ./test/run-tests.sh #< Test (PhantomJS)
- ./test/run-tests-ghostdriver.sh #< Test (GhostDriver / PhantomJSDriver)
notifications:
irc:
channels:
- "irc.freenode.org#phantomjs"
on_success: always
on_failure: always
use_notice: true

88
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,88 @@
# Contribution Guide
This page describes how to contribute changes to PhantomJS.
Please do **not** create a pull request without reading this guide first. Failure to do so may result in the **rejection** of the pull request.
## For The Impatients
**Work on a feature branch**.
If your changes need to be modified due to some reviews, it is less clutter to tweak an isolated feature branch and push it again.
**Create a ticket in the issue tracker**.
This serves as a placeholder for important feedback, review, or any future updates.
In the commit message:
* **Keep the first line < 72 characters**. Write additional paragraphs
if necessary.
* **Put the link to the issue** (see above). This is important for cross-referencing purposes.
## Communicate
*Second opinion is always important.*
**Bug fixing**. If you have a fix for a bug, please attach your patch in the corresponding issue in the [issue tracker](https://github.com/ariya/phantomjs/issues). If there is no entry for the bug yet, then please create a new one. If you are confident working with Git, see the Get Ready section below on how to submit your change.
**Improvement and feature request**. If you have an improvement idea, please send an email to the [mailing list](http://groups.google.com/group/phantomjs) (rather than contacting the developers directly) so that other people can give their insights and opinions. This is also important to avoid duplicate work.
**Task management**. Once the feature idea is agreed upon and translated into concrete actions and tasks, please use the [issue tracker](https://github.com/ariya/phantomjs/issues) to create an issue for each individual task. Further technical discussion about the task and the implementation details should be carried out in the issue tracker.
**Extending with new API**. Whenever you want to introduce a new API, please send an email to the mailing list along with the link to the issue. Consider good API name for the object or function, read the [API Design Principle](http://developer.qt.nokia.com/wiki/API_Design_Principles) article. It may require few iterations to agree on the final API and hence it is important to engage all interested parties as early as possible.
## Get Ready
For your proposed change, you need to have:
* **an issue** (in the issue tracker) which describe your bug or feature
* **a feature branch** in your git fork
### Refer the Issue
The commit message needs to link to the issue. This cross-reference is [very important](http://ariya.ofilabs.com/2012/01/small-scale-software-craftsmanship.html) for the following reasons.
First, the commit log is frozen and can not be changed. If it contains a mistake or outdated information, the log can not be amended. However, further updates can be still posted to the linked issue, which can be followed from the commit log itself.
Second, it provides a placeholder for code review and other feedback.
An example of a bad commit log:
Fix Mountain Lion
The above log is too short and useless in the long run. A better version (and note the issue link):
Better support for OS X Mountain Lion.
require('system').os.version should give "10.8 (Mountain Lion)".
https://github.com/ariya/phantomjs/issues/10688
### Use Feature Branch
To isolate your change, please avoid working on the master branch. Instead, work on a *feature branch* (often also known as *topic branch*). You can create a new branch (example here crash-fix) off the master branch by using:
git checkout -b crash-fix master
Refer to your favorite Git tutorial/book for further detailed help.
Some good practices for the feature branch:
* Give it a meaningful name instead of, e.g. `prevent-zero-divide` instead of just `fix`
* Make *granular* and *atomic* commits, e.g. do not mix a typo fix with some major refactoring
* Keep one branch for one specific issue. If you need to work on other unrelated issues, create another branch.
## Review and Merge
When your branch is ready, send the pull request.
While it is not always the case, often it is necessary to improve parts of your code in the branch. This is the actual review process.
Here is a check list for the review:
* It does not break the test suite
* There is no typo
* The coding style follows the existing one
* There is a reasonable amount of comment
* The license header is intact
* All examples are still working

174
ChangeLog
View File

@ -1,12 +1,181 @@
Please see also http://code.google.com/p/phantomjs/wiki/ReleaseNotes.
Please see also http://phantomjs.org/releases.html.
2015-01-23: Version 2.0.0
New features
* Switched to Qt 5 and updated WebKit (issue 10448)
* Implemented clearing of memory cache (issue 10357)
* Added support for HTTP header change for every request (issue 11299)
Improvements
* Fixed rendering of CJK text by always linking the codecs (issue 10249)
* Ensured onResourceReceived is still fired on an error (issue 11163)
* Fixed possible crash in handling network requests (issue 11252)
* Removed hardcoded GhostDriver launching message (issue 12681)
* Allowed disk cache more than 2 GB (issue 12303)
Examples
* Netsniff example should exit when fails to load (issue 11333)
2014-01-25: Version 1.9.7
* Reverted to GhostDriver 1.1.0 instead of 1.1.1 (issue 11915)
* Fixed another warning of obsolete userSpaceScaleFactor on OS X 10.9 (issue 11612)
2014-01-20: Version 1.9.6
* Updated GhostDriver to version 1.1.1 (issue 11877, 11893)
2014-01-19: Version 1.9.3
* Fixed CoreText performance note on OS X 10.9 (issue 11418)
* Fixed warning of obsolete userSpaceScaleFactor on OS X 10.9 (issue 11612)
2013-09-06: Version 1.9.2
* Fixed graphical artifacts with transparent background on Windows (issue 11276, 11007, 11366)
* Updated GhostDriver to version 1.0.4 (issue 11452)
2013-06-04: Version 1.9.1
Critical bug fixes:
* Fixed problems with specifying proxy server (issue 10811, 11117)
* Fixed UTF-8 encoding with system.stdout and system.stderr (issue 11162)
* Ensured that onResourceReceived will be always invoked (issue 11163)
* Fixed module loading from an absolute path on Windows (issue 11165)
* Fixed typo in the command-line option for setting the cache size (11219)
* Fixed possible crash when handling network requests (issue 11252, 11338)
2013-03-20: Version 1.9.0 "Sakura"
New features
* Added spawn and execFile to execute external programs (issue 10219)
* Added the ability to abort network requests (issue 10230)
* Added system access to stdin, stdout, and stderr (issue 10333)
* Added support for custom CA certificates location (issue 10916)
* Added seek function to the File stream (issue 10937)
* Implemented file read for a specified number of bytes (issue 10938)
* Added a callback to handle network error (issue 10954, 10997)
* Added custom encoding support when opening a page (issue 11043)
* Implemented require.stub() support for a factory function (issue 11044)
* Added page loading indicator and progress (issue 11091)
* Added a timeout option for network requests (issue 11129)
Improvements
* Fixed the build on FreeBSD (issue 10597)
* Ensured a consistent 72 dpi for Linux headless rendering (issue 10659)
* Fixed possible PDF error due to invalid CreationDate field (issue 10663)
* Fixed crash when uploading non existing files (issue 10941)
* Improved the autocomplete internal of the interactive/REPL mode (issue 10943)
* Fixed possible crash when accessing inline frames (issue 10947)
* Changed Linux binary package setup to be built on CentOS 5 (issue 10963)
* Extended SSL ignore setting to synchronous XHR (issue 10985)
* Added convenient constants for modifier keys (issue 11056)
* Fixed incorrect date handling in the cookies (issue 11068)
* Updated GhostDriver to version 1.0.3 (issue 11146)
Examples
* Fixed invalid data URI in the netsniff example (issue 10740)
* Implemented a new weather example (issue 10794)
* Fixed rendering issues in render_multi_url (issue 11021)
* Fixed proper event sequence in page_events example (issue 11028)
* Miscellanous tweaks (issue 11082)
2013-03-02: Version 1.8.2
Critical bug fixes:
* Fixed possible PDF error due to invalid CreationDate field (issue 663)
* Fixed crash when uploading non existing files (issue 941)
* Fixed possible crash when accessing inline frames (issue 947)
* Extended SSL ignore setting to synchronous XHR (issue 985)
* Fixed incorrect date handling in the cookies (issue 1068)
2013-01-06: Version 1.8.1
Critical bug fix:
* Mac OS X: Fix possible crash when using some TrueType fonts (issue 690)
2012-12-21: Version 1.8.0 "Blue Winter Rose"
New features
* Integrated GhostDriver as the WebDriver implementation (issue 49)
* Added an option to specify the SSL protocol (issue 174)
* Added encoding support for WebServer's response (issue 505)
* Added process ID (PID) to the System module (issue 769)
* Added properties to obtain page and frame title (issue 799)
* Added page navigation methods (issue 808)
* Added support for modifier keys in keyboard events (issue 835)
* Added onFilePicker callback for more generic file upload API (issue 843)
* Added the ability to set the page content and location (issue 909)
Improvements
* Fixed date parsing in ISO8601 format (issue 187, 267)
* Fixed window.location (issue 530, 632)
* Deregistered multiple callback handler (issue 807)
* Fixed sending of double-click events (issue 848)
* Increases maximum number of redirects (issue 849)
* Fixed keycodes sent for lowercase characters (issue 852)
* Fixed a regression in table row page break (issue 880)
* Completed the CoffeeScript version of the examples (issue 907)
* Updated Qt to version 4.8.4 (issue 918)
* Fixed potential hang in some example scripts (issue 922)
2012-09-22: Version 1.7.0 "Blazing Star"
New features
* Added a module system modelled after CommonJS/Node.js (issue 47)
* Added support for window pop-up (issue 151)
* Static build on Linux (issue 413)
* Added run-time detection of SSL support (issue 484)
* Added more events support (issue 492, 712)
* Added support for disabling automatic proxy detection (issue 580)
* Provided page closing callback (issue 678)
* Added methods to access URL, frames URL, frame Content (issue 758)
* Added more cookies-related API (issue 761)
Improvements
* Refactored command-line options handling (issue 55)
* Improved the workflow for producing release builds (issue 599)
* Improved cookies API and implementation (issue 603, 761)
* Improved frame switching API (issue 654)
* Fixed iframe handling regression (issue 683)
* Fixed OS version number with Windows 8 and Mountain Lion (issue 684, 688)
* Fixed HAR navigation info in the netsniff example (issue 733)
* Fixed compile warnings with Visual Studio (issue 744)
* Removed hacks for static linking on Windows (issue 753)
* Added ICO image handling on Windows (issue 779)
* Fixed font antialiasing on Windows (issue 785)
* Improved Jasmine test runner for Jasmine 1.2 (issue 792)
2012-07-22: Version 1.6.1
Bug fixes
* Don't build the deploy in debug mode (issue 599)
* Fixed building on Windows (issue 424)
* Fixed remote inspector when building statically (issue 430)
2012-06-20: Version 1.6.0 "Lavender"
New features
* Added support for passing arguments to WebPage's evaluate (issue 132)
* Added callbacks for JavaScript onConfirm and onAlert (issue 133)
* Added callbacks for JavaScript onConfirm and onPrompt (issue 133)
* Added stack trace when error occurs (issue 166)
* Added support for local storage path and quota (issue 300)
* Added initial support for cookies handling (issue 354)
* Added support for header footer when printing the page (issue 410, 512)
* Added headers support in the loading request (issue 452)
@ -32,6 +201,7 @@ Please see also http://code.google.com/p/phantomjs/wiki/ReleaseNotes.
* Fixed example scripts to exit with the right exit code (issue 544)
* Fixed build failure with glib 2.31.0+ (issue 559)
* Fixed error handler failures in some cases (issue 589)
* Fixed Twitter-related examples to work with the new site (issue 609)
2012-03-20: Version 1.5.0 "Ghost Flower"

View File

@ -1,27 +1,24 @@
# [PhantomJS](http://phantomjs.org) - Scriptable Headless WebKit
PhantomJS ([www.phantomjs.org](http://phantomjs.org)) is a headless WebKit scriptable with JavaScript or CoffeeScript. It is used by hundreds of [developers](http://code.google.com/p/phantomjs/wiki/ExternalArticles) and dozens of [organizations](http://code.google.com/p/phantomjs/wiki/WhoUsesPhantomJS) for web-related development workflow.
PhantomJS ([www.phantomjs.org](http://phantomjs.org)) is a headless WebKit scriptable with JavaScript. It is used by hundreds of [developers](http://phantomjs.org/buzz.html) and dozens of [organizations](http://phantomjs.org/users.html) for web-related development workflow.
The latest [stable release](http://code.google.com/p/phantomjs/wiki/ReleaseNotes) is version 1.5 (codenamed "Ghost Flower"). Follow the official Twitter stream [@HeadlessPhantom](http://twitter.com/HeadlessPhantom) to get the frequent development updates.
The latest [stable release](http://phantomjs.org/release-2.0.html) is version 2.0.
PhantomJS is created and maintained by [Ariya Hidayat](http://ariya.ofilabs.com/about) (Twitter: [@ariyahidayat](http://twitter.com/ariyahidayat)), with the help of [many contributors](https://github.com/ariya/phantomjs/contributors).
**Note**: Please **do not** create a GitHub pull request **without** reading the [Contribution Guide](https://github.com/ariya/phantomjs/blob/master/CONTRIBUTING.md) first. Failure to do so may result in the rejection of the pull request.
## Use Cases
- **Headless web testing**. Lightning-fast testing without the browser is now possible! Various [test frameworks](http://code.google.com/p/phantomjs/wiki/TestFrameworkIntegration) such as Jasmine, Capybara, QUnit, WebDriver, YUI Test, BusterJS, FuncUnit, Robot Framework, and many others are supported.
- **Site scraping**. [Access and manipulate](http://code.google.com/p/phantomjs/wiki/QuickStart#DOM_Manipulation) webpages with the standard DOM API, or with usual libraries like jQuery.
- **Page rendering**. [Capture](http://code.google.com/p/phantomjs/wiki/QuickStart#Rendering) the full contents, even with SVG and Canvas, to an image. Build server-side web graphics apps, from a screenshot service to a vector chart rasterizer.
- **Network monitoring**. [Monitor](http://code.google.com/p/phantomjs/wiki/QuickStart#Network_traffic) network activity, track resource loading, perform load-balancing tests, verify contents optimization, and many others.
- **Headless web testing**. Lightning-fast testing without the browser is now possible! Various [test frameworks](http://phantomjs.org/headless-testing.html) such as Jasmine, Capybara, QUnit, Mocha, WebDriver, YUI Test, BusterJS, FuncUnit, Robot Framework, and many others are supported.
- **Page automation**. [Access and manipulate](http://phantomjs.org/page-automation.html) web pages with the standard DOM API, or with usual libraries like jQuery.
- **Screen capture**. Programmatically [capture web contents](http://phantomjs.org/screen-capture.html), including CSS, SVG and Canvas. Build server-side web graphics apps, from a screenshot service to a vector chart rasterizer.
- **Network monitoring**. Automate performance analysis, track [page loading](http://phantomjs.org/network-monitoring.html) and export as standard HAR format.
## Features
- **Multiplatform**, available on major operating systems: Windows, Mac OS X, Linux, other Unices.
- **Fast and native implementation** of web standards: DOM, CSS, JavaScript, Canvas, SVG. No emulation!
- **Pure headless (X11) on Linux**, ideal for continuous integration systems. Also runs on Amazon EC2.
- **Easy to install**: [Download](http://code.google.com/p/phantomjs/wiki/Installation), unpack, and start having fun in just 5 minutes.
- **Multiplatform**, available on major operating systems: Windows, Mac OS X, Linux, and other Unices.
- **Fast and native implementation** of web standards: DOM, CSS, JavaScript, Canvas, and SVG. No emulation!
- **Pure headless (no X11) on Linux**, ideal for continuous integration systems. Also runs on Amazon EC2, Heroku, and Iron.io.
- **Easy to install**: [Download](http://phantomjs.org/download.html), unpack, and start having fun in just 5 minutes.
## Ecosystem
@ -32,11 +29,18 @@ PhantomJS needs not be used only as a stand-alone tool. Check also some excellen
- [Guard::Jasmine](https://github.com/netzpirat/guard-jasmine) automatically tests Jasmine specs on Rails when files are modified.
- [GhostDriver](http://github.com/detro/ghostdriver/) complements Selenium tests with a PhantomJS WebDriver implementation.
- [PhantomRobot](https://github.com/datakurre/phantomrobot) runs Robot Framework acceptance tests in the background via PhantomJS.
- [Mocha-PhantomJS](https://github.com/metaskills/mocha-phantomjs) run Mocha tests using PhantomJS.
and many others [companion projects](http://code.google.com/p/phantomjs/wiki/WhoUsesPhantomJS).
and many others [related projects](http://phantomjs.org/related-projects.html).
## Questions?
- Explore the complete [documentation](http://code.google.com/p/phantomjs/wiki/PhantomJS?tm=6).
- Read tons of [user articles](http://code.google.com/p/phantomjs/wiki/ExternalArticles) on using PhantomJS.
- Explore the complete [documentation](http://phantomjs.org/documentation/).
- Read tons of [user articles](http://phantomjs.org/buzz.html) on using PhantomJS.
- Join the [mailing-list](http://groups.google.com/group/phantomjs) and discuss with other PhantomJS fans.
PhantomJS is free software/open source, and is distributed under the [BSD license](http://opensource.org/licenses/BSD-3-Clause). It contains third-party code, see the included `third-party.txt` file for the license information on third-party code.
PhantomJS is created and maintained by [Ariya Hidayat](http://ariya.ofilabs.com/about) (Twitter: [@ariyahidayat](http://twitter.com/ariyahidayat)), with the help of [many contributors](https://github.com/ariya/phantomjs/contributors). Follow the official Twitter stream [@PhantomJS](http://twitter.com/PhantomJS) to get the frequent development updates.

128
build.cmd Normal file
View File

@ -0,0 +1,128 @@
@echo off
SETLOCAL EnableExtensions EnableDelayedExpansion
set BUILD_TYPE=release
if /i "%1" == "debug" (
SET BUILD_TYPE=debug
)
set ROOT_DIR=%CD%
set 3RD_PARTY_LIBRARIES_REPO_URL=https://github.com/Vitallium/phantomjs-3rdparty-win
set 3RD_PARTY_LIBRARIES_REPO_BRANCH=msvc2013
if /i BUILD_TYPE == "debug" (
set 3RD_PARTY_LIBRARIES_REPO_BRANCH=msvc2013_debug
)
set BUILD_DATESTAMP=%date:~-4,4%%date:~-7,2%%date:~-10,2%
set BUILD_TIMESTAMP=%time:~-11,2%%time:~-8,2%
:: replace leading space with 0
set BUILD_TIMESTAMP=%BUILD_TIMESTAMP: =0%
set QT_LOG_FILE=!ROOT_DIR!\build_qt_!BUILD_DATESTAMP!-!BUILD_TIMESTAMP!.log
set WEBKIT_LOG_FILE=!ROOT_DIR!\build_webkit_!BUILD_DATESTAMP!_!BUILD_TIMESTAMP!.log
set PHANTOMJS_LOG_FILE=!ROOT_DIR!\build_phantomjs_!BUILD_DATESTAMP!_!BUILD_TIMESTAMP!.log
set MAKE_TOOL=nmake
echo:
echo Build type: !BUILD_TYPE!
call :build
ENDLOCAL
@exit /B 0
rem ========================================================================================================
:build
SETLOCAL EnableExtensions EnableDelayedExpansion
set _3RDPARTY=!ROOT_DIR!\src\qt\3rdparty
for %%X in (git.exe) do (set GIT_FOUND=%%~$PATH:X)
if defined GIT_FOUND (
echo.
echo GIT found. Getting 3rd party libraries.
if not exist !_3RDPARTY! call git clone -b !3RD_PARTY_LIBRARIES_REPO_BRANCH! !3RD_PARTY_LIBRARIES_REPO_URL! !_3RDPARTY!
) else (
ECHO.
CALL :exitB "Git is missing! Can't proceed. Please install Git."
GOTO :eof
)
:: prepare 3rdparty libraries
:: setup INCLUDE and LIB environment variables
:: OpenSSL
set OPENSSL_DIR=!_3RDPARTY!\openssl
set OPENSSL_LIB=!OPENSSL_DIR!\lib
set OPENSSL_INCLUDE=!OPENSSL_DIR!\include
:: ICU
set ICU_DIR=!_3RDPARTY!\libicu
set ICU_LIB=!ICU_DIR!\lib
set ICU_INCLUDE=!ICU_DIR!\include
:: libxml
set LIBXML_DIR=!_3RDPARTY!\libxml
set LIBXML_LIB=!LIBXML_DIR!\lib
set LIBXML_INCLUDE=!LIBXML_DIR!\include\libxml2
:: sqlite
set SQLITE3SRCDIR=!ROOT_DIR!\src\qt\qtbase\src\3rdparty\sqlite
set LIB=!OPENSSL_LIB!;!ICU_LIB!;!LIBXML_LIB!;%LIB%
set INCLUDE=!OPENSSL_INCLUDE!;!ICU_INCLUDE!;!LIBXML_INCLUDE!;%INCLUDE%
set PATH=!_3RDPARTY!\gnuwin32\bin;%PATH%
echo LIB: %LIB%
echo INCLUDE: %INCLUDE%
for %%X in (jom.exe) do (set JOMFOUND=%%~$PATH:X)
if defined JOMFOUND (
set MAKE_TOOL=jom
) else (
set MAKE_TOOL=nmake
)
pushd !ROOT_DIR!\src\qt
call preconfig.cmd !BUILD_TYPE! 2>&1 >> !QT_LOG_FILE!
popd
set PATH=!ROOT_DIR!\src\qt\qtbase\bin;%PATH%
for %%X in (qmake.exe) do (set QMAKE_FOUND=%%~$PATH:X)
if defined QMAKE_FOUND (
echo.
echo qmake found. Building QtWebkit
) else (
ECHO.
CALL :exitB "qmake.exe is missing! Can't proceed."
GOTO :eof
)
pushd !ROOT_DIR!\src\qt\qtwebkit
call qmake.exe
%MAKE_TOOL% %BUILD_TYPE% 2>&1 >> !WEBKIT_LOG_FILE!
popd
pushd !ROOT_DIR!\src
call qmake.exe
%MAKE_TOOL% %BUILD_TYPE% 2>&1 >> !PHANTOMJS_LOG_FILE!
popd
if EXIST !ROOT_DIR!\bin\phantomjs.exe (
echo.
echo Build has finished
echo.
) else (
echo:
echo Unable to find phantomjs.exe. Please, check log files:
echo Qt: !QT_LOG_FILE!
echo Webkit: !WEBKIT_LOG_FILE!
echo PhantomJS: !PHANTOMJS_LOG_FILE!
echo:
)
EXIT /b
rem ========================================================================================================
:: %1 an error message
:exitB
echo:
echo Error: %1
echo:
echo Contact vitaliy.slobodin@gmail.com
@exit /B 0

View File

@ -1,9 +1,7 @@
#!/bin/bash
#!/usr/bin/env bash
set -e
QT_CFG=''
COMPILE_JOBS=1
MAKEFLAGS_JOBS=''
@ -18,45 +16,67 @@ elif [[ $OSTYPE = darwin* ]]; then
# We only support modern Mac machines, they are at least using
# hyperthreaded dual-core CPU.
COMPILE_JOBS=4
elif [[ $OSTYPE == freebsd* ]]; then
COMPILE_JOBS=`sysctl -n hw.ncpu`
else
CPU_CORES=`grep -c ^processor /proc/cpuinfo`
if [[ "$CPU_CORES" -gt 1 ]]; then
COMPILE_JOBS=$CPU_CORES
if [[ "$COMPILE_JOBS" -gt 8 ]]; then
# Safety net.
COMPILE_JOBS=8
fi
fi
fi
until [ -z "$1" ]; do
if [[ "$COMPILE_JOBS" -gt 8 ]]; then
# Safety net.
COMPILE_JOBS=8
fi
SILENT=
until [[ -z "$1" ]]; do
case $1 in
"--qt-config")
shift
QT_CFG=" $1"
shift;;
"--qmake-args")
(--qmake-args)
shift
QMAKE_ARGS=$1
shift;;
"--jobs")
(--jobs)
shift
COMPILE_JOBS=$1
shift;;
(--silent)
SILENT=silent
shift;;
"--help")
echo "Usage: $0 [--qt-config CONFIG] [--jobs NUM]"
echo
echo " --qt-config CONFIG Specify extra config options to be used when configuring Qt"
echo " --jobs NUM How many parallel compile jobs to use. Defaults to 4."
echo
cat <<EOF
Usage: $0 [--jobs NUM]
--silent Produce less verbose output.
--jobs NUM How many parallel compile jobs to use.
Defaults to the number of CPU cores you have,
with a maximum of 8.
EOF
exit 0
;;
*)
echo "Unrecognised option: $1"
echo "Unrecognised option: $1" >&2
exit 1;;
esac
done
cd src/qt && ./preconfig.sh --jobs $COMPILE_JOBS --qt-config "$QT_CFG" && cd ../..
src/qt/bin/qmake $QMAKE_ARGS
UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
echo "System architecture... ($UNAME_SYSTEM $UNAME_RELEASE $UNAME_MACHINE)"
export QMAKE=qmake
# some Linux distros (e.g. Debian) allow you to parallel-install
# Qt4 and Qt5, using this environment variable to declare which
# one you want
export QT_SELECT=qt5
echo
echo "Building main PhantomJS application..."
echo
$QMAKE $QMAKE_ARGS
make -j$COMPILE_JOBS

5
debian/changelog vendored
View File

@ -1,5 +0,0 @@
phantomjs (1.3-1~git20110703) unstable; urgency=low
* Initial release.
-- Dennis Kaarsemaker <dennis@kaarsemaker.net> Sun, 03 Jul 2011 20:45:52 +0200

1
debian/compat vendored
View File

@ -1 +0,0 @@
7

24
debian/control vendored
View File

@ -1,24 +0,0 @@
Source: phantomjs
Section: python
Priority: extra
Maintainer: Dennis Kaarsemaker <dennis@kaarsemaker.net>
Build-Depends: debhelper (>= 7), libqt4-dev (>= 4.6), libqtwebkit-dev, qt4-qmake, python-support (>= 0.6.4), python-all-dev (>= 2.5), python-qt4-dev, python-qt4
Standards-Version: 3.8.4
XS-Python-Version: >= 2.6
Vcs-Git: http://github.com/ariya/phantomjs
Package: phantomjs
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: phantomjs - minimalistic headless WebKit-based JavaScript-driven tool
PhantomJS is a minimalistic, headless, WebKit-based, JavaScript-driven tool.
PhantomJs has native support for different web technologies: DOM handling,
CSS selector, JSON, Canvas, SVG, and of course JavaScript.
Package: python-pyphantomjs
Architecture: all
Depends: ${python:Depends}, ${shlibs:Depends}, ${misc:Depends}, python-qt4, python-argparse
Description: phantomjs - minimalistic headless WebKit-based JavaScript-driven tool
PhantomJS is a minimalistic, headless, WebKit-based, JavaScript-driven tool.
PhantomJs has native support for different web technologies: DOM handling,
CSS selector, JSON, Canvas, SVG, and of course JavaScript.

35
debian/copyright vendored
View File

@ -1,35 +0,0 @@
Format-Specification: http://anonscm.debian.org/viewvc/dep/web/deps/dep5.mdwn?revision=174&view=co&pathrev=174
Name: phantomjs
Maintainer: Dennis Kaarsemaker <dennis@kaarsemaker.net>
Source: http://github.com/ariya/phantomjs
Copyright: 2011 Ariya Hidayat <ariya.hidayat@gmail.com>
License: BSD-3-clause
Files: debian/*
Copyright: 2011 Dennis Kaarsemaker <dennis@kaarsemaker.net>
License: BSD-3-clause
License: BSD-3-clause
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 <organization> 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 <COPYRIGHT HOLDER> 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.

View File

@ -1,2 +0,0 @@
README.md
examples

View File

@ -1 +0,0 @@
debian/tmp/usr/bin/phantomjs

View File

@ -1 +0,0 @@
python/README.md

View File

@ -1,2 +0,0 @@
debian/tmp/usr/bin/pyphantomjs
debian/tmp/usr/lib

19
debian/rules vendored
View File

@ -1,19 +0,0 @@
#!/usr/bin/make -f
%:
dh $@
override_dh_auto_build:
qmake-qt4
$(MAKE)
cd python && python setup.py build
override_dh_auto_install:
$(MAKE) install
mkdir -p debian/tmp/usr/bin
cp bin/* debian/tmp/usr/bin
cd python && python setup.py install --root=../debian/tmp --install-layout=deb
override_dh_auto_clean:
if [ -f Makefile ]; then $(MAKE) distclean; fi
cd python && python setup.py clean

View File

@ -1 +0,0 @@
1.0

16
deploy/Vagrantfile vendored
View File

@ -9,11 +9,23 @@ end
Vagrant::Config.run do |config|
config.vm.define :i686 do |c|
c.vm.box_url = "https://opscode-vm.s3.amazonaws.com/vagrant/boxes/opscode-centos-5.8-i386.box"
c.vm.box = "centos_58_32bit"
c.vm.customize ["modifyvm", :id, "--ostype", "RedHat"]
end
config.vm.define :x86_64 do |c|
c.vm.box_url = "https://opscode-vm.s3.amazonaws.com/vagrant/boxes/opscode-centos-5.8.box"
c.vm.box = "centos_58_64bit"
c.vm.customize ["modifyvm", :id, "--ostype", "RedHat_64"]
end
config.vm.define :lucid32 do |c|
c.vm.box_url = "http://files.vagrantup.com/lucid32.box"
c.vm.box = "lucid32"
end
config.vm.define :x86_64 do |c|
config.vm.define :lucid64 do |c|
c.vm.box_url = "http://files.vagrantup.com/lucid64.box"
c.vm.box = "lucid64"
end
@ -25,6 +37,6 @@ Vagrant::Config.run do |config|
# You may wish to tweak these, but be aware that you need quite a lot of
# memory for the linking stage.
config.vm.customize ["modifyvm", :id, "--memory", 2048]
config.vm.customize ["modifyvm", :id, "--memory", 3072]
config.vm.customize ["modifyvm", :id, "--cpus", 2]
end

View File

@ -2,14 +2,16 @@
cd `dirname $0`/..
echo "Building Qt and PhantomJS in debug mode. If you have previously" \
"built in release mode, you should run:"
echo "Building Qt and PhantomJS with debugging symbols. If you have previously" \
"built without debugging symbols, you should run:"
echo
echo " $ make clean && cd src/qt && make clean && cd ../.."
echo " $ git clean -xdff"
echo
# Build the project
./build.sh --qt-config "-debug -webkit-debug" --qmake-args "CONFIG-=release CONFIG+=debug" || exit 1
# This incantation will cause Qt and WebKit and PhantomJS to all build in "release"
# mode, with compiler optimisations, but also with debug symbols. (We will strip the
# symbols in package.sh.)
CFLAGS=-g CXXFLAGS=-g ./build.sh --confirm --qt-config '-webkit-debug' --qmake-args "QMAKE_CFLAGS=-g QMAKE_CXXFLAGS=-g" || exit 1
# Package the release tarball
rm deploy/*.tar.bz2 2>/dev/null
@ -18,7 +20,7 @@ rm deploy/*.tar.bz2 2>/dev/null
# Build the dump_syms program for dumping breakpad debugging symbols
if [[ $OSTYPE = darwin* ]]; then
pushd tools
../src/qt/bin/qmake dump-syms-mac.pro
../src/qt/bin/qmake dump-syms-mac.pro && make
popd
else
pushd src/breakpad
@ -30,13 +32,22 @@ fi
./tools/dump-symbols.sh
version=$(bin/phantomjs --version | sed 's/ /-/' | sed 's/[()]//g')
if [[ $OSTYPE = darwin* ]]; then
symbols="phantomjs-$version-macosx-symbols"
else
symbols="phantomjs-$version-linux-$(uname -m)-symbols"
fi
cp -r symbols/ $symbols
# The minidump_stackwalk program is architecture-specific, so copy the
# binary for later use. This means that e.g. a developer on x86_64 can
# analyse a crash dump produced by a i686 user.
#
# We don't yet have a process for building minidump_stackwalk on OS X
if [[ $OSTYPE != darwin* ]]; then
cp src/breakpad/src/processor/minidump_stackwalk symbols/
cp src/breakpad/src/processor/minidump_stackwalk $symbols
read -r -d '' README <<EOT
These are symbols files that can be used to analyse a crash dump
@ -46,10 +57,11 @@ run:
./minidump_stackwalk /path/to/crash.dmp .
EOT
echo "$README" > symbols/README
echo "$README" > $symbols/README
fi
tar -cjf $(ls deploy/*.bz2 | sed 's/\.tar\.bz2/-symbols.tar.bz2/') symbols/
tar -cjf deploy/$symbols.tar.bz2 $symbols
rm -r $symbols
echo "PhantomJS built and packaged:"
echo

View File

@ -1,4 +1,4 @@
#!/bin/bash
#!/usr/bin/env bash
#
# usage: just run this script (after having run build.sh)
@ -18,14 +18,39 @@ if [[ ! -f ../bin/phantomjs ]]; then
exit 1
fi
if [[ "$1" = "--bundle-libs" ]]; then
bundle_libs=1
else
bundle_libs=0
fi
version=$(../bin/phantomjs --version | sed 's/ /-/' | sed 's/[()]//g')
src=..
echo "packaging phantomjs $version"
if [[ $OSTYPE = darwin* ]]; then
dest="phantomjs-$version-macosx-static"
dest="phantomjs-$version-macosx"
else
dest="phantomjs-$version-linux-$(uname -m)"
fi
rm -Rf $dest{.tar.bz2,} &> /dev/null
mkdir -p $dest/bin
echo
echo -n "copying files..."
cp $src/bin/phantomjs $dest/bin
cp -r $src/{ChangeLog,examples,LICENSE.BSD,third-party.txt,README.md} $dest/
echo "done"
echo
phantomjs=$dest/bin/phantomjs
if [[ "$bundle_libs" = "1" ]]; then
mkdir -p $dest/lib
if [[ ! -f brandelf ]]; then
echo
echo "brandelf executable not found in current dir"
@ -34,36 +59,15 @@ else
echo "done"
fi
dest="phantomjs-$version-linux-$(uname -m)-dynamic"
fi
libs=$(ldd $phantomjs | egrep -o "/[^ ]+ ")
rm -Rf $dest{.tar.bz2,} &> /dev/null
mkdir -p $dest/bin
if [[ $OSTYPE != darwin* ]]; then
mkdir -p $dest/lib
fi
echo
echo -n "copying files..."
cp $src/bin/phantomjs $dest/bin
cp -r $src/{ChangeLog,examples,LICENSE.BSD,README.md} $dest/
echo "done"
echo
if [[ $OSTYPE == darwin* ]]; then
echo -n "compressing binary..."
[ ! -z upx ] && upx -qqq -9 $dest/bin/phantomjs
echo "done"
echo
else
echo -n "copying shared libs..."
libld=
for l in $(ldd $dest/bin/phantomjs | egrep -o "/[^ ]+ "); do
if [[ "$l" != "" ]]; then
ll=$(basename $l)
cp $l $dest/lib/$ll
for l in $libs; do
ll=$(basename $l)
cp $l $dest/lib/$ll
if [[ "$bundle_libs" = "1" ]]; then
# ensure OS ABI compatibility
./brandelf -t SVR4 $dest/lib/$ll
if [[ "$l" == *"ld-linux"* ]]; then
@ -73,37 +77,44 @@ else
done
echo "done"
echo
fi
# strip to reduce file size
echo -n "stripping binary and libs..."
if [[ $OSTYPE = darwin* ]]; then
strip -x $dest/bin/*
else
strip -s $dest/lib/* $dest/bin/*
fi
echo "done"
echo
if [[ $OSTYPE != darwin* ]]; then
echo -n "writing run script..."
# write run scripts
mv $dest/bin/phantomjs $dest/bin/phantomjs.bin
mv $phantomjs $phantomjs.bin
phantomjs=$phantomjs.bin
run=$dest/bin/phantomjs
echo '#!/bin/sh' >> $run
echo 'path=$(dirname $(dirname $(readlink -f $0)))' >> $run
echo 'export LD_LIBRARY_PATH=$path/lib' >> $run
echo 'exec $path/lib/'$libld' $path/bin/phantomjs.bin $@' >> $run
echo 'exec $path/lib/'$libld' $phantomjs $@' >> $run
chmod +x $run
echo "done"
echo
fi
echo -n "creating tarball..."
tar -cjf $dest{.tar.bz2,}
echo -n "stripping binary and libs..."
if [[ $OSTYPE = darwin* ]]; then
strip -x $phantomjs
else
strip -s $phantomjs
[[ -d $dest/lib ]] && strip -s $dest/lib/*
fi
echo "done"
echo
echo "you can now deploy $dest or $dest.tar.bz2"
echo -n "compressing binary..."
if type upx >/dev/null 2>&1; then
upx -qqq -9 $phantomjs
echo "done"
else
echo "upx not found"
fi
echo
echo -n "creating archive..."
if [[ $OSTYPE = darwin* ]]; then
zip -r $dest.zip $dest
else
tar -cjf $dest{.tar.bz2,}
fi
echo "done"
echo

View File

@ -1,7 +1,29 @@
#!/usr/bin/env bash
apt-get update
apt-get install -y build-essential git-core libssl-dev libfontconfig1-dev gdb binutils-gold
export PATH=$HOME/git/bin:$PATH
if type apt-get >/dev/null 2>&1; then
apt-get update
apt-get install -y build-essential git-core libssl-dev libfontconfig1-dev gdb binutils-gold
fi
if type yum >/dev/null 2>&1; then
yum -y update
yum -y install gcc gcc-c++ make openssl-devel freetype-devel fontconfig-devel
if type git >/dev/null 2>&1; then
echo "Git is already available."
else
yum -y install cpio expat-devel gettext-devel zlib-devel
echo "Downloading and building git..."
rm -rf git-*
wget -nv https://git-core.googlecode.com/files/git-1.8.0.3.tar.gz
tar -xzvf git-1.8.0.3.tar.gz
cd git-1.8.0.3
./configure --prefix=$HOME/git && make -j2 && make install
cd ..
sleep 3
fi
fi
if [[ ! -d phantomjs ]]; then
git clone git://github.com/ariya/phantomjs.git

View File

@ -1,7 +0,0 @@
system = require 'system'
if system.args.length is 1
console.log 'Try to pass some args when invoking this script!'
else
for arg, i in system.args
console.log i + ': ' + arg
phantom.exit()

View File

@ -0,0 +1,27 @@
var spawn = require("child_process").spawn
var execFile = require("child_process").execFile
var child = spawn("ls", ["-lF", "/rooot"])
child.stdout.on("data", function (data) {
console.log("spawnSTDOUT:", JSON.stringify(data))
})
child.stderr.on("data", function (data) {
console.log("spawnSTDERR:", JSON.stringify(data))
})
child.on("exit", function (code) {
console.log("spawnEXIT:", code)
})
//child.kill("SIGKILL")
execFile("ls", ["-lF", "/usr"], null, function (err, stdout, stderr) {
console.log("execFileSTDOUT:", JSON.stringify(stdout))
console.log("execFileSTDERR:", JSON.stringify(stderr))
})
setTimeout(function () {
phantom.exit(0)
}, 2000)

View File

@ -1,46 +0,0 @@
page = require('webpage').create()
page.viewportSize = { width: 400, height : 400 }
page.content = '<html><body><canvas id="surface"></canvas></body></html>'
page.evaluate ->
el = document.getElementById 'surface'
context = el.getContext '2d'
width = window.innerWidth
height = window.innerHeight
cx = width / 2
cy = height / 2
radius = width / 2.3
i = 0
el.width = width
el.height = height
imageData = context.createImageData(width, height)
pixels = imageData.data
for y in [0...height]
for x in [0...width]
i = i + 4
rx = x - cx
ry = y - cy
d = rx * rx + ry * ry
if d < radius * radius
hue = 6 * (Math.atan2(ry, rx) + Math.PI) / (2 * Math.PI)
sat = Math.sqrt(d) / radius
g = Math.floor(hue)
f = hue - g
u = 255 * (1 - sat)
v = 255 * (1 - sat * f)
w = 255 * (1 - sat * (1 - f))
pixels[i] = [255, v, u, u, w, 255, 255][g]
pixels[i + 1] = [w, 255, 255, v, u, u, w][g]
pixels[i + 2] = [u, u, w, 255, 255, v, u][g]
pixels[i + 3] = 255
context.putImageData imageData, 0, 0
document.body.style.backgroundColor = 'white'
document.body.style.margin = '0px'
page.render('colorwheel.png')
phantom.exit()

View File

@ -1,8 +0,0 @@
t = 10
interval = setInterval ->
if t > 0
console.log t--
else
console.log 'BLAST OFF!'
phantom.exit()
, 1000

View File

@ -1,41 +0,0 @@
page = require('webpage').create()
system = require 'system'
page.onInitialized = ->
page.evaluate ->
userAgent = window.navigator.userAgent
platform = window.navigator.platform
window.navigator =
appCodeName: 'Mozilla'
appName: 'Netscape'
cookieEnabled: false
sniffed: false
window.navigator.__defineGetter__ 'userAgent', ->
window.navigator.sniffed = true
userAgent
window.navigator.__defineGetter__ 'platform', ->
window.navigator.sniffed = true
platform
if system.args.length is 1
console.log 'Usage: unsniff.coffee <some URL>'
phantom.exit 1
else
address = system.args[1]
console.log 'Checking ' + address + '...'
page.open address, (status) ->
if status isnt 'success'
console.log 'FAIL to load the address'
else
window.setTimeout ->
sniffed = page.evaluate(->
navigator.sniffed
)
if sniffed
console.log 'The page tried to sniff the user agent.'
else
console.log 'The page did not try to sniff the user agent.'
phantom.exit()
, 1500

View File

@ -33,7 +33,7 @@ page.onInitialized = function () {
};
if (system.args.length === 1) {
console.log('Usage: unsniff.js <some URL>');
console.log('Usage: detectsniff.js <some URL>');
phantom.exit(1);
} else {
address = system.args[1];
@ -41,6 +41,7 @@ if (system.args.length === 1) {
page.open(address, function (status) {
if (status !== 'success') {
console.log('FAIL to load the address');
phantom.exit();
} else {
window.setTimeout(function () {
sniffed = page.evaluate(function () {

View File

@ -1,30 +0,0 @@
# Get driving direction using Google Directions API.
page = require('webpage').create()
system = require 'system'
if system.args.length < 3
console.log 'Usage: direction.coffee origin destination'
console.log 'Example: direction.coffee "San Diego" "Palo Alto"'
phantom.exit 1
else
origin = system.args[1]
dest = system.args[2]
page.open encodeURI('http://maps.googleapis.com/maps/api/directions/xml?origin=' + origin +
'&destination=' + dest + '&units=imperial&mode=driving&sensor=false'),
(status) ->
if status isnt 'success'
console.log 'Unable to access network'
else
steps = page.content.match(/<html_instructions>(.*)<\/html_instructions>/ig)
if not steps
console.log 'No data available for ' + origin + ' to ' + dest
else
for ins in steps
ins = ins.replace(/\&lt;/ig, '<').replace(/\&gt;/ig, '>')
ins = ins.replace(/\<div/ig, '\n<div')
ins = ins.replace(/<.*?>/g, '')
console.log(ins)
console.log ''
console.log page.content.match(/<copyrights>.*<\/copyrights>/ig).join('').replace(/<.*?>/g, '')
phantom.exit()

View File

@ -1,20 +0,0 @@
# echoToFile.coffee - Write in a given file all the parameters passed on the CLI
fs = require 'fs'
system = require 'system'
if system.args.length < 3
console.log "Usage: echoToFile.coffee DESTINATION_FILE <arguments to echo...>"
phantom.exit 1
else
content = ""
f = null
i = 2
while i < system.args.length
content += system.args[i] + (if i == system.args.length - 1 then "" else " ")
++i
try
f = fs.open(system.args[1], "w")
f.writeLine content
catch e
console.log e
phantom.exit()

View File

@ -7,16 +7,15 @@ if (system.args.length < 3) {
phantom.exit(1);
} else {
var content = '',
f = null;
f = null,
i;
for ( i= 2; i < system.args.length; ++i ) {
content += system.args[i] + (i === system.args.length-1 ? '' : ' ');
}
try {
f = fs.open(system.args[1], "w");
f.writeLine(content);
f.close();
} catch (e) {
fs.write(system.args[1], content, 'w');
} catch(e) {
console.log(e);
}

View File

@ -1,8 +0,0 @@
fibs = [0, 1]
f = ->
console.log fibs[fibs.length - 1]
fibs.push fibs[fibs.length - 1] + fibs[fibs.length - 2]
if fibs.length > 10
window.clearInterval ticker
phantom.exit()
ticker = window.setInterval(f, 300)

View File

@ -1,29 +0,0 @@
# List following and followers from several accounts
users= [
'ariyahidayat'
'detronizator'
'KDABQt'
'lfranchi'
'jonleighton'
]
follow = (user, callback) ->
page = require('webpage').create()
page.open 'http://mobile.twitter.com/' + user, (status) ->
if status is 'fail'
console.log user + ': ?'
else
data = page.evaluate -> document.querySelector('div.timeline-following').innerText
console.log user + ': ' + data
callback.apply()
process = () ->
if (users.length > 0)
user = users[0]
users.splice(0, 1)
follow(user, process)
else
phantom.exit()
process()

View File

@ -1,10 +1,13 @@
// List following and followers from several accounts
var users = ['ariyahidayat',
var users = ['PhantomJS',
'ariyahidayat',
'detronizator',
'KDABQt',
'lfranchi',
'jonleighton'];
'jonleighton',
'_jamesmgreene',
'Vitalliumm'];
function follow(user, callback) {
var page = require('webpage').create();
@ -13,10 +16,11 @@ function follow(user, callback) {
console.log(user + ': ?');
} else {
var data = page.evaluate(function () {
return document.querySelector('div.timeline-following').innerText;
return document.querySelector('div.profile td.stat.stat-last div.statnum').innerText;
});
console.log(user + ': ' + data);
}
page.close();
callback.apply();
});
}

View File

@ -1,2 +0,0 @@
console.log 'Hello, world!'
phantom.exit()

View File

@ -1,20 +0,0 @@
# Upload an image to imagebin.org
page = require('webpage').create()
system = require 'system'
if system.args.length isnt 2
console.log 'Usage: imagebin.coffee filename'
phantom.exit 1
else
fname = system.args[1]
page.open 'http://imagebin.org/index.php?page=add', ->
page.uploadFile 'input[name=image]', fname
page.evaluate ->
document.querySelector('input[name=nickname]').value = 'phantom'
document.querySelector('input[name=disclaimer_agree]').click()
document.querySelector('form').submit()
window.setTimeout ->
phantom.exit()
, 3000

View File

@ -2,7 +2,7 @@
var page = require('webpage').create(),
system = require('system'),
fname;
fname;
if (system.args.length !== 2) {
console.log('Usage: imagebin.js filename');

View File

@ -1,23 +0,0 @@
# Use 'page.injectJs()' to load the script itself in the Page context
if phantom?
page = require('webpage').create()
# Route "console.log()" calls from within the Page context to the main
# Phantom context (i.e. current "this")
page.onConsoleMessage = (msg) -> console.log(msg)
page.onAlert = (msg) -> console.log(msg)
console.log "* Script running in the Phantom context."
console.log "* Script will 'inject' itself in a page..."
page.open "about:blank", (status) ->
if status is "success"
if page.injectJs("injectme.coffee")
console.log "... done injecting itself!"
else
console.log "... fail! Check the $PWD?!"
phantom.exit()
else
alert "* Script running in the Page context."

View File

@ -1,13 +0,0 @@
# Give the estimated location based on the IP address.
window.cb = (data) ->
loc = data.city
if data.region_name.length > 0
loc = loc + ', ' + data.region_name
console.log 'IP address: ' + data.ip
console.log 'Estimated location: ' + loc
phantom.exit()
el = document.createElement 'script'
el.src = 'http://freegeoip.net/json/?callback=window.cb'
document.body.appendChild el

View File

@ -1,18 +0,0 @@
page = require('webpage').create()
system = require 'system'
if system.args.length is 1
console.log 'Usage: loadspeed.coffee <some URL>'
phantom.exit 1
else
t = Date.now()
address = system.args[1]
page.open address, (status) ->
if status isnt 'success'
console.log('FAIL to load the address')
else
t = Date.now() - t
console.log('Page title is ' + page.evaluate( (-> document.title) ))
console.log('Loading time ' + t + ' msec')
phantom.exit()

View File

@ -0,0 +1,25 @@
var page = require('webpage').create(),
system = require('system');
if (system.args.length < 2) {
console.log('Usage: loadurlwithoutcss.js URL');
phantom.exit();
}
var address = system.args[1];
page.onResourceRequested = function(requestData, request) {
if ((/http:\/\/.+?\.css/gi).test(requestData['url']) || requestData.headers['Content-Type'] == 'text/css') {
console.log('The url of the request is matching. Aborting: ' + requestData['url']);
request.abort();
}
};
page.open(address, function(status) {
if (status === 'success') {
phantom.exit();
} else {
console.log('Unable to load the address!');
phantom.exit();
}
});

File diff suppressed because it is too large Load Diff

4
examples/module.js Normal file
View File

@ -0,0 +1,4 @@
var universe = require('./universe');
universe.start();
console.log('The answer is' + universe.answer);
phantom.exit();

View File

@ -1,13 +0,0 @@
# List movies from kids-in-mind.com
window.cbfunc = (data) ->
globaldata = data
list = data.query.results.movie
for item in list
console.log item.title + ' [' + item.rating.MPAA.content + ']'
phantom.exit()
el = document.createElement 'script'
el.src =
"http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20movies.kids-in-mind&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&callback=window.cbfunc"
document.body.appendChild el

View File

@ -1,18 +0,0 @@
page = require('webpage').create()
system = require 'system'
if system.args.length is 1
console.log 'Usage: netlog.coffee <some URL>'
phantom.exit 1
else
address = system.args[1]
page.onResourceRequested = (req) ->
console.log 'requested ' + JSON.stringify(req, undefined, 4)
page.onResourceReceived = (res) ->
console.log 'received ' + JSON.stringify(res, undefined, 4)
page.open address, (status) ->
if status isnt 'success'
console.log 'FAIL to load the address'
phantom.exit()

View File

@ -1,110 +0,0 @@
if not Date::toISOString
Date::toISOString = ->
pad = (n) ->
if n < 10 then '0' + n else n
ms = (n) ->
if n < 10 then '00' + n else (if n < 100 then '0' + n else n)
@getFullYear() + '-' +
pad(@getMonth() + 1) + '-' +
pad(@getDate()) + 'T' +
pad(@getHours()) + ':' +
pad(@getMinutes()) + ':' +
pad(@getSeconds()) + '.' +
ms(@getMilliseconds()) + 'Z'
createHAR = (address, title, startTime, resources) ->
entries = []
resources.forEach (resource) ->
request = resource.request
startReply = resource.startReply
endReply = resource.endReply
if not request or not startReply or not endReply
return
entries.push
startedDateTime: request.time.toISOString()
time: endReply.time - request.time
request:
method: request.method
url: request.url
httpVersion: 'HTTP/1.1'
cookies: []
headers: request.headers
queryString: []
headersSize: -1
bodySize: -1
response:
status: endReply.status
statusText: endReply.statusText
httpVersion: 'HTTP/1.1'
cookies: []
headers: endReply.headers
redirectURL: ''
headersSize: -1
bodySize: startReply.bodySize
content:
size: startReply.bodySize
mimeType: endReply.contentType
cache: {}
timings:
blocked: 0
dns: -1
connect: -1
send: 0
wait: startReply.time - request.time
receive: endReply.time - startReply.time
ssl: -1
log:
version: '1.2'
creator:
name: 'PhantomJS'
version: phantom.version.major + '.' + phantom.version.minor + '.' + phantom.version.patch
pages: [
startedDateTime: startTime.toISOString()
id: address
title: title
pageTimings: {}
]
entries: entries
page = require('webpage').create()
system = require 'system'
if system.args.length is 1
console.log 'Usage: netsniff.coffee <some URL>'
phantom.exit 1
else
page.address = system.args[1]
page.resources = []
page.onLoadStarted = ->
page.startTime = new Date()
page.onResourceRequested = (req) ->
page.resources[req.id] =
request: req
startReply: null
endReply: null
page.onResourceReceived = (res) ->
if res.stage is 'start'
page.resources[res.id].startReply = res
if res.stage is 'end'
page.resources[res.id].endReply = res
page.open page.address, (status) ->
if status isnt 'success'
console.log 'FAIL to load the address'
else
page.title = page.evaluate ->
document.title
har = createHAR page.address, page.title, page.startTime, page.resources
console.log JSON.stringify har, undefined, 4
phantom.exit()

View File

@ -25,6 +25,12 @@ function createHAR(address, title, startTime, resources)
return;
}
// Exclude Data URI from HAR file because
// they aren't included in specification
if (request.url.match(/(^data:image\/.*)/i)) {
return;
}
entries.push({
startedDateTime: request.time.toISOString(),
time: endReply.time - request.time,
@ -61,7 +67,8 @@ function createHAR(address, title, startTime, resources)
wait: startReply.time - request.time,
receive: endReply.time - startReply.time,
ssl: -1
}
},
pageref: address
});
});
@ -77,7 +84,9 @@ function createHAR(address, title, startTime, resources)
startedDateTime: startTime.toISOString(),
id: address,
title: title,
pageTimings: {}
pageTimings: {
onLoad: page.endTime - page.startTime
}
}],
entries: entries
}
@ -88,7 +97,7 @@ var page = require('webpage').create(),
system = require('system');
if (system.args.length === 1) {
console.log('Usage: netsniff.coffee <some URL>');
console.log('Usage: netsniff.js <some URL>');
phantom.exit(1);
} else {
@ -120,13 +129,15 @@ if (system.args.length === 1) {
var har;
if (status !== 'success') {
console.log('FAIL to load the address');
phantom.exit(1);
} else {
page.endTime = new Date();
page.title = page.evaluate(function () {
return document.title;
});
har = createHAR(page.address, page.title, page.startTime, page.resources);
console.log(JSON.stringify(har, undefined, 4));
phantom.exit();
}
phantom.exit();
});
}

View File

@ -0,0 +1,24 @@
var page = require('webpage').create(),
system = require('system'),
host, port, address;
if (system.args.length < 4) {
console.log('Usage: openurlwithproxy.js <proxyHost> <proxyPort> <URL>');
phantom.exit(1);
} else {
host = system.args[1];
port = system.args[2];
address = system.args[3];
phantom.setProxy(host, port, 'manual', '', '');
page.open(address, function (status) {
if (status !== 'success') {
console.log('FAIL to load the address "' +
address + '" using proxy "' + host + ':' + port + '"');
} else {
console.log('Page title is ' + page.evaluate(function () {
return document.title;
}));
}
phantom.exit();
});
}

View File

@ -1,12 +0,0 @@
helloWorld = () -> console.log phantom.outputEncoding + ": こんにちは、世界!"
console.log "Using default encoding..."
helloWorld()
console.log "\nUsing other encodings..."
for enc in ["euc-jp", "sjis", "utf8", "System"]
do (enc) ->
phantom.outputEncoding = enc
helloWorld()
phantom.exit()

146
examples/page_events.js Normal file
View File

@ -0,0 +1,146 @@
// The purpose of this is to show how and when events fire, considering 5 steps
// happening as follows:
//
// 1. Load URL
// 2. Load same URL, but adding an internal FRAGMENT to it
// 3. Click on an internal Link, that points to another internal FRAGMENT
// 4. Click on an external Link, that will send the page somewhere else
// 5. Close page
//
// Take particular care when going through the output, to understand when
// things happen (and in which order). Particularly, notice what DOESN'T
// happen during step 3.
//
// If invoked with "-v" it will print out the Page Resources as they are
// Requested and Received.
//
// NOTE.1: The "onConsoleMessage/onAlert/onPrompt/onConfirm" events are
// registered but not used here. This is left for you to have fun with.
// NOTE.2: This script is not here to teach you ANY JavaScript. It's aweful!
// NOTE.3: Main audience for this are people new to PhantomJS.
var sys = require("system"),
page = require("webpage").create(),
logResources = false,
step1url = "http://en.wikipedia.org/wiki/DOM_events",
step2url = "http://en.wikipedia.org/wiki/DOM_events#Event_flow";
if (sys.args.length > 1 && sys.args[1] === "-v") {
logResources = true;
}
function printArgs() {
var i, ilen;
for (i = 0, ilen = arguments.length; i < ilen; ++i) {
console.log(" arguments[" + i + "] = " + JSON.stringify(arguments[i]));
}
console.log("");
}
////////////////////////////////////////////////////////////////////////////////
page.onInitialized = function() {
console.log("page.onInitialized");
printArgs.apply(this, arguments);
};
page.onLoadStarted = function() {
console.log("page.onLoadStarted");
printArgs.apply(this, arguments);
};
page.onLoadFinished = function() {
console.log("page.onLoadFinished");
printArgs.apply(this, arguments);
};
page.onUrlChanged = function() {
console.log("page.onUrlChanged");
printArgs.apply(this, arguments);
};
page.onNavigationRequested = function() {
console.log("page.onNavigationRequested");
printArgs.apply(this, arguments);
};
page.onRepaintRequested = function() {
console.log("page.onRepaintRequested");
printArgs.apply(this, arguments);
};
if (logResources === true) {
page.onResourceRequested = function() {
console.log("page.onResourceRequested");
printArgs.apply(this, arguments);
};
page.onResourceReceived = function() {
console.log("page.onResourceReceived");
printArgs.apply(this, arguments);
};
}
page.onClosing = function() {
console.log("page.onClosing");
printArgs.apply(this, arguments);
};
// window.console.log(msg);
page.onConsoleMessage = function() {
console.log("page.onConsoleMessage");
printArgs.apply(this, arguments);
};
// window.alert(msg);
page.onAlert = function() {
console.log("page.onAlert");
printArgs.apply(this, arguments);
};
// var confirmed = window.confirm(msg);
page.onConfirm = function() {
console.log("page.onConfirm");
printArgs.apply(this, arguments);
};
// var user_value = window.prompt(msg, default_value);
page.onPrompt = function() {
console.log("page.onPrompt");
printArgs.apply(this, arguments);
};
////////////////////////////////////////////////////////////////////////////////
setTimeout(function() {
console.log("");
console.log("### STEP 1: Load '" + step1url + "'");
page.open(step1url);
}, 0);
setTimeout(function() {
console.log("");
console.log("### STEP 2: Load '" + step2url + "' (load same URL plus FRAGMENT)");
page.open(step2url);
}, 5000);
setTimeout(function() {
console.log("");
console.log("### STEP 3: Click on page internal link (aka FRAGMENT)");
page.evaluate(function() {
var ev = document.createEvent("MouseEvents");
ev.initEvent("click", true, true);
document.querySelector("a[href='#Event_object']").dispatchEvent(ev);
});
}, 10000);
setTimeout(function() {
console.log("");
console.log("### STEP 4: Click on page external link");
page.evaluate(function() {
var ev = document.createEvent("MouseEvents");
ev.initEvent("click", true, true);
document.querySelector("a[title='JavaScript']").dispatchEvent(ev);
});
}, 15000);
setTimeout(function() {
console.log("");
console.log("### STEP 5: Close page and shutdown (with a delay)");
page.close();
setTimeout(function(){
phantom.exit();
}, 100);
}, 20000);

View File

@ -1,13 +0,0 @@
p = require("webpage").create()
p.onConsoleMessage = (msg) ->
console.log msg
p.onCallback = (msg) ->
console.log "Received by the 'phantom' main context: " + msg
"Hello there, I'm coming to you from the 'phantom' context instead"
p.evaluate ->
callbackResponse = phantomCallback("Hello, I'm coming to you from the 'page' context")
console.log "Received by the 'page' context: " + callbackResponse
phantom.exit()

View File

@ -2,7 +2,7 @@ var p = require("webpage").create();
p.onConsoleMessage = function(msg) { console.log(msg); };
// Calls to "phantomCallback" within the page 'p' arrive here
// Calls to "callPhantom" within the page 'p' arrive here
p.onCallback = function(msg) {
console.log("Received by the 'phantom' main context: "+msg);
return "Hello there, I'm coming to you from the 'phantom' context instead";
@ -10,7 +10,7 @@ p.onCallback = function(msg) {
p.evaluate(function() {
// Return-value of the "onCallback" handler arrive here
var callbackResponse = callPhantom("Hello, I'm coming to you from the 'page' context");
var callbackResponse = window.callPhantom("Hello, I'm coming to you from the 'page' context");
console.log("Received by the 'page' context: "+callbackResponse);
});

View File

@ -1,13 +0,0 @@
# Read the Phantom webpage '#intro' element text using jQuery and "includeJs"
page = require('webpage').create()
page.onConsoleMessage = (msg) -> console.log msg
page.open "http://www.phantomjs.org", (status) ->
if status is "success"
page.includeJs "http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js", ->
page.evaluate ->
console.log "$(\"#intro\").text() -> " + $("#intro").text()
phantom.exit()

View File

@ -10,7 +10,7 @@ page.open("http://www.phantomjs.org", function(status) {
if ( status === "success" ) {
page.includeJs("http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js", function() {
page.evaluate(function() {
console.log("$(\"#intro\").text() -> " + $("#intro").text());
console.log("$(\".explanation\").text() -> " + $(".explanation").text());
});
phantom.exit();
});

View File

@ -1,18 +0,0 @@
# Find pizza in Mountain View using Yelp
page = require('webpage').create()
url = 'http://lite.yelp.com/search?find_desc=pizza&find_loc=94040&find_submit=Search'
page.open url,
(status) ->
if status isnt 'success'
console.log 'Unable to access network'
else
results = page.evaluate ->
pizza = []
list = document.querySelectorAll 'span.address'
for item in list
pizza.push(item.innerText)
return pizza
console.log results.join('\n')
phantom.exit()

View File

@ -8,7 +8,7 @@ page.open(url, function (status) {
console.log('Unable to access network');
} else {
var results = page.evaluate(function() {
var list = document.querySelectorAll('span.address'), pizza = [], i;
var list = document.querySelectorAll('address'), pizza = [], i;
for (i = 0; i < list.length; i++) {
pizza.push(list[i].innerText);
}

View File

@ -1,12 +0,0 @@
# Example using HTTP POST operation
page = require('webpage').create()
server = 'http://posttestserver.com/post.php?dump'
data = 'universe=expanding&answer=42'
page.open server, 'post', data, (status) ->
if status isnt 'success'
console.log 'Unable to post!'
else
console.log page.content
phantom.exit()

18
examples/postjson.js Normal file
View File

@ -0,0 +1,18 @@
// Example using HTTP POST operation
var page = require('webpage').create(),
server = 'http://posttestserver.com/post.php?dump',
data = '{"universe": "expanding", "answer": 42}';
var headers = {
"Content-Type": "application/json"
}
page.open(server, 'post', data, headers, function (status) {
if (status !== 'success') {
console.log('Unable to post!');
} else {
console.log(page.content);
}
phantom.exit();
});

View File

@ -2,7 +2,7 @@ var page = require('webpage').create(),
system = require('system');
function someCallback(pageNum, numPages) {
return "<h1> somCallback: " + pageNum + " / " + numPages + "</h1>";
return "<h1> someCallback: " + pageNum + " / " + numPages + "</h1>";
}
if (system.args.length < 3) {

View File

@ -1,23 +0,0 @@
page = require('webpage').create()
system = require 'system'
if system.args.length < 3 or system.args.length > 4
console.log 'Usage: rasterize.coffee URL filename [paperwidth*paperheight|paperformat]'
console.log ' paper (pdf output) examples: "5in*7.5in", "10cm*20cm", "A4", "Letter"'
phantom.exit 1
else
address = system.args[1]
output = system.args[2]
page.viewportSize = { width: 600, height: 600 }
if system.args.length is 4 and system.args[2].substr(-4) is ".pdf"
size = system.args[3].split '*'
if size.length is 2
page.paperSize = { width: size[0], height: size[1], border: '0px' }
else
page.paperSize = { format: system.args[3], orientation: 'portrait', border: '1cm' }
page.open address, (status) ->
if status isnt 'success'
console.log 'Unable to load the address!'
phantom.exit()
else
window.setTimeout (-> page.render output; phantom.exit()), 200

View File

@ -5,6 +5,8 @@ var page = require('webpage').create(),
if (system.args.length < 3 || system.args.length > 5) {
console.log('Usage: rasterize.js URL filename [paperwidth*paperheight|paperformat] [zoom]');
console.log(' paper (pdf output) examples: "5in*7.5in", "10cm*20cm", "A4", "Letter"');
console.log(' image (png/jpg output) examples: "1920px" entire page, window width 1920px');
console.log(' "800px*600px" window, clipped to 800x600');
phantom.exit(1);
} else {
address = system.args[1];
@ -14,6 +16,20 @@ if (system.args.length < 3 || system.args.length > 5) {
size = system.args[3].split('*');
page.paperSize = size.length === 2 ? { width: size[0], height: size[1], margin: '0px' }
: { format: system.args[3], orientation: 'portrait', margin: '1cm' };
} else if (system.args.length > 3 && system.args[3].substr(-2) === "px") {
size = system.args[3].split('*');
if (size.length === 2) {
pageWidth = parseInt(size[0], 10);
pageHeight = parseInt(size[1], 10);
page.viewportSize = { width: pageWidth, height: pageHeight };
page.clipRect = { top: 0, left: 0, width: pageWidth, height: pageHeight };
} else {
console.log("size:", system.args[3]);
pageWidth = parseInt(system.args[3], 10);
pageHeight = parseInt(pageWidth * 3/4, 10); // it's as good an assumption as any
console.log ("pageHeight:",pageHeight);
page.viewportSize = { width: pageWidth, height: pageHeight };
}
}
if (system.args.length > 4) {
page.zoomFactor = system.args[4];
@ -21,6 +37,7 @@ if (system.args.length < 3 || system.args.length > 5) {
page.open(address, function (status) {
if (status !== 'success') {
console.log('Unable to load the address!');
phantom.exit(1);
} else {
window.setTimeout(function () {
page.render(output);

View File

@ -1,50 +0,0 @@
# Render Multiple URLs to file
# FIXME: For now it is fine with pure domain names: don't think it would work with paths and stuff like that
system = require 'system'
# Extend the Array Prototype with a 'foreach'
Array.prototype.forEach = (action) ->
for i, j in this
action j, i, _len
# Render a given url to a given file
# @param url URL to render
# @param file File to render to
# @param callback Callback function
renderUrlToFile = (url, file, callback) ->
page = require('webpage').create()
page.viewportSize = { width: 800, height : 600 }
page.settings.userAgent = 'Phantom.js bot'
page.open url, (status) ->
if status isnt 'success'
console.log "Unable to render '#{url}'"
else
page.render file
delete page
callback url, file
# Read the passed args
if system.args.length > 1
arrayOfUrls = Array.prototype.slice.call system.args, 1
else
# Default (no args passed)
console.log 'Usage: phantomjs render_multi_url.coffee [domain.name1, domain.name2, ...]'
arrayOfUrls = [
'www.google.com',
'www.bbc.co.uk',
'www.phantomjs.org'
]
# For each URL
arrayOfUrls.forEach (pos, url, total) ->
file_name = "./#{url}.png"
# Render to a file
renderUrlToFile "http://#{url}", file_name, (url, file) ->
console.log "Rendered '#{url}' at '#{file}'"
if pos is total - 1
# Close Phantom if it's the last URL
phantom.exit()

View File

@ -1,62 +1,73 @@
// Render Multiple URLs to file
// FIXME: For now it is fine with pure domain names: don't think it would work with paths and stuff like that
var system = require('system');
var RenderUrlsToFile, arrayOfUrls, system;
// Extend the Array Prototype with a 'foreach'
Array.prototype.forEach = function (action) {
var i, len;
for ( i = 0, len = this.length; i < len; ++i ) {
action(i, this[i], len);
}
system = require("system");
/*
Render given urls
@param array of URLs to render
@param callbackPerUrl Function called after finishing each URL, including the last URL
@param callbackFinal Function called after finishing everything
*/
RenderUrlsToFile = function(urls, callbackPerUrl, callbackFinal) {
var getFilename, next, page, retrieve, urlIndex, webpage;
urlIndex = 0;
webpage = require("webpage");
page = null;
getFilename = function() {
return "rendermulti-" + urlIndex + ".png";
};
next = function(status, url, file) {
page.close();
callbackPerUrl(status, url, file);
return retrieve();
};
retrieve = function() {
var url;
if (urls.length > 0) {
url = urls.shift();
urlIndex++;
page = webpage.create();
page.viewportSize = {
width: 800,
height: 600
};
page.settings.userAgent = "Phantom.js bot";
return page.open("http://" + url, function(status) {
var file;
file = getFilename();
if (status === "success") {
return window.setTimeout((function() {
page.render(file);
return next(status, url, file);
}), 200);
} else {
return next(status, url, file);
}
});
} else {
return callbackFinal();
}
};
return retrieve();
};
/**
* Render a given url to a given file
* @param url URL to render
* @param file File to render to
* @param callback Callback function
*/
function renderUrlToFile(url, file, callback) {
var page = require('webpage').create();
page.viewportSize = { width: 800, height : 600 };
page.settings.userAgent = "Phantom.js bot";
arrayOfUrls = null;
page.open(url, function(status){
if ( status !== "success") {
console.log("Unable to render '"+url+"'");
} else {
page.render(file);
}
delete page;
callback(url, file);
});
}
// Read the passed args
var arrayOfUrls;
if ( system.args.length > 1 ) {
if (system.args.length > 1) {
arrayOfUrls = Array.prototype.slice.call(system.args, 1);
} else {
// Default (no args passed)
console.log("Usage: phantomjs render_multi_url.js [domain.name1, domain.name2, ...]");
arrayOfUrls = [
'www.google.com',
'www.bbc.co.uk',
'www.phantomjs.org'
];
arrayOfUrls = ["www.google.com", "www.bbc.co.uk", "www.phantomjs.org"];
}
// For each URL
arrayOfUrls.forEach(function(pos, url, total){
var file_name = "./" + url + ".png";
// Render to a file
renderUrlToFile("http://"+url, file_name, function(url, file){
console.log("Rendered '"+url+"' at '"+file+"'");
if ( pos === total-1 ) {
// Close Phantom if it's the last URL
phantom.exit();
}
});
RenderUrlsToFile(arrayOfUrls, (function(status, url, file) {
if (status !== "success") {
return console.log("Unable to render '" + url + "'");
} else {
return console.log("Rendered '" + url + "' at '" + file + "'");
}
}), function() {
return phantom.exit();
});

View File

@ -1,61 +0,0 @@
system = require 'system'
##
# Wait until the test condition is true or a timeout occurs. Useful for waiting
# on a server response or for a ui change (fadeIn, etc.) to occur.
#
# @param testFx javascript condition that evaluates to a boolean,
# it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
# as a callback function.
# @param onReady what to do when testFx condition is fulfilled,
# it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
# as a callback function.
# @param timeOutMillis the max amount of time to wait. If not specified, 3 sec is used.
##
waitFor = (testFx, onReady, timeOutMillis=3000) ->
start = new Date().getTime()
condition = false
f = ->
if (new Date().getTime() - start < timeOutMillis) and not condition
# If not time-out yet and condition not yet fulfilled
condition = (if typeof testFx is 'string' then eval testFx else testFx()) #< defensive code
else
if not condition
# If condition still not fulfilled (timeout but condition is 'false')
console.log "'waitFor()' timeout"
phantom.exit 1
else
# Condition fulfilled (timeout and/or condition is 'true')
console.log "'waitFor()' finished in #{new Date().getTime() - start}ms."
if typeof onReady is 'string' then eval onReady else onReady() #< Do what it's supposed to do once the condition is fulfilled
clearInterval interval #< Stop this interval
interval = setInterval f, 100 #< repeat check every 100ms
if system.args.length isnt 2
console.log 'Usage: run-jasmine.coffee URL'
phantom.exit 1
page = require('webpage').create()
# Route "console.log()" calls from within the Page context to the main Phantom context (i.e. current "this")
page.onConsoleMessage = (msg) ->
console.log msg
page.open system.args[1], (status) ->
if status isnt 'success'
console.log 'Unable to access network'
phantom.exit()
else
waitFor ->
page.evaluate ->
if document.body.querySelector '.finished-at'
return true
return false
, ->
page.evaluate ->
console.log document.body.querySelector('.description').innerText
list = document.body.querySelectorAll('.failed > .description, .failed > .messages > .resultMessage')
for el in list
console.log el.innerText
phantom.exit()

View File

@ -50,30 +50,42 @@ page.onConsoleMessage = function(msg) {
page.open(system.args[1], function(status){
if (status !== "success") {
console.log("Unable to access network");
phantom.exit();
console.log("Unable to open " + system.args[1]);
phantom.exit(1);
} else {
waitFor(function(){
return page.evaluate(function(){
if (document.body.querySelector('.runner .description')) {
return true;
}
return false;
return document.body.querySelector('.symbolSummary .pending') === null
});
}, function(){
page.evaluate(function(){
console.log(document.body.querySelector('.description').innerText);
list = document.body.querySelectorAll('div.jasmine_reporter > div.suite.failed');
for (i = 0; i < list.length; ++i) {
el = list[i];
desc = el.querySelectorAll('.description');
var exitCode = page.evaluate(function(){
try {
console.log('');
for (j = 0; j < desc.length; ++j) {
console.log(desc[j].innerText);
console.log(document.body.querySelector('.description').innerText);
var list = document.body.querySelectorAll('.results > #details > .specDetail.failed');
if (list && list.length > 0) {
console.log('');
console.log(list.length + ' test(s) FAILED:');
for (i = 0; i < list.length; ++i) {
var el = list[i],
desc = el.querySelector('.description'),
msg = el.querySelector('.resultMessage.fail');
console.log('');
console.log(desc.innerText);
console.log(msg.innerText);
console.log('');
}
return 1;
} else {
console.log(document.body.querySelector('.alert > .passingAlert.bar').innerText);
return 0;
}
} catch (ex) {
console.log(ex);
return 1;
}
});
phantom.exit();
phantom.exit(exitCode);
});
}
});

92
examples/run-jasmine2.js Normal file
View File

@ -0,0 +1,92 @@
var system = require('system');
/**
* Wait until the test condition is true or a timeout occurs. Useful for waiting
* on a server response or for a ui change (fadeIn, etc.) to occur.
*
* @param testFx javascript condition that evaluates to a boolean,
* it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
* as a callback function.
* @param onReady what to do when testFx condition is fulfilled,
* it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
* as a callback function.
* @param timeOutMillis the max amount of time to wait. If not specified, 3 sec is used.
*/
function waitFor(testFx, onReady, timeOutMillis) {
var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 3001, //< Default Max Timeout is 3s
start = new Date().getTime(),
condition = false,
interval = setInterval(function() {
if ( (new Date().getTime() - start < maxtimeOutMillis) && !condition ) {
// If not time-out yet and condition not yet fulfilled
condition = (typeof(testFx) === "string" ? eval(testFx) : testFx()); //< defensive code
} else {
if(!condition) {
// If condition still not fulfilled (timeout but condition is 'false')
console.log("'waitFor()' timeout");
phantom.exit(1);
} else {
// Condition fulfilled (timeout and/or condition is 'true')
console.log("'waitFor()' finished in " + (new Date().getTime() - start) + "ms.");
typeof(onReady) === "string" ? eval(onReady) : onReady(); //< Do what it's supposed to do once the condition is fulfilled
clearInterval(interval); //< Stop this interval
}
}
}, 100); //< repeat check every 100ms
};
if (system.args.length !== 2) {
console.log('Usage: run-jasmine.js URL');
phantom.exit(1);
}
var page = require('webpage').create();
// Route "console.log()" calls from within the Page context to the main Phantom context (i.e. current "this")
page.onConsoleMessage = function(msg) {
console.log(msg);
};
page.open(system.args[1], function(status){
if (status !== "success") {
console.log("Unable to access network");
phantom.exit();
} else {
waitFor(function(){
return page.evaluate(function(){
return document.body.querySelector('.symbolSummary .pending') === null
});
}, function(){
var exitCode = page.evaluate(function(){
console.log('');
var el = document.body.querySelector('.banner');
var banner = el.querySelector('.title').innerText + " " +
el.querySelector('.version').innerText + " " +
el.querySelector('.duration').innerText;
console.log(banner);
var list = document.body.querySelectorAll('.results > .failures > .spec-detail.failed');
if (list && list.length > 0) {
console.log('');
console.log(list.length + ' test(s) FAILED:');
for (i = 0; i < list.length; ++i) {
var el = list[i],
desc = el.querySelector('.description'),
msg = el.querySelector('.messages > .result-message');
console.log('');
console.log(desc.innerText);
console.log(msg.innerText);
console.log('');
}
return 1;
} else {
console.log(document.body.querySelector('.alert > .bar.passed').innerText);
return 0;
}
});
phantom.exit(exitCode);
});
}
});

View File

@ -1,64 +0,0 @@
system = require 'system'
##
# Wait until the test condition is true or a timeout occurs. Useful for waiting
# on a server response or for a ui change (fadeIn, etc.) to occur.
#
# @param testFx javascript condition that evaluates to a boolean,
# it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
# as a callback function.
# @param onReady what to do when testFx condition is fulfilled,
# it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
# as a callback function.
# @param timeOutMillis the max amount of time to wait. If not specified, 3 sec is used.
##
waitFor = (testFx, onReady, timeOutMillis=3000) ->
start = new Date().getTime()
condition = false
f = ->
if (new Date().getTime() - start < timeOutMillis) and not condition
# If not time-out yet and condition not yet fulfilled
condition = (if typeof testFx is 'string' then eval testFx else testFx()) #< defensive code
else
if not condition
# If condition still not fulfilled (timeout but condition is 'false')
console.log "'waitFor()' timeout"
phantom.exit 1
else
# Condition fulfilled (timeout and/or condition is 'true')
console.log "'waitFor()' finished in #{new Date().getTime() - start}ms."
if typeof onReady is 'string' then eval onReady else onReady() #< Do what it's supposed to do once the condition is fulfilled
clearInterval interval #< Stop this interval
interval = setInterval f, 100 #< repeat check every 100ms
if system.args.length isnt 2
console.log 'Usage: run-qunit.coffee URL'
phantom.exit 1
page = require('webpage').create()
# Route "console.log()" calls from within the Page context to the main Phantom context (i.e. current "this")
page.onConsoleMessage = (msg) ->
console.log msg
page.open system.args[1], (status) ->
if status isnt 'success'
console.log 'Unable to access network'
phantom.exit 1
else
waitFor ->
page.evaluate ->
el = document.getElementById 'qunit-testresult'
if el and el.innerText.match 'completed'
return true
return false
, ->
failedNum = page.evaluate ->
el = document.getElementById 'qunit-testresult'
console.log el.innerText
try
return el.getElementsByClassName('failed')[0].innerHTML
catch e
return 10000
phantom.exit if parseInt(failedNum, 10) > 0 then 1 else 0

View File

@ -1,16 +0,0 @@
# List all the files in a Tree of Directories
system = require 'system'
if system.args.length != 2
console.log "Usage: phantomjs scandir.coffee DIRECTORY_TO_SCAN"
phantom.exit 1
scanDirectory = (path) ->
fs = require 'fs'
if fs.exists(path) and fs.isFile(path)
console.log path
else if fs.isDirectory(path)
fs.list(path).forEach (e) ->
scanDirectory path + "/" + e if e != "." and e != ".."
scanDirectory system.args[1]
phantom.exit()

View File

@ -1,17 +0,0 @@
# Show BBC seasonal food list.
window.cbfunc = (data) ->
list = data.query.results.results.result
names = ['January', 'February', 'March',
'April', 'May', 'June',
'July', 'August', 'September',
'October', 'November', 'December']
for item in list
console.log [item.name.replace(/\s/ig, ' '), ':',
names[item.atItsBestUntil], 'to',
names[item.atItsBestFrom]].join(' ')
phantom.exit()
el = document.createElement 'script'
el.src = 'http://query.yahooapis.com/v1/public/yql?q=SELECT%20*%20FROM%20bbc.goodfood.seasonal%3B&format=json&diagnostics=true&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&callback=window.cbfunc'
document.body.appendChild el

View File

@ -1,38 +0,0 @@
system = require 'system'
if system.args.length is 1
console.log "Usage: simpleserver.coffee <portnumber>"
phantom.exit 1
else
port = system.args[1]
server = require("webserver").create()
service = server.listen(port, (request, response) ->
console.log "Request at " + new Date()
console.log JSON.stringify(request, null, 4)
response.statusCode = 200
response.headers =
Cache: "no-cache"
"Content-Type": "text/html"
response.write "<html>"
response.write "<head>"
response.write "<title>Hello, world!</title>"
response.write "</head>"
response.write "<body>"
response.write "<p>This is from PhantomJS web server.</p>"
response.write "<p>Request data:</p>"
response.write "<pre>"
response.write JSON.stringify(request, null, 4)
response.write "</pre>"
response.write "</body>"
response.write "</html>"
response.close()
)
if service
console.log "Web server running on port " + port
else
console.log "Error: Could not create web server listening on port " + port
phantom.exit()

View File

@ -1,20 +0,0 @@
###
Sort integers from the command line in a very ridiculous way: leveraging timeouts :P
###
system = require 'system'
if system.args.length < 2
console.log "Usage: phantomjs sleepsort.coffee PUT YOUR INTEGERS HERE SEPARATED BY SPACES"
phantom.exit 1
else
sortedCount = 0
args = Array.prototype.slice.call(system.args, 1)
for int in args
setTimeout (do (int) ->
->
console.log int
++sortedCount
phantom.exit() if sortedCount is args.length),
int

View File

@ -15,11 +15,11 @@ function sleepSort(array, callback) {
}
}
if ( system.args < 2 ) {
if ( system.args.length < 2 ) {
console.log("Usage: phantomjs sleepsort.js PUT YOUR INTEGERS HERE SEPARATED BY SPACES");
phantom.exit(1);
} else {
sleepSort(Array.prototype.slice.call(system.args, 1), function() {
sleepSort(system.args.slice(1), function() {
phantom.exit();
});
}
}

View File

@ -0,0 +1,18 @@
var system = require('system');
system.stdout.write('Hello, system.stdout.write!');
system.stdout.writeLine('\nHello, system.stdout.writeLine!');
system.stderr.write('Hello, system.stderr.write!');
system.stderr.writeLine('\nHello, system.stderr.writeLine!');
system.stdout.writeLine('system.stdin.readLine(): ');
var line = system.stdin.readLine();
system.stdout.writeLine(JSON.stringify(line));
// This is essentially a `readAll`
system.stdout.writeLine('system.stdin.read(5): (ctrl+D to end)');
var input = system.stdin.read(5);
system.stdout.writeLine(JSON.stringify(input));
phantom.exit(0);

View File

@ -1,17 +0,0 @@
page = require('webpage').create()
page.viewportSize = { width: 320, height: 480 }
page.open 'http://news.google.com/news/i/section?&topic=t',
(status) ->
if status isnt 'success'
console.log 'Unable to access the network!'
else
page.evaluate ->
body = document.body
body.style.backgroundColor = '#fff'
body.querySelector('div#title-block').style.display = 'none'
body.querySelector('form#edition-picker-form')
.parentElement.parentElement.style.display = 'none'
page.render 'technews.png'
phantom.exit()

View File

@ -1,31 +0,0 @@
# Get twitter status for given account (or for the default one, "HeadlessPhantom")
page = require('webpage').create()
system = require 'system'
twitterId = 'HeadlessPhantom' #< default value
# Route "console.log()" calls from within the Page context to the main Phantom context (i.e. current "this")
page.onConsoleMessage = (msg) ->
console.log msg
# Print usage message, if no twitter ID is passed
if system.args.length < 2
console.log 'Usage: tweets.coffee [twitter ID]'
else
twitterId = system.args[1]
# Heading
console.log "*** Latest tweets from @#{twitterId} ***\n"
# Open Twitter Mobile and, onPageLoad, do...
page.open encodeURI("http://mobile.twitter.com/#{twitterId}"), (status) ->
# Check for page load success
if status isnt 'success'
console.log 'Unable to access network'
else
# Execute some DOM inspection within the page context
page.evaluate ->
list = document.querySelectorAll 'span.status'
for i, j in list
console.log "#{j + 1}: #{i.innerHTML.replace /<.*?>/g, ''}"
phantom.exit()

View File

@ -1,8 +1,8 @@
// Get twitter status for given account (or for the default one, "HeadlessPhantom")
// Get twitter status for given account (or for the default one, "PhantomJS")
var page = require('webpage').create(),
system = require('system'),
twitterId = "HeadlessPhantom"; //< default value
twitterId = "PhantomJS"; //< default value
// Route "console.log()" calls from within the Page context to the main Phantom context (i.e. current "this")
page.onConsoleMessage = function(msg) {
@ -27,9 +27,9 @@ page.open(encodeURI("http://mobile.twitter.com/" + twitterId), function (status)
} else {
// Execute some DOM inspection within the page context
page.evaluate(function() {
var list = document.querySelectorAll('span.status');
var list = document.querySelectorAll('div.tweet-text');
for (var i = 0; i < list.length; ++i) {
console.log((i + 1) + ": " + list[i].innerHTML.replace(/<.*?>/g, ''));
console.log((i + 1) + ": " + list[i].innerText);
}
});
}

10
examples/universe.js Normal file
View File

@ -0,0 +1,10 @@
// This is to be used by "module.js" (and "module.coffee") example(s).
// There should NOT be a "universe.coffee" as only 1 of the 2 would
// ever be loaded unless the file extension was specified.
exports.answer = 42;
exports.start = function () {
console.log('Starting the universe....');
}

View File

@ -1,18 +0,0 @@
# Modify global object at the page initialization.
# In this example, effectively Math.random() always returns 0.42.
page = require('webpage').create()
page.onInitialized = ->
page.evaluate ->
Math.random = ->
42 / 100
page.open "http://ariya.github.com/js/random/", (status) ->
if status != "success"
console.log "Network error."
else
console.log page.evaluate(->
document.getElementById("numbers").textContent
)
phantom.exit()

View File

@ -1,11 +0,0 @@
page = require('webpage').create()
console.log 'The default user agent is ' + page.settings.userAgent
page.settings.userAgent = 'SpecialAgent'
page.open 'http://www.httpuseragent.org', (status) ->
if status isnt 'success'
console.log 'Unable to access network'
else
console.log page.evaluate -> document.getElementById('myagent').innerText
phantom.exit()

View File

@ -1,5 +0,0 @@
console.log 'using PhantomJS version ' +
phantom.version.major + '.' +
phantom.version.minor + '.' +
phantom.version.patch
phantom.exit()

View File

@ -1,48 +0,0 @@
##
# Wait until the test condition is true or a timeout occurs. Useful for waiting
# on a server response or for a ui change (fadeIn, etc.) to occur.
#
# @param testFx javascript condition that evaluates to a boolean,
# it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
# as a callback function.
# @param onReady what to do when testFx condition is fulfilled,
# it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
# as a callback function.
# @param timeOutMillis the max amount of time to wait. If not specified, 3 sec is used.
##
waitFor = (testFx, onReady, timeOutMillis=3000) ->
start = new Date().getTime()
condition = false
f = ->
if (new Date().getTime() - start < timeOutMillis) and not condition
# If not time-out yet and condition not yet fulfilled
condition = (if typeof testFx is 'string' then eval testFx else testFx()) #< defensive code
else
if not condition
# If condition still not fulfilled (timeout but condition is 'false')
console.log "'waitFor()' timeout"
phantom.exit 1
else
# Condition fulfilled (timeout and/or condition is 'true')
console.log "'waitFor()' finished in #{new Date().getTime() - start}ms."
if typeof onReady is 'string' then eval onReady else onReady() #< Do what it's supposed to do once the condition is fulfilled
clearInterval interval #< Stop this interval
interval = setInterval f, 250 #< repeat check every 250ms
page = require('webpage').create()
# Open Twitter on 'sencha' profile and, onPageLoad, do...
page.open 'http://twitter.com/#!/sencha', (status) ->
# Check for page load success
if status isnt 'success'
console.log 'Unable to access network'
else
# Wait for 'signin-dropdown' to be visible
waitFor ->
# Check in the page if a specific element is now visible
page.evaluate ->
$('#signin-dropdown').is ':visible'
, ->
console.log 'The sign-in dialog should be visible now.'
phantom.exit()

View File

@ -1,66 +0,0 @@
pageTitle = (page) ->
page.evaluate ->
window.document.title
setPageTitle = (page, newTitle) ->
page.evaluate ((newTitle) ->
window.document.title = newTitle
), newTitle
p = require("webpage").create()
p.open "../test/webpage-spec-frames/index.html", (status) ->
console.log "pageTitle(): " + pageTitle(p)
console.log "currentFrameName(): " + p.currentFrameName()
console.log "childFramesCount(): " + p.childFramesCount()
console.log "childFramesName(): " + p.childFramesName()
console.log "setPageTitle(CURRENT TITLE+'-visited')"
setPageTitle p, pageTitle(p) + "-visited"
console.log ""
console.log "p.switchToChildFrame(\"frame1\"): " + p.switchToChildFrame("frame1")
console.log "pageTitle(): " + pageTitle(p)
console.log "currentFrameName(): " + p.currentFrameName()
console.log "childFramesCount(): " + p.childFramesCount()
console.log "childFramesName(): " + p.childFramesName()
console.log "setPageTitle(CURRENT TITLE+'-visited')"
setPageTitle p, pageTitle(p) + "-visited"
console.log ""
console.log "p.switchToChildFrame(\"frame1-2\"): " + p.switchToChildFrame("frame1-2")
console.log "pageTitle(): " + pageTitle(p)
console.log "currentFrameName(): " + p.currentFrameName()
console.log "childFramesCount(): " + p.childFramesCount()
console.log "childFramesName(): " + p.childFramesName()
console.log "setPageTitle(CURRENT TITLE+'-visited')"
setPageTitle p, pageTitle(p) + "-visited"
console.log ""
console.log "p.switchToParentFrame(): " + p.switchToParentFrame()
console.log "pageTitle(): " + pageTitle(p)
console.log "currentFrameName(): " + p.currentFrameName()
console.log "childFramesCount(): " + p.childFramesCount()
console.log "childFramesName(): " + p.childFramesName()
console.log "setPageTitle(CURRENT TITLE+'-visited')"
setPageTitle p, pageTitle(p) + "-visited"
console.log ""
console.log "p.switchToChildFrame(0): " + p.switchToChildFrame(0)
console.log "pageTitle(): " + pageTitle(p)
console.log "currentFrameName(): " + p.currentFrameName()
console.log "childFramesCount(): " + p.childFramesCount()
console.log "childFramesName(): " + p.childFramesName()
console.log "setPageTitle(CURRENT TITLE+'-visited')"
setPageTitle p, pageTitle(p) + "-visited"
console.log ""
console.log "p.switchToMainFrame()"
p.switchToMainFrame()
console.log "pageTitle(): " + pageTitle(p)
console.log "currentFrameName(): " + p.currentFrameName()
console.log "childFramesCount(): " + p.childFramesCount()
console.log "childFramesName(): " + p.childFramesName()
console.log "setPageTitle(CURRENT TITLE+'-visited')"
setPageTitle p, pageTitle(p) + "-visited"
console.log ""
console.log "p.switchToChildFrame(\"frame2\"): " + p.switchToChildFrame("frame2")
console.log "pageTitle(): " + pageTitle(p)
console.log "currentFrameName(): " + p.currentFrameName()
console.log "childFramesCount(): " + p.childFramesCount()
console.log "childFramesName(): " + p.childFramesName()
console.log "setPageTitle(CURRENT TITLE+'-visited')"
setPageTitle p, pageTitle(p) + "-visited"
console.log ""
phantom.exit()

View File

@ -1,49 +0,0 @@
# Get weather info for given address (or for the default one, "Mountain View")
page = require('webpage').create()
system = require 'system'
address = 'Mountain View' #< default value
# Route "console.log()" calls from within the Page context to the main Phantom context (i.e. current "this")
page.onConsoleMessage = (msg) ->
console.log msg
# Print usage message, if no address is passed
if system.args.length < 2
console.log 'Usage: weather.coffee [address]'
else
address = Array.prototype.slice.call(system.args, 1).join(' ')
# Heading
console.log "*** Loading weather information for '#{address}' ***\n"
# Open Google "secret" Weather API and, onPageLoad, do...
page.open encodeURI("http://www.google.com/ig/api?weather=#{address}"), (status) ->
# Check for page load success
if status isnt 'success'
console.log 'Unable to access network'
else
# Execute some DOM inspection within the page context
page.evaluate ->
if document.querySelectorAll('problem_cause').length > 0
console.log "No data available for #{address}"
else
data = (s, e) ->
e = e or document
el = e.querySelector s
if el then el.attributes.data.value else undefined
console.log """City: #{data 'weather > forecast_information > city'}
Current condition: #{data 'weather > current_conditions > condition'}
Temperature: #{data 'weather > current_conditions > temp_f'} F
#{data 'weather > current_conditions > humidity'}
#{data 'weather > current_conditions > wind_condition'}\n
"""
forecasts = document.querySelectorAll 'weather > forecast_conditions'
for i in forecasts
console.log "#{ data 'day_of_week', i }: " +
"#{ data 'low', i }-" +
"#{ data 'high', i } F " +
"#{ data 'condition', i }"
phantom.exit()

View File

@ -1,58 +1,37 @@
// Get weather info for given address (or for the default one, "Mountain View")
var page = require('webpage').create(),
system = require('system'),
address = "Mountain View"; //< default value
city,
url;
// Route "console.log()" calls from within the Page context to the main Phantom context (i.e. current "this")
page.onConsoleMessage = function(msg) {
console.log(msg);
};
// Print usage message, if no address is passed
if (system.args.length < 2) {
console.log("Usage: weather.js [address]");
} else {
address = Array.prototype.slice.call(system.args, 1).join(' ');
city = 'Mountain View, California'; // default
if (system.args.length > 1) {
city = Array.prototype.slice.call(system.args, 1).join(' ');
}
url = encodeURI('http://api.openweathermap.org/data/2.1/find/name?q=' + city);
// Heading
console.log("*** Loading weather information for '" + address + "' ***\n");
console.log('Checking weather condition for', city, '...');
// Open Google "secret" Weather API and, onPageLoad, do...
page.open(encodeURI('http://www.google.com/ig/api?weather=' + address), function (status) {
// Check for page load success
if (status !== "success") {
console.log("Unable to access network");
page.open(url, function(status) {
var result, data;
if (status !== 'success') {
console.log('Error: Unable to access network!');
} else {
// Execute some DOM inspection within the page context
page.evaluate(function() {
if (document.querySelectorAll('problem_cause').length > 0) {
console.log('No data available for ' + address);
} else {
function data (s, e) {
var el;
e = e || document;
el = e.querySelector(s);
return el ? el.attributes.data.value : undefined;
};
console.log('City: ' + data('weather > forecast_information > city'));
console.log('Current condition: ' + data('weather > current_conditions > condition'));
console.log('Temperature: ' + data('weather > current_conditions > temp_f') + ' F');
console.log(data('weather > current_conditions > humidity'));
console.log(data('weather > current_conditions > wind_condition'));
console.log('');
var forecasts = document.querySelectorAll('weather > forecast_conditions');
for (var i = 0; i < forecasts.length; ++i) {
var f = forecasts[i];
console.log(data('day_of_week', f) + ': ' +
data('low', f) + '-' + data('high', f) + ' F ' +
data('condition', f));
}
}
result = page.evaluate(function () {
return document.body.innerText;
});
try {
data = JSON.parse(result);
data = data.list[0];
console.log('');
console.log('City:', data.name);
console.log('Condition:', data.weather.map(function(entry) {
return entry.main;
}).join(', '));
console.log('Temperature:', Math.round(data.main.temp - 273.15), 'C');
console.log('Humidity:', Math.round(data.main.humidity), '%');
} catch (e) {
console.log('Error:', e.toString());
}
}
phantom.exit();
});

View File

@ -1,3 +1,3 @@
TEMPLATE = subdirs
CONFIG += ordered
SUBDIRS += src/phantomjs.pro
SUBDIRS += src/qphantom/phantom.pro src/phantomjs.pro

24
rpm/mkrpm.sh Executable file
View File

@ -0,0 +1,24 @@
#!/bin/sh
#
# A silly little helper script to build the RPM.
set -e
name=${1:?"Usage: build <toolname>"}
name=${name%.spec}
topdir=$(mktemp -d)
version=$(awk '/define version/ { print $NF }' ${name}.spec)
builddir=${TMPDIR:-/tmp}/${name}-${version}
sourcedir="${topdir}/SOURCES"
buildroot="${topdir}/BUILD/${name}-${version}-root"
mkdir -p ${topdir}/RPMS ${topdir}/SRPMS ${topdir}/SOURCES ${topdir}/BUILD
mkdir -p ${buildroot} ${builddir}
echo "=> Copying sources..."
( cd .. && tar cf - ./[A-Z]* ./bin ./examples | tar xf - -C ${builddir} )
echo "=> Creating source tarball under ${sourcedir}..."
( cd ${builddir}/.. && tar zcf ${sourcedir}/${name}-${version}.tar.gz ${name}-${version} )
echo "=> Building RPM..."
rpm=$(rpmbuild --define "_topdir ${topdir}" --buildroot ${buildroot} --clean -bb ${name}.spec 2>/dev/null | \
awk '/\/RPMS\// { print $2; }')
cp ${rpm} ${TMPDIR:-/tmp}/
rm -fr ${topdir}
echo ${TMPDIR:-/tmp}/${rpm##*/}

163
rpm/phantomjs.spec Normal file
View File

@ -0,0 +1,163 @@
%define name phantomjs
%define version 1.9
%define release 1
%define prefix /usr
%define mybuilddir %{_builddir}/%{name}-%{version}-root
Summary: a headless WebKit with JavaScript API
Name: %{name}
Version: %{version}
License: BSD
Release: %{release}
Packager: Matthew Barr <mbarr@snap-interactive.com>
Group: Utilities/Misc
Source: %{name}-%{version}.tar.gz
BuildRoot: /tmp/%{name}-%{version}-root
%description
PhantomJS is a headless WebKit with JavaScript API. It has fast and native
support for various web standards: DOM handling, CSS selector, JSON,
Canvas, and SVG. PhantomJS is created by Ariya Hidayat.
%prep
%setup -q
%install
mkdir -p %{mybuilddir}%{prefix}/bin
mkdir -p %{mybuilddir}%{prefix}/share/%{name}/examples
cp bin/%{name} %{mybuilddir}%{prefix}/bin/%{name}
cp examples/* %{mybuilddir}%{prefix}/share/%{name}/examples/
cp CONTRIBUTING.md %{mybuilddir}%{prefix}/share/%{name}/
cp ChangeLog %{mybuilddir}%{prefix}/share/%{name}/
cp LICENSE.BSD %{mybuilddir}%{prefix}/share/%{name}/
cp README.md %{mybuilddir}%{prefix}/share/%{name}/
%files
%defattr(0444,root,root)
%attr(0555,root,root)%{prefix}/bin/%{name}
%{prefix}/share/%{name}/ChangeLog
%{prefix}/share/%{name}/CONTRIBUTING.md
%{prefix}/share/%{name}/examples/arguments.coffee
%{prefix}/share/%{name}/examples/arguments.js
%{prefix}/share/%{name}/examples/child_process-examples.coffee
%{prefix}/share/%{name}/examples/child_process-examples.js
%{prefix}/share/%{name}/examples/colorwheel.coffee
%{prefix}/share/%{name}/examples/colorwheel.js
%{prefix}/share/%{name}/examples/countdown.coffee
%{prefix}/share/%{name}/examples/countdown.js
%{prefix}/share/%{name}/examples/detectsniff.coffee
%{prefix}/share/%{name}/examples/detectsniff.js
%{prefix}/share/%{name}/examples/direction.coffee
%{prefix}/share/%{name}/examples/direction.js
%{prefix}/share/%{name}/examples/echoToFile.coffee
%{prefix}/share/%{name}/examples/echoToFile.js
%{prefix}/share/%{name}/examples/features.coffee
%{prefix}/share/%{name}/examples/features.js
%{prefix}/share/%{name}/examples/fibo.coffee
%{prefix}/share/%{name}/examples/fibo.js
%{prefix}/share/%{name}/examples/follow.coffee
%{prefix}/share/%{name}/examples/follow.js
%{prefix}/share/%{name}/examples/hello.coffee
%{prefix}/share/%{name}/examples/hello.js
%{prefix}/share/%{name}/examples/imagebin.coffee
%{prefix}/share/%{name}/examples/imagebin.js
%{prefix}/share/%{name}/examples/injectme.coffee
%{prefix}/share/%{name}/examples/injectme.js
%{prefix}/share/%{name}/examples/ipgeocode.coffee
%{prefix}/share/%{name}/examples/ipgeocode.js
%{prefix}/share/%{name}/examples/loadspeed.coffee
%{prefix}/share/%{name}/examples/loadspeed.js
%{prefix}/share/%{name}/examples/loadurlwithoutcss.coffee
%{prefix}/share/%{name}/examples/loadurlwithoutcss.js
%{prefix}/share/%{name}/examples/modernizr.js
%{prefix}/share/%{name}/examples/module.coffee
%{prefix}/share/%{name}/examples/module.js
%{prefix}/share/%{name}/examples/movies.coffee
%{prefix}/share/%{name}/examples/movies.js
%{prefix}/share/%{name}/examples/netlog.coffee
%{prefix}/share/%{name}/examples/netlog.js
%{prefix}/share/%{name}/examples/netsniff.coffee
%{prefix}/share/%{name}/examples/netsniff.js
%{prefix}/share/%{name}/examples/openurlwithproxy.coffee
%{prefix}/share/%{name}/examples/openurlwithproxy.js
%{prefix}/share/%{name}/examples/outputEncoding.coffee
%{prefix}/share/%{name}/examples/outputEncoding.js
%{prefix}/share/%{name}/examples/page_events.coffee
%{prefix}/share/%{name}/examples/page_events.js
%{prefix}/share/%{name}/examples/pagecallback.coffee
%{prefix}/share/%{name}/examples/pagecallback.js
%{prefix}/share/%{name}/examples/phantomwebintro.coffee
%{prefix}/share/%{name}/examples/phantomwebintro.js
%{prefix}/share/%{name}/examples/pizza.coffee
%{prefix}/share/%{name}/examples/pizza.js
%{prefix}/share/%{name}/examples/post.coffee
%{prefix}/share/%{name}/examples/post.js
%{prefix}/share/%{name}/examples/postjson.coffee
%{prefix}/share/%{name}/examples/postjson.js
%{prefix}/share/%{name}/examples/postserver.coffee
%{prefix}/share/%{name}/examples/postserver.js
%{prefix}/share/%{name}/examples/printenv.coffee
%{prefix}/share/%{name}/examples/printenv.js
%{prefix}/share/%{name}/examples/printheaderfooter.coffee
%{prefix}/share/%{name}/examples/printheaderfooter.js
%{prefix}/share/%{name}/examples/printmargins.coffee
%{prefix}/share/%{name}/examples/printmargins.js
%{prefix}/share/%{name}/examples/rasterize.coffee
%{prefix}/share/%{name}/examples/rasterize.js
%{prefix}/share/%{name}/examples/render_multi_url.coffee
%{prefix}/share/%{name}/examples/render_multi_url.js
%{prefix}/share/%{name}/examples/run-jasmine.coffee
%{prefix}/share/%{name}/examples/run-jasmine.js
%{prefix}/share/%{name}/examples/run-jasmine2.js
%{prefix}/share/%{name}/examples/run-qunit.coffee
%{prefix}/share/%{name}/examples/run-qunit.js
%{prefix}/share/%{name}/examples/scandir.coffee
%{prefix}/share/%{name}/examples/scandir.js
%{prefix}/share/%{name}/examples/seasonfood.coffee
%{prefix}/share/%{name}/examples/seasonfood.js
%{prefix}/share/%{name}/examples/server.coffee
%{prefix}/share/%{name}/examples/server.js
%{prefix}/share/%{name}/examples/serverkeepalive.coffee
%{prefix}/share/%{name}/examples/serverkeepalive.js
%{prefix}/share/%{name}/examples/simpleserver.coffee
%{prefix}/share/%{name}/examples/simpleserver.js
%{prefix}/share/%{name}/examples/sleepsort.coffee
%{prefix}/share/%{name}/examples/sleepsort.js
%{prefix}/share/%{name}/examples/stdin-stdout-stderr.coffee
%{prefix}/share/%{name}/examples/stdin-stdout-stderr.js
%{prefix}/share/%{name}/examples/technews.coffee
%{prefix}/share/%{name}/examples/technews.js
%{prefix}/share/%{name}/examples/tweets.coffee
%{prefix}/share/%{name}/examples/tweets.js
%{prefix}/share/%{name}/examples/universe.js
%{prefix}/share/%{name}/examples/unrandomize.coffee
%{prefix}/share/%{name}/examples/unrandomize.js
%{prefix}/share/%{name}/examples/useragent.coffee
%{prefix}/share/%{name}/examples/useragent.js
%{prefix}/share/%{name}/examples/version.coffee
%{prefix}/share/%{name}/examples/version.js
%{prefix}/share/%{name}/examples/waitfor.coffee
%{prefix}/share/%{name}/examples/waitfor.js
%{prefix}/share/%{name}/examples/walk_through_frames.coffee
%{prefix}/share/%{name}/examples/walk_through_frames.js
%{prefix}/share/%{name}/examples/weather.coffee
%{prefix}/share/%{name}/examples/weather.js
%{prefix}/share/%{name}/LICENSE.BSD
%{prefix}/share/%{name}/README.md
%changelog
* Fri Apr 18 2014 Eric Heydenberk <heydenberk@gmail.com>
- add missing filenames for examples to files section
* Tue Apr 30 2013 Eric Heydenberk <heydenberk@gmail.com>
- add missing filenames for examples to files section
* Wed Apr 24 2013 Robin Helgelin <lobbin@gmail.com>
- updated to version 1.9
* Thu Jan 24 2013 Matthew Barr <mbarr@snap-interactive.com>
- updated to version 1.8
* Thu Nov 15 2012 Jan Schaumann <jschauma@etsy.com>
- first rpm version

View File

@ -8,6 +8,7 @@
Copyright (C) 2011 Ivan De Marino <ivan.de.marino@gmail.com>
Copyright (C) 2011 James Roe <roejames12@hotmail.com>
Copyright (C) 2011 execjosh, http://execjosh.blogspot.com
Copyright (C) 2012 James M. Greene <james.m.greene@gmail.com>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
@ -33,53 +34,53 @@
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
function require(name) {
var code, func, exports;
phantom.__defineErrorSignalHandler__ = function(obj, page, handlers) {
var handlerName = 'onError';
if (name === 'webpage' || name === 'fs' || name === 'webserver' || name === 'system') {
code = phantom.loadModuleSource(name);
func = new Function("exports", "window", code);
exports = {};
if (name === 'fs') {
exports = phantom.createFilesystem();
} else if (name === 'system') {
exports = phantom.createSystem();
}
func.call({}, exports, {});
return exports;
}
Object.defineProperty(obj, handlerName, {
set: function (f) {
// Disconnect previous handler (if any)
var handlerObj = handlers[handlerName];
if (!!handlerObj && typeof handlerObj.callback === "function" && typeof handlerObj.connector === "function") {
try { page.javaScriptErrorSent.disconnect(handlerObj.connector); }
catch (e) { }
}
if (typeof exports === 'undefined') {
throw 'Unknown module ' + name + ' for require()';
}
}
// Delete the previous handler
delete handlers[handlerName];
phantom.__defineErrorSetter__ = function(obj, page) {
var handler;
var signal = page.javaScriptErrorSent;
if (typeof f === 'function') {
var connector = function (message, lineNumber, source, stack) {
var revisedStack = JSON.parse(stack).map(function (item) {
return { file: item.url, line: item.lineNumber, function: item.functionName };
});
if (revisedStack.length == 0)
revisedStack = [{ file: source, line: lineNumber }];
obj.__defineSetter__('onError', function(f) {
if (handler && typeof handler === 'function') {
try { signal.disconnect(handler); }
catch (e) {}
}
f(message, revisedStack);
};
// Store the new handler for reference
handlers[handlerName] = {
callback: f,
connector: connector
};
if (typeof f === 'function') {
handler = function(message, stack) {
stack = JSON.parse(stack).map(function(item) {
return { file: item.url, line: item.lineNumber, function: item.functionName }
});
f(message, stack);
};
signal.connect(handler);
} else {
handler = null;
page.javaScriptErrorSent.connect(connector);
}
},
get: function () {
var handlerObj = handlers[handlerName];
return (!!handlerObj && typeof handlerObj.callback === "function" && typeof handlerObj.connector === "function") ?
handlers[handlerName].callback :
undefined;
}
});
};
phantom.__defineErrorSetter__(phantom, phantom.page);
(function() {
var handlers = {};
phantom.__defineErrorSignalHandler__(phantom, phantom.page, handlers);
})();
// TODO: Make this output to STDERR
phantom.defaultErrorHandler = function(message, stack) {
@ -87,12 +88,14 @@ phantom.defaultErrorHandler = function(message, stack) {
stack.forEach(function(item) {
var message = item.file + ":" + item.line;
if (item.function)
message += " in " + item.function;
if (item["function"])
message += " in " + item["function"];
console.log(" " + message);
});
};
phantom.onError = phantom.defaultErrorHandler;
phantom.callback = function(callback) {
var ret = phantom.createCallback();
ret.called.connect(function(args) {
@ -102,7 +105,223 @@ phantom.callback = function(callback) {
return ret;
};
phantom.onError = phantom.defaultErrorHandler;
(function() {
// CommonJS module implementation follows
window.global = window;
// fs is loaded at the end, when everything is ready
var fs;
var cache = {};
var paths = [];
// use getters to initialize lazily
// (for future, now both fs and system are loaded anyway)
var nativeExports = {
get fs() { return phantom.createFilesystem(); },
get child_process() { return phantom._createChildProcess(); },
get system() { return phantom.createSystem(); }
};
var extensions = {
'.js': function(module, filename) {
var code = fs.read(filename);
module._compile(code);
},
'.json': function(module, filename) {
module.exports = JSON.parse(fs.read(filename));
}
};
function loadFs() {
var file, code, module, filename = ':/modules/fs.js';
module = new Module(filename);
cache[filename] = module;
module.exports = nativeExports.fs;
file = module.exports._open(filename, { mode: 'r' })
code = file.read();
file.close();
module._compile(code);
return module.exports;
}
function dirname(path) {
var replaced = path.replace(/\/[^\/]*\/?$/, '');
if (replaced == path) {
replaced = '';
}
return replaced;
}
function basename(path) {
return path.replace(/.*\//, '');
}
function joinPath() {
// It should be okay to hard-code a slash here.
// The FileSystem module returns a platform-specific
// separator, but the JavaScript engine only expects
// the slash.
var args = Array.prototype.slice.call(arguments);
return args.join('/');
}
function tryFile(path) {
if (fs.isFile(path)) return path;
return null;
}
function tryExtensions(path) {
var filename, exts = Object.keys(extensions);
for (var i=0; i<exts.length; ++i) {
filename = tryFile(path + exts[i]);
if (filename) return filename;
}
return null;
}
function tryPackage(path) {
var filename, package, packageFile = joinPath(path, 'package.json');
if (fs.isFile(packageFile)) {
package = JSON.parse(fs.read(packageFile));
if (!package || !package.main) return null;
filename = fs.absolute(joinPath(path, package.main));
return tryFile(filename) || tryExtensions(filename) ||
tryExtensions(joinPath(filename, 'index'));
}
return null;
}
function Module(filename, stubs) {
if (filename) this._setFilename(filename);
this.exports = {};
this.stubs = {};
for (var name in stubs) {
this.stubs[name] = stubs[name];
}
}
Module.prototype._setFilename = function(filename) {
this.id = this.filename = filename;
this.dirname = dirname(filename);
};
Module.prototype._isNative = function() {
return this.filename && this.filename[0] === ':';
};
Module.prototype._getPaths = function(request) {
var _paths = [], dir;
if (request[0] === '.') {
_paths.push(fs.absolute(joinPath(phantom.webdriverMode ? ":/ghostdriver" : this.dirname, request)));
} else if (fs.isAbsolute(request)) {
_paths.push(fs.absolute(request));
} else {
// first look in PhantomJS modules
_paths.push(joinPath(':/modules', request));
// then look in node_modules directories
if (!this._isNative()) {
dir = this.dirname;
while (dir) {
_paths.push(joinPath(dir, 'node_modules', request));
dir = dirname(dir);
}
}
}
for (var i=0; i<paths.length; ++i) {
if(fs.isAbsolute(paths[i])) {
_paths.push(fs.absolute(joinPath(paths[i], request)));
} else {
_paths.push(fs.absolute(joinPath(this.dirname, paths[i], request)));
}
}
return _paths;
};
Module.prototype._getFilename = function(request) {
var path, filename = null, _paths = this._getPaths(request);
for (var i=0; i<_paths.length && !filename; ++i) {
path = _paths[i];
filename = tryFile(path) || tryExtensions(path) || tryPackage(path) ||
tryExtensions(joinPath(path, 'index'));
}
return filename;
};
Module.prototype._getRequire = function() {
var self = this;
function require(request) {
return self.require(request);
}
require.cache = cache;
require.extensions = extensions;
require.paths = paths;
require.stub = function(request, exports) {
self.stubs[request] = { exports: exports };
};
return require;
};
Module.prototype._load = function() {
var ext = this.filename.match(/\.[^.]+$/)[0];
if (!ext) ext = '.js';
extensions[ext](this, this.filename);
};
Module.prototype._compile = function(code) {
phantom.loadModule(code, this.filename);
};
Module.prototype.require = function(request) {
var filename, module;
// first see if there are any stubs for the request
if (this.stubs.hasOwnProperty(request)) {
if (this.stubs[request].exports instanceof Function) {
this.stubs[request].exports = this.stubs[request].exports();
}
return this.stubs[request].exports;
}
// else look for a file
filename = this._getFilename(request);
if (!filename) {
throw new Error("Cannot find module '" + request + "'");
}
if (cache.hasOwnProperty(filename)) {
return cache[filename].exports;
}
module = new Module(filename, this.stubs);
if (module._isNative()) {
module.exports = nativeExports[request] || {};
}
cache[filename] = module;
module._load();
return module.exports;
};
(function() {
var cwd, mainFilename, mainModule = new Module();
window.require = mainModule._getRequire();
fs = loadFs();
cwd = fs.absolute(phantom.libraryPath);
mainFilename = joinPath(cwd, basename(require('system').args[0]) || 'repl');
mainModule._setFilename(mainFilename);
}());
}());
// Legacy way to use WebPage
window.WebPage = require('webpage').create;

View File

@ -1 +0,0 @@
../.gitignore-breakpad

18
src/breakpad/.gitignore vendored Normal file
View File

@ -0,0 +1,18 @@
/src/client/linux/linux_dumper_unittest_helper
/src/processor/minidump_dump
/src/processor/minidump_stackwalk
/src/tools/linux/core2md/core2md
/src/tools/linux/dump_syms/dump_syms
/src/tools/linux/md2core/minidump-2-core
/src/tools/linux/symupload/minidump_upload
/src/tools/linux/symupload/sym_upload
/src/config.h
/src/stamp-h1
/config.log
/config.status
/autom4te.cache
!Makefile.am
!Makefile.in
.dirstamp
.deps

View File

@ -1 +0,0 @@
/usr/share/automake-1.11/compile

View File

@ -29,6 +29,8 @@
#include "callback.h"
#include <QDebug>
Callback::Callback(QObject* parent)
: QObject(parent)
{
@ -38,6 +40,7 @@ QVariant Callback::call(const QVariantList& arguments)
{
emit called(arguments);
qDebug() << "Callback - call result:" << m_returnValue;
return m_returnValue;
}
@ -49,4 +52,4 @@ QVariant Callback::returnValue() const
void Callback::setReturnValue(const QVariant& returnValue)
{
m_returnValue = returnValue;
}
}

136
src/childprocess.cpp Normal file
View File

@ -0,0 +1,136 @@
/*
This file is part of the PhantomJS project from Ofi Labs.
Copyright (C) 2012 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 <organization> 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 <COPYRIGHT HOLDER> 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.
*/
#include "childprocess.h"
//
// ChildProcessContext
//
ChildProcessContext::ChildProcessContext(QObject *parent)
: QObject(parent)
, m_proc(this)
{
connect(&m_proc, SIGNAL(readyReadStandardOutput()), this, SLOT(_readyReadStandardOutput()));
connect(&m_proc, SIGNAL(readyReadStandardError()), this, SLOT(_readyReadStandardError()));
connect(&m_proc, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(_finished(int, QProcess::ExitStatus)));
connect(&m_proc, SIGNAL(error(QProcess::ProcessError)), this, SLOT(_error(QProcess::ProcessError)));
}
ChildProcessContext::~ChildProcessContext()
{
}
// public:
qint64 ChildProcessContext::pid() const
{
Q_PID pid = m_proc.pid();
#if !defined(Q_OS_WIN32) && !defined(Q_OS_WINCE)
return pid;
#else
return pid->dwProcessId;
#endif
}
void ChildProcessContext::kill(const QString &signal)
{
// TODO: it would be nice to be able to handle more signals
if ("SIGKILL" == signal) {
m_proc.kill();
} else {
// Default to "SIGTERM"
m_proc.terminate();
}
}
void ChildProcessContext::_setEncoding(const QString &encoding)
{
m_encoding.setEncoding(encoding);
}
// This is affected by [QTBUG-5990](https://bugreports.qt-project.org/browse/QTBUG-5990).
// `QProcess` doesn't properly handle the situations of `cmd` not existing or
// failing to start...
bool ChildProcessContext::_start(const QString &cmd, const QStringList &args)
{
m_proc.start(cmd, args);
// TODO: Is there a better way to do this???
return m_proc.waitForStarted(1000);
}
// private slots:
void ChildProcessContext::_readyReadStandardOutput()
{
QByteArray bytes = m_proc.readAllStandardOutput();
emit stdoutData(m_encoding.decode(bytes));
}
void ChildProcessContext::_readyReadStandardError()
{
QByteArray bytes = m_proc.readAllStandardError();
emit stderrData(m_encoding.decode(bytes));
}
void ChildProcessContext::_finished(const int exitCode, const QProcess::ExitStatus exitStatus)
{
Q_UNUSED(exitStatus)
emit exit(exitCode);
}
void ChildProcessContext::_error(const QProcess::ProcessError error)
{
Q_UNUSED(error)
emit exit(m_proc.exitCode());
}
//
// ChildProcess
//
ChildProcess::ChildProcess(QObject *parent)
: QObject(parent)
{
}
ChildProcess::~ChildProcess()
{
}
// public:
QObject *ChildProcess::_createChildProcessContext()
{
return new ChildProcessContext(this);
}

97
src/childprocess.h Normal file
View File

@ -0,0 +1,97 @@
/*
This file is part of the PhantomJS project from Ofi Labs.
Copyright (C) 2012 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 <organization> 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 <COPYRIGHT HOLDER> 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.
*/
#ifndef CHILDPROCESS_H
#define CHILDPROCESS_H
#include <QObject>
#include <QProcess>
#ifdef Q_OS_WIN32
#include <QtCore/qt_windows.h>
#endif
#include "encoding.h"
/**
* This class wraps a QProcess and facilitates emulation of node.js's ChildProcess
*/
class ChildProcessContext : public QObject
{
Q_OBJECT
Q_PROPERTY(qint64 pid READ pid)
public:
explicit ChildProcessContext(QObject *parent = 0);
virtual ~ChildProcessContext();
qint64 pid() const;
Q_INVOKABLE void kill(const QString &signal = "SIGTERM");
Q_INVOKABLE void _setEncoding(const QString &encoding);
Q_INVOKABLE bool _start(const QString &cmd, const QStringList &args);
signals:
void exit(const int code) const;
/**
* For emulating `child.stdout.on("data", function (data) {})`
*/
void stdoutData(const QString &data) const;
/**
* For emulating `child.stderr.on("data", function (data) {})`
*/
void stderrData(const QString &data) const;
private slots:
void _readyReadStandardOutput();
void _readyReadStandardError();
void _error(const QProcess::ProcessError error);
void _finished(const int exitCode, const QProcess::ExitStatus exitStatus);
private:
QProcess m_proc;
Encoding m_encoding;
};
/**
* Helper class for child_process module
*/
class ChildProcess : public QObject
{
Q_OBJECT
public:
explicit ChildProcess(QObject *parent = 0);
virtual ~ChildProcess();
Q_INVOKABLE QObject *_createChildProcessContext();
};
#endif // CHILDPROCESS_H

File diff suppressed because one or more lines are too long

View File

@ -1,8 +1,10 @@
/*
This file is part of the PhantomJS project from Ofi Labs.
Copyright (C) 2012 Ariya Hidayat <ariya.hidayat@gmail.com>
Copyright (C) 2011 Ariya Hidayat <ariya.hidayat@gmail.com>
Copyright (C) 2011 execjosh, http://execjosh.blogspot.com
Copyright (C) 2013 James M. Greene <james.m.greene@gmail.com>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
@ -31,17 +33,65 @@
#include "config.h"
#include <QDir>
#include <QWebPage>
#include <QWebFrame>
#include <QFileInfo>
#include <QtWebKitWidgets/QWebPage>
#include <QtWebKitWidgets/QWebFrame>
#include <QNetworkProxy>
#include "terminal.h"
#include "qcommandline.h"
#include "utils.h"
#include "consts.h"
#include <iostream>
static const struct QCommandLineConfigEntry flags[] =
{
{ QCommandLine::Option, '\0', "cookies-file", "Sets the file name to store the persistent cookies", QCommandLine::Optional },
{ QCommandLine::Option, '\0', "config", "Specifies JSON-formatted configuration file", QCommandLine::Optional },
{ QCommandLine::Option, '\0', "debug", "Prints additional warning and debug message: 'true' or 'false' (default)", QCommandLine::Optional },
{ QCommandLine::Option, '\0', "disk-cache", "Enables disk cache: 'true' or 'false' (default)", QCommandLine::Optional },
{ QCommandLine::Option, '\0', "ignore-ssl-errors", "Ignores SSL errors (expired/self-signed certificate errors): 'true' or 'false' (default)", QCommandLine::Optional },
{ QCommandLine::Option, '\0', "load-images", "Loads all inlined images: 'true' (default) or 'false'", QCommandLine::Optional },
{ QCommandLine::Option, '\0', "local-storage-path", "Specifies the location for offline local storage", QCommandLine::Optional },
{ QCommandLine::Option, '\0', "local-storage-quota", "Sets the maximum size of the offline local storage (in KB)", QCommandLine::Optional },
{ QCommandLine::Option, '\0', "local-url-access", "Allows use of 'file:///' URLs: 'true' (default) or 'false'", QCommandLine::Optional },
{ QCommandLine::Option, '\0', "local-to-remote-url-access", "Allows local content to access remote URL: 'true' or 'false' (default)", QCommandLine::Optional },
{ QCommandLine::Option, '\0', "max-disk-cache-size", "Limits the size of the disk cache (in KB)", QCommandLine::Optional },
{ QCommandLine::Option, '\0', "output-encoding", "Sets the encoding for the terminal output, default is 'utf8'", QCommandLine::Optional },
{ QCommandLine::Option, '\0', "remote-debugger-port", "Starts the script in a debug harness and listens on the specified port", QCommandLine::Optional },
{ QCommandLine::Option, '\0', "remote-debugger-autorun", "Runs the script in the debugger immediately: 'true' or 'false' (default)", QCommandLine::Optional },
{ QCommandLine::Option, '\0', "proxy", "Sets the proxy server, e.g. '--proxy=http://proxy.company.com:8080'", QCommandLine::Optional },
{ QCommandLine::Option, '\0', "proxy-auth", "Provides authentication information for the proxy, e.g. ''-proxy-auth=username:password'", QCommandLine::Optional },
{ QCommandLine::Option, '\0', "proxy-type", "Specifies the proxy type, 'http' (default), 'none' (disable completely), or 'socks5'", QCommandLine::Optional },
{ QCommandLine::Option, '\0', "script-encoding", "Sets the encoding used for the starting script, default is 'utf8'", QCommandLine::Optional },
{ QCommandLine::Option, '\0', "script-language", "Sets the script language instead of detecting it: 'javascript'", QCommandLine::Optional },
{ QCommandLine::Option, '\0', "web-security", "Enables web security, 'true' (default) or 'false'", QCommandLine::Optional },
{ QCommandLine::Option, '\0', "ssl-protocol", "Selects a specific SSL protocol version to offer. Values (case insensitive): TLSv1.2, TLSv1.1, TLSv1.0, TLSv1 (same as v1.0), SSLv3, or ANY. Default is to offer all that Qt thinks are secure (SSLv3 and up). Not all values may be supported, depending on the system OpenSSL library.", QCommandLine::Optional },
{ QCommandLine::Option, '\0', "ssl-ciphers", "Sets supported TLS/SSL ciphers. Argument is a colon-separated list of OpenSSL cipher names (macros like ALL, kRSA, etc. may not be used). Default matches modern browsers.", QCommandLine::Optional },
{ QCommandLine::Option, '\0', "ssl-certificates-path", "Sets the location for custom CA certificates (if none set, uses system default)", QCommandLine::Optional },
{ QCommandLine::Option, '\0', "webdriver", "Starts in 'Remote WebDriver mode' (embedded GhostDriver): '[[<IP>:]<PORT>]' (default '127.0.0.1:8910') ", QCommandLine::Optional },
{ QCommandLine::Option, '\0', "webdriver-logfile", "File where to write the WebDriver's Log (default 'none') (NOTE: needs '--webdriver') ", QCommandLine::Optional },
{ QCommandLine::Option, '\0', "webdriver-loglevel", "WebDriver Logging Level: (supported: 'ERROR', 'WARN', 'INFO', 'DEBUG') (default 'INFO') (NOTE: needs '--webdriver') ", QCommandLine::Optional },
{ QCommandLine::Option, '\0', "webdriver-selenium-grid-hub", "URL to the Selenium Grid HUB: 'URL_TO_HUB' (default 'none') (NOTE: needs '--webdriver') ", QCommandLine::Optional },
{ QCommandLine::Param, '\0', "script", "Script", QCommandLine::Flags(QCommandLine::Optional|QCommandLine::ParameterFence)},
{ QCommandLine::Param, '\0', "argument", "Script argument", QCommandLine::OptionalMultiple },
{ QCommandLine::Switch, 'w', "wd", "Equivalent to '--webdriver' option above", QCommandLine::Optional },
{ QCommandLine::Switch, 'h', "help", "Shows this message and quits", QCommandLine::Optional },
{ QCommandLine::Switch, 'v', "version", "Prints out PhantomJS version", QCommandLine::Optional },
QCOMMANDLINE_CONFIG_ENTRY_END
};
// public:
Config::Config(QObject *parent)
: QObject(parent)
{
m_cmdLine = new QCommandLine(this);
// We will handle --help and --version ourselves in phantom.cpp
m_cmdLine->enableHelp(false);
m_cmdLine->enableVersion(false);
resetToDefaults();
}
@ -49,138 +99,46 @@ void Config::init(const QStringList *const args)
{
resetToDefaults();
QByteArray envSslCertDir = qgetenv("SSL_CERT_DIR");
if (!envSslCertDir.isEmpty())
setSslCertificatesPath(envSslCertDir);
processArgs(*args);
}
void Config::processArgs(const QStringList &args)
{
QStringListIterator it(args);
while (it.hasNext()) {
const QString &arg = it.next();
connect(m_cmdLine, SIGNAL(switchFound(const QString &)), this, SLOT(handleSwitch(const QString &)));
connect(m_cmdLine, SIGNAL(optionFound(const QString &, const QVariant &)), this, SLOT(handleOption(const QString &, const QVariant &)));
connect(m_cmdLine, SIGNAL(paramFound(const QString &, const QVariant &)), this, SLOT(handleParam(const QString &, const QVariant &)));
connect(m_cmdLine, SIGNAL(parseError(const QString &)), this, SLOT(handleError(const QString &)));
if (arg == "--help" || arg == "-h") {
setHelpFlag(true);
return;
}
if (arg == "--version" || arg == "-v") {
setVersionFlag(true);
return;
}
if (arg == "--load-images=yes") {
setAutoLoadImages(true);
continue;
}
if (arg == "--load-images=no") {
setAutoLoadImages(false);
continue;
}
if (arg == "--disk-cache=yes") {
setDiskCacheEnabled(true);
continue;
}
if (arg == "--disk-cache=no") {
setDiskCacheEnabled(false);
continue;
}
if (arg.startsWith("--max-disk-cache-size=")) {
setMaxDiskCacheSize(arg.mid(arg.indexOf("=") + 1).trimmed().toInt());
continue;
}
if (arg == "--ignore-ssl-errors=yes") {
setIgnoreSslErrors(true);
continue;
}
if (arg == "--ignore-ssl-errors=no") {
setIgnoreSslErrors(false);
continue;
}
if (arg == "--local-to-remote-url-access=no") {
setLocalToRemoteUrlAccessEnabled(false);
continue;
}
if (arg == "--local-to-remote-url-access=yes") {
setLocalToRemoteUrlAccessEnabled(true);
continue;
}
if (arg.startsWith("--proxy-type=")) {
setProxyType(arg.mid(13).trimmed());
continue;
}
if (arg.startsWith("--proxy-auth=")){
setProxyAuth(arg.mid(13).trimmed());
continue;
}
if (arg.startsWith("--proxy=")) {
setProxy(arg.mid(8).trimmed());
continue;
}
if (arg.startsWith("--cookies-file=")) {
setCookiesFile(arg.mid(15).trimmed());
continue;
}
if (arg.startsWith("--local-storage-path=")) {
setOfflineStoragePath(arg.mid(21).trimmed());
continue;
}
if (arg.startsWith("--local-storage-quota=")) {
setOfflineStorageDefaultQuota(arg.mid(arg.indexOf("=") + 1).trimmed().toInt());
continue;
}
if (arg.startsWith("--output-encoding=")) {
setOutputEncoding(arg.mid(18).trimmed());
continue;
}
if (arg.startsWith("--script-encoding=")) {
setScriptEncoding(arg.mid(18).trimmed());
continue;
}
if (arg.startsWith("--config=")) {
QString configPath = arg.mid(9).trimmed();
loadJsonFile(configPath);
continue;
}
if (arg.startsWith("--remote-debugger-port=")) {
setDebug(true);
setRemoteDebugPort(arg.mid(23).trimmed().toInt());
continue;
}
if (arg == "--remote-debugger-autorun=yes") {
setRemoteDebugAutorun(true);
continue;
}
if (arg == "--remote-debugger-autorun=no") {
setRemoteDebugAutorun(false);
continue;
}
if (arg == "--web-security=yes") {
setWebSecurityEnabled(true);
continue;
}
if (arg == "--web-security=no") {
setWebSecurityEnabled(false);
continue;
}
if (arg == "--debug=yes") {
setPrintDebugMessages(true);
continue;
}
if (arg == "--debug=no") {
setPrintDebugMessages(false);
continue;
}
if (arg.startsWith("--")) {
setUnknownOption(QString("Unknown option '%1'").arg(arg));
return;
m_cmdLine->setArguments(args);
m_cmdLine->setConfig(flags);
m_cmdLine->parse();
// Inject command line parameters to be picked up by GhostDriver
if (isWebdriverMode()) {
QStringList argsForGhostDriver;
m_scriptFile = "main.js"; //< launch script
argsForGhostDriver << QString("--ip=%1").arg(m_webdriverIp); //< "--ip=IP"
argsForGhostDriver << QString("--port=%1").arg(m_webdriverPort); //< "--port=PORT"
if (!m_webdriverSeleniumGridHub.isEmpty()) {
argsForGhostDriver << QString("--hub=%1").arg(m_webdriverSeleniumGridHub); //< "--hub=SELENIUM_GRID_HUB_URL"
}
// There are no more options at this point.
// The remaining arguments are available for the script.
m_scriptFile = arg;
while (it.hasNext()) {
m_scriptArgs += it.next();
if (!m_webdriverLogFile.isEmpty()) {
argsForGhostDriver << QString("--logFile=%1").arg(m_webdriverLogFile); //< "--logFile=LOG_FILE"
argsForGhostDriver << "--logColor=false"; //< Force no-color-output in Log File
}
argsForGhostDriver << QString("--logLevel=%1").arg(m_webdriverLogLevel); //< "--logLevel=LOG_LEVEL"
// Clear current args and override with those
setScriptArgs(argsForGhostDriver);
}
}
@ -213,7 +171,12 @@ void Config::loadJsonFile(const QString &filePath)
// Add this object to the global scope
webPage.mainFrame()->addToJavaScriptWindowObject("config", this);
// Apply the JSON config settings to this very object
webPage.mainFrame()->evaluateJavaScript(configurator.arg(jsonConfig), QString());
webPage.mainFrame()->evaluateJavaScript(configurator.arg(jsonConfig));
}
QString Config::helpText() const
{
return m_cmdLine->help();
}
bool Config::autoLoadImages() const
@ -287,6 +250,16 @@ void Config::setIgnoreSslErrors(const bool value)
m_ignoreSslErrors = value;
}
bool Config::localUrlAccessEnabled() const
{
return m_localUrlAccessEnabled;
}
void Config::setLocalUrlAccessEnabled(const bool value)
{
m_localUrlAccessEnabled = value;
}
bool Config::localToRemoteUrlAccessEnabled() const
{
return m_localToRemoteUrlAccessEnabled;
@ -323,25 +296,17 @@ void Config::setProxyType(const QString value)
QString Config::proxy() const
{
return proxyHost() + ":" + proxyPort();
return m_proxyHost + ":" + QString::number(m_proxyPort);
}
void Config::setProxy(const QString &value)
{
QString proxyHost = value;
int proxyPort = 1080;
QUrl proxyUrl = QUrl::fromUserInput(value);
if (proxyHost.lastIndexOf(':') > 0) {
bool ok = true;
int port = proxyHost.mid(proxyHost.lastIndexOf(':') + 1).toInt(&ok);
if (ok) {
proxyHost = proxyHost.left(proxyHost.lastIndexOf(':')).trimmed();
proxyPort = port;
}
if (proxyUrl.isValid()) {
setProxyHost(proxyUrl.host());
setProxyPort(proxyUrl.port(1080));
}
setProxyHost(proxyHost);
setProxyPort(proxyPort);
}
void Config::setProxyAuth(const QString &value)
@ -412,6 +377,20 @@ void Config::setScriptEncoding(const QString &value)
m_scriptEncoding = value;
}
QString Config::scriptLanguage() const
{
return m_scriptLanguage;
}
void Config::setScriptLanguage(const QString &value)
{
if (value.isEmpty()) {
return;
}
m_scriptLanguage = value;
}
QString Config::scriptFile() const
{
return m_scriptFile;
@ -482,6 +461,81 @@ void Config::setWebSecurityEnabled(const bool value)
m_webSecurityEnabled = value;
}
void Config::setJavascriptCanOpenWindows(const bool value)
{
m_javascriptCanOpenWindows = value;
}
bool Config::javascriptCanOpenWindows() const
{
return m_javascriptCanOpenWindows;
}
void Config::setJavascriptCanCloseWindows(const bool value)
{
m_javascriptCanCloseWindows = value;
}
bool Config::javascriptCanCloseWindows() const
{
return m_javascriptCanCloseWindows;
}
void Config::setWebdriver(const QString &webdriverConfig)
{
// Parse and validate the configuration
bool isValidPort;
QStringList wdCfg = webdriverConfig.split(':');
if (wdCfg.length() == 1 && wdCfg[0].toInt(&isValidPort) && isValidPort) {
// Only a PORT was provided
m_webdriverPort = wdCfg[0];
} else if(wdCfg.length() == 2 && !wdCfg[0].isEmpty() && wdCfg[1].toInt(&isValidPort) && isValidPort) {
// Both IP and PORT provided
m_webdriverIp = wdCfg[0];
m_webdriverPort = wdCfg[1];
}
}
QString Config::webdriver() const
{
return QString("%1:%2").arg(m_webdriverIp).arg(m_webdriverPort);
}
bool Config::isWebdriverMode() const
{
return !m_webdriverPort.isEmpty();
}
void Config::setWebdriverLogFile(const QString& webdriverLogFile)
{
m_webdriverLogFile = webdriverLogFile;
}
QString Config::webdriverLogFile() const
{
return m_webdriverLogFile;
}
void Config::setWebdriverLogLevel(const QString& webdriverLogLevel)
{
m_webdriverLogLevel = webdriverLogLevel;
}
QString Config::webdriverLogLevel() const
{
return m_webdriverLogLevel;
}
void Config::setWebdriverSeleniumGridHub(const QString &hubUrl)
{
m_webdriverSeleniumGridHub = hubUrl;
}
QString Config::webdriverSeleniumGridHub() const
{
return m_webdriverSeleniumGridHub;
}
// private:
void Config::resetToDefaults()
{
@ -492,6 +546,7 @@ void Config::resetToDefaults()
m_diskCacheEnabled = false;
m_maxDiskCacheSize = -1;
m_ignoreSslErrors = false;
m_localUrlAccessEnabled = true;
m_localToRemoteUrlAccessEnabled = false;
m_outputEncoding = "UTF-8";
m_proxyType = "http";
@ -501,6 +556,7 @@ void Config::resetToDefaults()
m_proxyAuthPass.clear();
m_scriptArgs.clear();
m_scriptEncoding = "UTF-8";
m_scriptLanguage.clear();
m_scriptFile.clear();
m_unknownOption.clear();
m_versionFlag = false;
@ -508,8 +564,36 @@ void Config::resetToDefaults()
m_remoteDebugPort = -1;
m_remoteDebugAutorun = false;
m_webSecurityEnabled = true;
m_javascriptCanOpenWindows = true;
m_javascriptCanCloseWindows = true;
m_helpFlag = false;
m_printDebugMessages = false;
m_sslProtocol = "default";
// Default taken from Chromium 35.0.1916.153
m_sslCiphers = ("ECDHE-ECDSA-AES128-GCM-SHA256"
":ECDHE-RSA-AES128-GCM-SHA256"
":DHE-RSA-AES128-GCM-SHA256"
":ECDHE-ECDSA-AES256-SHA"
":ECDHE-ECDSA-AES128-SHA"
":ECDHE-RSA-AES128-SHA"
":ECDHE-RSA-AES256-SHA"
":ECDHE-ECDSA-RC4-SHA"
":ECDHE-RSA-RC4-SHA"
":DHE-RSA-AES128-SHA"
":DHE-DSS-AES128-SHA"
":DHE-RSA-AES256-SHA"
":AES128-GCM-SHA256"
":AES128-SHA"
":AES256-SHA"
":DES-CBC3-SHA"
":RC4-SHA"
":RC4-MD5");
m_sslCertificatesPath.clear();
m_webdriverIp = QString();
m_webdriverPort = QString();
m_webdriverLogFile = QString();
m_webdriverLogLevel = "INFO";
m_webdriverSeleniumGridHub = QString();
}
void Config::setProxyAuthPass(const QString &value)
@ -551,3 +635,191 @@ void Config::setPrintDebugMessages(const bool value)
{
m_printDebugMessages = value;
}
void Config::handleSwitch(const QString &sw)
{
setHelpFlag(sw == "help");
setVersionFlag(sw == "version");
if (sw == "wd") {
setWebdriver(DEFAULT_WEBDRIVER_CONFIG);
}
}
void Config::handleOption(const QString &option, const QVariant &value)
{
bool boolValue = false;
QStringList booleanFlags;
booleanFlags << "debug";
booleanFlags << "disk-cache";
booleanFlags << "ignore-ssl-errors";
booleanFlags << "load-images";
booleanFlags << "local-url-access";
booleanFlags << "local-to-remote-url-access";
booleanFlags << "remote-debugger-autorun";
booleanFlags << "web-security";
if (booleanFlags.contains(option)) {
if ((value != "true") && (value != "yes") && (value != "false") && (value != "no")) {
setUnknownOption(QString("Invalid values for '%1' option.").arg(option));
return;
}
boolValue = (value == "true") || (value == "yes");
}
if (option == "cookies-file") {
setCookiesFile(value.toString());
}
if (option == "config") {
loadJsonFile(value.toString());
}
if (option == "debug") {
setPrintDebugMessages(boolValue);
}
if (option == "disk-cache") {
setDiskCacheEnabled(boolValue);
}
if (option == "ignore-ssl-errors") {
setIgnoreSslErrors(boolValue);
}
if (option == "load-images") {
setAutoLoadImages(boolValue);
}
if (option == "local-storage-path") {
setOfflineStoragePath(value.toString());
}
if (option == "local-storage-quota") {
setOfflineStorageDefaultQuota(value.toInt());
}
if (option == "local-url-access") {
setLocalUrlAccessEnabled(boolValue);
}
if (option == "local-to-remote-url-access") {
setLocalToRemoteUrlAccessEnabled(boolValue);
}
if (option == "max-disk-cache-size") {
setMaxDiskCacheSize(value.toInt());
}
if (option == "output-encoding") {
setOutputEncoding(value.toString());
}
if (option == "remote-debugger-autorun") {
setRemoteDebugAutorun(boolValue);
}
if (option == "remote-debugger-port") {
setDebug(true);
setRemoteDebugPort(value.toInt());
}
if (option == "proxy") {
setProxy(value.toString());
}
if (option == "proxy-type") {
setProxyType(value.toString());
}
if (option == "proxy-auth") {
setProxyAuth(value.toString());
}
if (option == "script-encoding") {
setScriptEncoding(value.toString());
}
if (option == "script-language") {
setScriptLanguage(value.toString());
}
if (option == "web-security") {
setWebSecurityEnabled(boolValue);
}
if (option == "ssl-protocol") {
setSslProtocol(value.toString());
}
if (option == "ssl-ciphers") {
setSslCiphers(value.toString());
}
if (option == "ssl-certificates-path") {
setSslCertificatesPath(value.toString());
}
if (option == "webdriver") {
setWebdriver(value.toString().length() > 0 ? value.toString() : DEFAULT_WEBDRIVER_CONFIG);
}
if (option == "webdriver-logfile") {
setWebdriverLogFile(value.toString());
}
if (option == "webdriver-loglevel") {
setWebdriverLogLevel(value.toString());
}
if (option == "webdriver-selenium-grid-hub") {
setWebdriverSeleniumGridHub(value.toString());
}
}
void Config::handleParam(const QString& param, const QVariant &value)
{
Q_UNUSED(param);
if (m_scriptFile.isEmpty())
m_scriptFile = value.toString();
else
m_scriptArgs += value.toString();
}
void Config::handleError(const QString &error)
{
setUnknownOption(QString("Error: %1").arg(error));
}
QString Config::sslProtocol() const
{
return m_sslProtocol;
}
void Config::setSslProtocol(const QString& sslProtocolName)
{
m_sslProtocol = sslProtocolName.toLower();
}
QString Config::sslCiphers() const
{
return m_sslCiphers;
}
void Config::setSslCiphers(const QString& sslCiphersName)
{
// OpenSSL cipher strings are case sensitive.
m_sslCiphers = sslCiphersName;
}
QString Config::sslCertificatesPath() const
{
return m_sslCertificatesPath;
}
void Config::setSslCertificatesPath(const QString& sslCertificatesPath)
{
QFileInfo sslPathInfo = QFileInfo(sslCertificatesPath);
if (sslPathInfo.isDir()) {
if (sslCertificatesPath.endsWith('/'))
m_sslCertificatesPath = sslCertificatesPath + "*";
else
m_sslCertificatesPath = sslCertificatesPath + "/*";
} else {
m_sslCertificatesPath = sslCertificatesPath;
}
}

View File

@ -34,14 +34,18 @@
#include <QString>
#include <QStringList>
#include <QNetworkProxy>
#include <QVariant>
class Config: QObject
class QCommandLine;
class Config: public QObject
{
Q_OBJECT
Q_PROPERTY(QString cookiesFile READ cookiesFile WRITE setCookiesFile)
Q_PROPERTY(bool diskCacheEnabled READ diskCacheEnabled WRITE setDiskCacheEnabled)
Q_PROPERTY(int maxDiskCacheSize READ maxDiskCacheSize WRITE setMaxDiskCacheSize)
Q_PROPERTY(bool ignoreSslErrors READ ignoreSslErrors WRITE setIgnoreSslErrors)
Q_PROPERTY(bool localUrlAccessEnabled READ localUrlAccessEnabled WRITE setLocalUrlAccessEnabled)
Q_PROPERTY(bool localToRemoteUrlAccessEnabled READ localToRemoteUrlAccessEnabled WRITE setLocalToRemoteUrlAccessEnabled)
Q_PROPERTY(QString outputEncoding READ outputEncoding WRITE setOutputEncoding)
Q_PROPERTY(QString proxyType READ proxyType WRITE setProxyType)
@ -52,6 +56,15 @@ class Config: QObject
Q_PROPERTY(QString offlineStoragePath READ offlineStoragePath WRITE setOfflineStoragePath)
Q_PROPERTY(int offlineStorageDefaultQuota READ offlineStorageDefaultQuota WRITE setOfflineStorageDefaultQuota)
Q_PROPERTY(bool printDebugMessages READ printDebugMessages WRITE setPrintDebugMessages)
Q_PROPERTY(bool javascriptCanOpenWindows READ javascriptCanOpenWindows WRITE setJavascriptCanOpenWindows)
Q_PROPERTY(bool javascriptCanCloseWindows READ javascriptCanCloseWindows WRITE setJavascriptCanCloseWindows)
Q_PROPERTY(QString sslProtocol READ sslProtocol WRITE setSslProtocol)
Q_PROPERTY(QString sslCiphers READ sslCiphers WRITE setSslCiphers)
Q_PROPERTY(QString sslCertificatesPath READ sslCertificatesPath WRITE setSslCertificatesPath)
Q_PROPERTY(QString webdriver READ webdriver WRITE setWebdriver)
Q_PROPERTY(QString webdriverLogFile READ webdriverLogFile WRITE setWebdriverLogFile)
Q_PROPERTY(QString webdriverLogLevel READ webdriverLogLevel WRITE setWebdriverLogLevel)
Q_PROPERTY(QString webdriverSeleniumGridHub READ webdriverSeleniumGridHub WRITE setWebdriverSeleniumGridHub)
public:
Config(QObject *parent = 0);
@ -60,6 +73,8 @@ public:
void processArgs(const QStringList &args);
void loadJsonFile(const QString &filePath);
QString helpText() const;
bool autoLoadImages() const;
void setAutoLoadImages(const bool value);
@ -81,6 +96,9 @@ public:
bool ignoreSslErrors() const;
void setIgnoreSslErrors(const bool value);
bool localUrlAccessEnabled() const;
void setLocalUrlAccessEnabled(const bool value);
bool localToRemoteUrlAccessEnabled() const;
void setLocalToRemoteUrlAccessEnabled(const bool value);
@ -108,6 +126,9 @@ public:
QString scriptEncoding() const;
void setScriptEncoding(const QString &value);
QString scriptLanguage() const;
void setScriptLanguage(const QString &value);
QString scriptFile() const;
void setScriptFile(const QString &value);
@ -135,6 +156,40 @@ public:
void setPrintDebugMessages(const bool value);
bool printDebugMessages() const;
void setJavascriptCanOpenWindows(const bool value);
bool javascriptCanOpenWindows() const;
void setJavascriptCanCloseWindows(const bool value);
bool javascriptCanCloseWindows() const;
void setSslProtocol(const QString& sslProtocolName);
QString sslProtocol() const;
void setSslCiphers(const QString& sslCiphersName);
QString sslCiphers() const;
void setSslCertificatesPath(const QString& sslCertificatesPath);
QString sslCertificatesPath() const;
void setWebdriver(const QString& webdriverConfig);
QString webdriver() const;
bool isWebdriverMode() const;
void setWebdriverLogFile(const QString& webdriverLogFile);
QString webdriverLogFile() const;
void setWebdriverLogLevel(const QString& webdriverLogLevel);
QString webdriverLogLevel() const;
void setWebdriverSeleniumGridHub(const QString& hubUrl);
QString webdriverSeleniumGridHub() const;
public slots:
void handleSwitch(const QString &sw);
void handleOption(const QString &option, const QVariant &value);
void handleParam(const QString& param, const QVariant &value);
void handleError(const QString &error);
private:
void resetToDefaults();
void setProxyHost(const QString &value);
@ -142,6 +197,7 @@ private:
void setAuthUser(const QString &value);
void setAuthPass(const QString &value);
QCommandLine *m_cmdLine;
bool m_autoLoadImages;
QString m_cookiesFile;
QString m_offlineStoragePath;
@ -149,6 +205,7 @@ private:
bool m_diskCacheEnabled;
int m_maxDiskCacheSize;
bool m_ignoreSslErrors;
bool m_localUrlAccessEnabled;
bool m_localToRemoteUrlAccessEnabled;
QString m_outputEncoding;
QString m_proxyType;
@ -158,6 +215,7 @@ private:
QString m_proxyAuthPass;
QStringList m_scriptArgs;
QString m_scriptEncoding;
QString m_scriptLanguage;
QString m_scriptFile;
QString m_unknownOption;
bool m_versionFlag;
@ -169,6 +227,16 @@ private:
bool m_webSecurityEnabled;
bool m_helpFlag;
bool m_printDebugMessages;
bool m_javascriptCanOpenWindows;
bool m_javascriptCanCloseWindows;
QString m_sslProtocol;
QString m_sslCiphers;
QString m_sslCertificatesPath;
QString m_webdriverIp;
QString m_webdriverPort;
QString m_webdriverLogFile;
QString m_webdriverLogLevel;
QString m_webdriverSeleniumGridHub;
};
#endif // CONFIG_H

View File

@ -32,13 +32,13 @@
#ifndef CONSTS_H
#define CONSTS_H
// Current Version: 1.6.0
#define PHANTOMJS_VERSION_MAJOR 1
#define PHANTOMJS_VERSION_MINOR 6
#define PHANTOMJS_VERSION_MAJOR 2
#define PHANTOMJS_VERSION_MINOR 0
#define PHANTOMJS_VERSION_PATCH 0
#define PHANTOMJS_VERSION_STRING "1.6.0 (development)"
#define PHANTOMJS_VERSION_STRING "2.0.0"
#define COFFEE_SCRIPT_EXTENSION ".coffee"
#define HTTP_HEADER_CONTENT_LENGTH "content-length"
#define HTTP_HEADER_CONTENT_TYPE "content-type"
#define JS_ELEMENT_CLICK "(function (el) { " \
"var ev = document.createEvent('MouseEvents');" \
@ -58,6 +58,12 @@
#define PAGE_SETTINGS_LOCAL_ACCESS_REMOTE "localToRemoteUrlAccessEnabled"
#define PAGE_SETTINGS_USERNAME "userName"
#define PAGE_SETTINGS_PASSWORD "password"
#define PAGE_SETTINGS_MAX_AUTH_ATTEMPTS "maxAuthAttempts"
#define PAGE_SETTINGS_RESOURCE_TIMEOUT "resourceTimeout"
#define PAGE_SETTINGS_WEB_SECURITY_ENABLED "webSecurityEnabled"
#define PAGE_SETTINGS_JS_CAN_OPEN_WINDOWS "javascriptCanOpenWindows"
#define PAGE_SETTINGS_JS_CAN_CLOSE_WINDOWS "javascriptCanCloseWindows"
#define DEFAULT_WEBDRIVER_CONFIG "127.0.0.1:8910"
#endif // CONSTS_H

View File

@ -2,6 +2,7 @@
This file is part of the PhantomJS project from Ofi Labs.
Copyright (C) 2011 Ariya Hidayat <ariya.hidayat@gmail.com>
Copyright (C) 2012 Ivan De Marino <ivan.de.marino@gmail.com>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
@ -27,44 +28,480 @@
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "phantom.h"
#include "config.h"
#include "cookiejar.h"
#include <QDateTime>
#include <QSettings>
#include <QStringList>
#include <QTimer>
CookieJar::CookieJar(QString cookiesFile)
: QNetworkCookieJar()
#define COOKIE_JAR_VERSION 1
// Operators needed for Cookie Serialization
QT_BEGIN_NAMESPACE
QDataStream &operator<<(QDataStream &stream, const QList<QNetworkCookie> &list)
{
m_cookiesFile = cookiesFile;
stream << COOKIE_JAR_VERSION;
stream << quint32(list.size());
for (int i = 0; i < list.size(); ++i)
stream << list.at(i).toRawForm();
return stream;
}
bool CookieJar::setCookiesFromUrl(const QList<QNetworkCookie> & cookieList, const QUrl & url)
QDataStream &operator>>(QDataStream &stream, QList<QNetworkCookie> &list)
{
QSettings settings(m_cookiesFile, QSettings::IniFormat);
list.clear();
settings.beginGroup(url.host());
for (QList<QNetworkCookie>::const_iterator i = cookieList.begin(); i != cookieList.end(); i++) {
settings.setValue((*i).name(), QString((*i).value()));
quint32 version;
stream >> version;
if (version != COOKIE_JAR_VERSION)
return stream;
quint32 count;
stream >> count;
for(quint32 i = 0; i < count; ++i)
{
QByteArray value;
stream >> value;
QList<QNetworkCookie> newCookies = QNetworkCookie::parseCookies(value);
if (newCookies.count() == 0 && value.length() != 0) {
qWarning() << "CookieJar: Unable to parse saved cookie:" << value;
}
for (int j = 0; j < newCookies.count(); ++j)
list.append(newCookies.at(j));
if (stream.atEnd())
break;
}
settings.sync();
return true;
return stream;
}
QT_END_NAMESPACE
QList<QNetworkCookie> CookieJar::cookiesForUrl(const QUrl & url) const
// public:
CookieJar::CookieJar(QString cookiesFile, QObject *parent)
: QNetworkCookieJar(parent)
, m_enabled(true)
{
QSettings settings(m_cookiesFile, QSettings::IniFormat);
QList<QNetworkCookie> cookieList;
settings.beginGroup(url.host());
QStringList keys = settings.childKeys();
for (QStringList::iterator i = keys.begin(); i != keys.end(); i++) {
cookieList.push_back(QNetworkCookie((*i).toLocal8Bit(), settings.value(*i).toByteArray()));
if (cookiesFile == "") {
m_cookieStorage = 0;
qDebug() << "CookieJar - Created but will not store cookies (use option '--cookies-file=<filename>' to enable persistent cookie storage)";
} else {
m_cookieStorage = new QSettings(cookiesFile, QSettings::IniFormat, this);
load();
qDebug() << "CookieJar - Created and will store cookies in:" << cookiesFile;
}
return cookieList;
}
// private:
CookieJar::~CookieJar()
{
// On destruction, before saving, clear all the session cookies
purgeSessionCookies();
save();
}
bool CookieJar::setCookiesFromUrl(const QList<QNetworkCookie> & cookieList, const QUrl &url)
{
// Update cookies in memory
if (isEnabled()) {
QNetworkCookieJar::setCookiesFromUrl(cookieList, url);
save();
}
// No changes occurred
return false;
}
QList<QNetworkCookie> CookieJar::cookiesForUrl(const QUrl &url) const
{
if (isEnabled()) {
return QNetworkCookieJar::cookiesForUrl(url);
}
// The CookieJar is disabled: don't return any cookie
return QList<QNetworkCookie>();
}
bool CookieJar::addCookie(const QNetworkCookie &cookie, const QString &url)
{
if (isEnabled() && (!url.isEmpty() || !cookie.domain().isEmpty())) {
// Save a single cookie
setCookiesFromUrl(
QList<QNetworkCookie>() << cookie, //< unfortunately, "setCookiesFromUrl" requires a list
!url.isEmpty() ?
url : //< use given URL
QString( //< mock-up a URL
(cookie.isSecure() ? "https://" : "http://") + //< URL protocol
QString(cookie.domain().startsWith('.') ? "www" : "") + cookie.domain() + //< URL domain
(cookie.path().isEmpty() ? "/" : cookie.path()))); //< URL path
// Return "true" if the cookie was really set
if (contains(cookie)) {
return true;
}
qDebug() << "CookieJar - Rejected Cookie" << cookie.toRawForm();
return false;
}
return false;
}
void CookieJar::addCookie(const QVariantMap &cookie)
{
addCookieFromMap(cookie);
}
bool CookieJar::addCookieFromMap(const QVariantMap &cookie, const QString &url)
{
QNetworkCookie newCookie;
// The cookie must have a non-empty "name" and a "value"
if (!cookie["name"].isNull() && !cookie["name"].toString().isEmpty() && !cookie["value"].isNull()) {
// Name & Value
newCookie.setName(cookie["name"].toByteArray());
newCookie.setValue(cookie["value"].toByteArray());
// Domain, if provided
if (!cookie["domain"].isNull() && !cookie["domain"].toString().isEmpty()) {
newCookie.setDomain(cookie["domain"].toString());
}
// Path, if provided
if (!cookie["path"].isNull() || !cookie["path"].toString().isEmpty()) {
newCookie.setPath(cookie["path"].toString());
}
// HttpOnly, false by default
newCookie.setHttpOnly(cookie["httponly"].isNull() ? false : cookie["httponly"].toBool());
// Secure, false by default
newCookie.setSecure(cookie["secure"].isNull() ? false : cookie["secure"].toBool());
// Expiration Date, if provided, giving priority to "expires" over "expiry"
QVariant expiresVar;
if (!cookie["expires"].isNull()) {
expiresVar = cookie["expires"];
} else if (!cookie["expiry"].isNull()) {
expiresVar = cookie["expiry"];
}
if (expiresVar.isValid()) {
QDateTime expirationDate;
if (expiresVar.type() == QVariant::String) {
// Set cookie expire date via "classic" string format
QString datetime = expiresVar.toString().replace(" GMT", "");
expirationDate = QDateTime::fromString(datetime, "ddd, dd MMM yyyy hh:mm:ss");
} else if (expiresVar.type() == QVariant::Double){
// Set cookie expire date via "number of seconds since epoch"
// NOTE: Every JS number is a Double.
// @see http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf
expirationDate = QDateTime::fromMSecsSinceEpoch(expiresVar.toLongLong());
}
if (expirationDate.isValid()) {
newCookie.setExpirationDate(expirationDate);
}
}
return addCookie(newCookie, url);
}
return false;
}
bool CookieJar::addCookies(const QList<QNetworkCookie> &cookiesList, const QString &url)
{
bool added = false;
for (int i = cookiesList.length() -1; i >=0; --i) {
if (addCookie(cookiesList.at(i), url)) {
// change it to "true" if at least 1 cookie was set
added = true;
}
}
return added;
}
bool CookieJar::addCookiesFromMap(const QVariantList &cookiesList, const QString &url)
{
bool added = false;
for (int i = cookiesList.length() -1; i >= 0; --i) {
if (addCookieFromMap(cookiesList.at(i).toMap(), url)) {
// change it to "true" if at least 1 cookie was set
added = true;
}
}
return added;
}
QList<QNetworkCookie> CookieJar::cookies(const QString &url) const
{
if (url.isEmpty()) {
// No url provided: return all the cookies in this CookieJar
return allCookies();
} else {
// Return ONLY the cookies that match this URL
return cookiesForUrl(url);
}
}
QVariantList CookieJar::cookiesToMap(const QString &url) const
{
QVariantList result;
QNetworkCookie c;
QVariantMap cookie;
QList<QNetworkCookie> cookiesList = cookies(url);
for (int i = cookiesList.length() -1; i >= 0; --i) {
c = cookiesList.at(i);
cookie["domain"] = QVariant(c.domain());
cookie["name"] = QVariant(QString(c.name()));
cookie["value"] = QVariant(QString(c.value()));
cookie["path"] = (c.path().isNull() || c.path().isEmpty()) ? QVariant("/") : QVariant(c.path());
cookie["httponly"] = QVariant(c.isHttpOnly());
cookie["secure"] = QVariant(c.isSecure());
if (c.expirationDate().isValid()) {
cookie["expires"] = QVariant(QString(c.expirationDate().toString("ddd, dd MMM yyyy hh:mm:ss")).append(" GMT"));
cookie["expiry"] = QVariant(c.expirationDate().toMSecsSinceEpoch() / 1000);
}
result.append(cookie);
}
return result;
}
QNetworkCookie CookieJar::cookie(const QString &name, const QString &url) const
{
QList<QNetworkCookie> cookiesList = cookies(url);
for (int i = cookiesList.length() -1; i >= 0; --i) {
if (cookiesList.at(i).name() == name) {
return cookiesList.at(i);
}
}
return QNetworkCookie();
}
QVariantMap CookieJar::cookieToMap(const QString &name, const QString &url) const
{
QVariantMap cookie;
QVariantList cookiesList = cookiesToMap(url);
for (int i = cookiesList.length() -1; i >= 0; --i) {
cookie = cookiesList.at(i).toMap();
if (cookie["name"].toString() == name) {
return cookie;
}
}
return QVariantMap();
}
bool CookieJar::deleteCookie(const QString &name, const QString &url)
{
bool deleted = false;
if (isEnabled()) {
// NOTE: This code has been written in an "extended form" to make it
// easy to understand. Surely this could be "shrinked", but it
// would probably look uglier.
QList<QNetworkCookie> cookiesListAll;
if (url.isEmpty()) {
if (name.isEmpty()) { //< Neither "name" or "url" provided
// This method has been used wrong:
// "redirecting" to the right method for the job
clearCookies();
} else { //< Only "name" provided
// Delete all cookies with the given name from the CookieJar
cookiesListAll = allCookies();
for (int i = cookiesListAll.length() -1; i >= 0; --i) {
if (cookiesListAll.at(i).name() == name) {
// Remove this cookie
qDebug() << "CookieJar - Deleted" << cookiesListAll.at(i).toRawForm();
cookiesListAll.removeAt(i);
deleted = true;
}
}
}
} else {
// Delete cookie(s) from the ones visible to the given "url".
// Use the "name" to delete only the right one, otherwise all of them.
QList<QNetworkCookie> cookiesListUrl = cookies(url);
cookiesListAll = allCookies();
for (int i = cookiesListAll.length() -1; i >= 0; --i) {
if (cookiesListUrl.contains(cookiesListAll.at(i)) && //< if it part of the set of cookies visible at URL
(cookiesListAll.at(i).name() == name || name.isEmpty())) { //< and if the name matches, or no name provided
// Remove this cookie
qDebug() << "CookieJar - Deleted" << cookiesListAll.at(i).toRawForm();
cookiesListAll.removeAt(i);
deleted = true;
if (!name.isEmpty()) {
// Only one cookie was supposed to be deleted: we are done here!
break;
}
}
}
}
// Put back the remaining cookies
setAllCookies(cookiesListAll);
}
return deleted;
}
bool CookieJar::deleteCookies(const QString &url)
{
if (isEnabled()) {
if (url.isEmpty()) {
// No URL provided: delete ALL the cookies in the CookieJar
clearCookies();
return true;
}
// No cookie name provided: delete all the cookies visible by this URL
qDebug() << "Delete all cookies for URL:" << url;
return deleteCookie("", url);
}
return false;
}
void CookieJar::clearCookies()
{
if (isEnabled()) {
setAllCookies(QList<QNetworkCookie>());
}
}
void CookieJar::enable()
{
m_enabled = true;
}
void CookieJar::disable()
{
m_enabled = false;
}
bool CookieJar::isEnabled() const
{
return m_enabled;
}
void CookieJar::close()
{
deleteLater();
}
// private:
bool CookieJar::purgeExpiredCookies()
{
QList<QNetworkCookie> cookiesList = allCookies();
// If empty, there is nothing to purge
if (cookiesList.isEmpty()) {
return false;
}
// Check if any cookie has expired
int prePurgeCookiesCount = cookiesList.count();
QDateTime now = QDateTime::currentDateTime();
for (int i = cookiesList.count() - 1; i >= 0; --i) {
if (!cookiesList.at(i).isSessionCookie() && cookiesList.at(i).expirationDate() < now) {
qDebug() << "CookieJar - Purged (expired)" << cookiesList.at(i).toRawForm();
cookiesList.removeAt(i);
}
}
// Set cookies and returns "true" if at least 1 cookie expired and has been removed
if (prePurgeCookiesCount != cookiesList.count()) {
setAllCookies(cookiesList);
return true;
}
return false;
}
bool CookieJar::purgeSessionCookies()
{
QList<QNetworkCookie> cookiesList = allCookies();
// If empty, there is nothing to purge
if (cookiesList.isEmpty()) {
return false;
}
// Check if any cookie has expired
int prePurgeCookiesCount = cookiesList.count();
for (int i = cookiesList.count() - 1; i >= 0; --i) {
if (cookiesList.at(i).isSessionCookie() || !cookiesList.at(i).expirationDate().isValid() || cookiesList.at(i).expirationDate().isNull()) {
qDebug() << "CookieJar - Purged (session)" << cookiesList.at(i).toRawForm();
cookiesList.removeAt(i);
}
}
// Set cookies and returns "true" if at least 1 session cookie was found and removed
if (prePurgeCookiesCount != cookiesList.count()) {
setAllCookies(cookiesList);
return true;
}
return false;
}
void CookieJar::save()
{
if (isEnabled()) {
// Get rid of all the Cookies that have expired
purgeExpiredCookies();
#ifndef QT_NO_DEBUG_OUTPUT
foreach (QNetworkCookie cookie, allCookies()) {
qDebug() << "CookieJar - Saved" << cookie.toRawForm();
}
#endif
// Store cookies
if (m_cookieStorage) {
m_cookieStorage->setValue(QLatin1String("cookies"), QVariant::fromValue<QList<QNetworkCookie> >(allCookies()));
}
}
}
void CookieJar::load()
{
if (isEnabled()) {
// Register a "StreamOperator" for this Meta Type, so we can easily serialize/deserialize the cookies
qRegisterMetaTypeStreamOperators<QList<QNetworkCookie> >("QList<QNetworkCookie>");
// Load all the cookies
if (m_cookieStorage) {
setAllCookies(qvariant_cast<QList<QNetworkCookie> >(m_cookieStorage->value(QLatin1String("cookies"))));
}
// If any cookie has expired since last execution, purge and save before going any further
if (purgeExpiredCookies()) {
save();
}
#ifndef QT_NO_DEBUG_OUTPUT
foreach (QNetworkCookie cookie, allCookies()) {
qDebug() << "CookieJar - Loaded" << cookie.toRawForm();
}
#endif
}
}
bool CookieJar::contains(const QNetworkCookie &cookie) const
{
QList<QNetworkCookie> cookiesList = allCookies();
for (int i = cookiesList.length() -1; i >= 0; --i) {
if (cookie.name() == cookiesList.at(i).name() &&
cookie.value() == cookiesList.at(i).value() &&
(cookie.domain().isEmpty() || cookiesList.at(i).domain().prepend('.').endsWith(cookie.domain())) &&
(cookie.path().isEmpty() || cookiesList.at(i).path() == cookie.path()) &&
cookie.isSecure() == cookiesList.at(i).isSecure() &&
cookie.isHttpOnly() == cookiesList.at(i).isHttpOnly() &&
cookie.expirationDate().toMSecsSinceEpoch() == cookiesList.at(i).expirationDate().toMSecsSinceEpoch()
) {
return true;
}
}
return false;
}

View File

@ -2,6 +2,7 @@
This file is part of the PhantomJS project from Ofi Labs.
Copyright (C) 2011 Ariya Hidayat <ariya.hidayat@gmail.com>
Copyright (C) 2012 Ivan De Marino <ivan.de.marino@gmail.com>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
@ -30,18 +31,61 @@
#ifndef COOKIEJAR_H
#define COOKIEJAR_H
#include <QSettings>
#include <QNetworkCookie>
#include <QNetworkCookieJar>
#include <QVariantList>
#include <QVariantMap>
class CookieJar: public QNetworkCookieJar
{
private:
QString m_cookiesFile;
Q_OBJECT
Q_PROPERTY(QVariantList cookies READ cookiesToMap WRITE addCookiesFromMap)
public:
CookieJar(QString cookiesFile);
CookieJar(QString cookiesFile, QObject *parent = NULL);
virtual ~CookieJar();
bool setCookiesFromUrl(const QList<QNetworkCookie> & cookieList, const QUrl & url);
bool setCookiesFromUrl(const QList<QNetworkCookie> &cookieList, const QUrl & url);
QList<QNetworkCookie> cookiesForUrl (const QUrl & url) const;
bool addCookie(const QNetworkCookie &cookie, const QString &url = QString());
bool addCookies(const QList<QNetworkCookie> &cookiesList, const QString &url = QString());
QList<QNetworkCookie> cookies(const QString &url = QString()) const;
QNetworkCookie cookie(const QString &name, const QString &url = QString()) const;
using QNetworkCookieJar::deleteCookie;
bool deleteCookies(const QString &url = QString());
void enable();
void disable();
bool isEnabled() const;
public slots:
void addCookie(const QVariantMap &cookie);
bool addCookieFromMap(const QVariantMap &cookie, const QString &url = QString());
bool addCookiesFromMap(const QVariantList &cookiesList, const QString &url = QString());
QVariantList cookiesToMap(const QString &url = QString()) const;
QVariantMap cookieToMap(const QString &name, const QString &url = QString()) const;
bool deleteCookie(const QString &name, const QString &url = QString());
void clearCookies();
void close();
private slots:
bool purgeExpiredCookies();
bool purgeSessionCookies();
void save();
void load();
private:
bool contains(const QNetworkCookie &cookie) const;
private:
QSettings *m_cookieStorage;
bool m_enabled;
};
#endif // COOKIEJAR_H

199
src/crashdump.cpp Normal file
View File

@ -0,0 +1,199 @@
/*
This file is part of the PhantomJS project from Ofi Labs.
Copyright (C) 2011 Ariya Hidayat <ariya.hidayat@gmail.com>
Copyright (C) 2011 Ivan De Marino <ivan.de.marino@gmail.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 <organization> 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 <COPYRIGHT HOLDER> 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.
*/
#include "crashdump.h"
#include <QtGlobal>
#include <QString>
#include <QByteArray>
#include <exception>
#include <cstdlib>
#ifdef Q_OS_LINUX
#include "client/linux/handler/exception_handler.h"
#define HAVE_BREAKPAD
#define EHC_EXTRA_ARGS true
#define MDC_PATH_ARG const char*
#define MDC_EXTRA_ARGS void*
#endif
#ifdef Q_OS_MAC
#include "client/mac/handler/exception_handler.h"
#define HAVE_BREAKPAD
#define EHC_EXTRA_ARGS true, NULL
#define MDC_PATH_ARG const char*
#define MDC_EXTRA_ARGS void*
#endif
#ifdef Q_OS_WIN32
#include "client/windows/handler/exception_handler.h"
#define HAVE_BREAKPAD
#define EHC_EXTRA_ARGS BreakpadEH::HANDLER_ALL
#define MDC_PATH_ARG const wchar_t*
#define MDC_EXTRA_ARGS void*, EXCEPTION_POINTERS*, MDRawAssertionInfo*
#endif
#ifdef HAVE_BREAKPAD
// This is not just 'using google_breakpad::ExceptionHandler' because
// one of the headers included by exception_handler.h on MacOS defines
// a typedef name 'ExceptionHandler' in the global namespace, and
// (apparently) a using-directive doesn't completely mask that.
typedef google_breakpad::ExceptionHandler BreakpadEH;
#ifdef Q_OS_WIN32
// qgetenv doesn't handle environment variables containing Unicode
// characters very well. Breakpad-for-Windows works exclusively with
// Unicode paths anyway, so we use the native API to retrieve %TEMP%
// as Unicode. This code based upon qglobal.cpp::qgetenv.
static QString
q_wgetenv(const wchar_t *varName)
{
size_t requiredSize;
_wgetenv_s(&requiredSize, 0, 0, varName);
if (requiredSize == 0 || requiredSize > size_t(INT_MAX / sizeof(wchar_t)))
return QString();
// Unfortunately it does not appear to be safe to pass QString::data()
// to a Windows API that expects wchar_t*. QChar is too different.
// We have to employ a scratch buffer. Limiting the length to
// INT_MAX / sizeof(wchar_t), above, ensures that the multiplication
// here cannot overflow.
wchar_t *buffer = (wchar_t *)malloc(requiredSize * sizeof(wchar_t));
if (!buffer)
return QString();
// requiredSize includes the terminating null, which we don't want.
// The range-check above also ensures that the conversion to int here
// does not overflow.
_wgetenv_s(&requiredSize, buffer, requiredSize, varName);
Q_ASSERT(buffer[requiredSize-1] == L'\0');
QString ret = QString::fromWCharArray(buffer, int(requiredSize - 1));
free(buffer);
return ret;
}
#endif
//
// Crash messages.
//
#ifdef Q_OS_WIN32
#define CRASH_DUMP_FMT "%ls\\%ls.dmp"
#define CRASH_DIR_FMT "%%TEMP%% (%ls)"
#else
#define CRASH_DUMP_FMT "%s/%s.dmp"
#define CRASH_DIR_FMT "$TMPDIR (%s)"
#endif
#define CRASH_MESSAGE_BASE \
"PhantomJS has crashed. Please read the crash reporting guide at\n" \
"<http://phantomjs.org/crash-reporting.html> and file a bug report at\n" \
"<https://github.com/ariya/phantomjs/issues/new>.\n"
#define CRASH_MESSAGE_HAVE_DUMP \
CRASH_MESSAGE_BASE \
"Please attach the crash dump file:\n " CRASH_DUMP_FMT "\n"
#define CRASH_MESSAGE_NO_DUMP \
CRASH_MESSAGE_BASE \
"Unfortunately, no crash dump is available.\n" \
"(Is " CRASH_DIR_FMT " a directory you cannot write?)\n"
static bool minidumpCallback(MDC_PATH_ARG dump_path,
MDC_PATH_ARG minidump_id,
MDC_EXTRA_ARGS,
bool succeeded)
{
if (succeeded)
fprintf(stderr, CRASH_MESSAGE_HAVE_DUMP, dump_path, minidump_id);
else
fprintf(stderr, CRASH_MESSAGE_NO_DUMP, dump_path);
return succeeded;
}
static BreakpadEH *initBreakpad()
{
// On all platforms, Breakpad can be disabled by setting the
// environment variable PHANTOMJS_DISABLE_CRASH_DUMPS to any
// non-empty value. This is not a command line argument because
// we want to initialize Breakpad before parsing the command line.
if (!qEnvironmentVariableIsEmpty("PHANTOMJS_DISABLE_CRASH_DUMPS"))
return 0;
// Windows and Unix have different conventions for the environment
// variable naming the directory that should hold scratch files.
#ifdef Q_OS_WIN32
std::wstring dumpPath(L".");
QString varbuf = q_wgetenv(L"TEMP");
if (!varbuf.isEmpty())
dumpPath = varbuf.toStdWString();
#else
std::string dumpPath("/tmp");
QByteArray varbuf = qgetenv("TMPDIR");
if (!varbuf.isEmpty())
dumpPath = varbuf.constData();
#endif
return new BreakpadEH(dumpPath, NULL, minidumpCallback, NULL,
EHC_EXTRA_ARGS);
}
#else // no HAVE_BREAKPAD
#define initBreakpad() NULL
#endif
// Qt, QtWebkit, and PhantomJS mostly don't make use of C++ exceptions,
// so in the rare cases where an exception does get thrown, it tends
// to pass all the way up the stack and cause the C++ runtime to call
// std::terminate(). The default std::terminate() handler in some
// C++ runtimes tries to print details of the exception or maybe even
// a stack trace. Breakpad does a better job of this.
//
// Worse, if the exception is bad_alloc, thrown because we've run into
// a system-imposed hard upper limit on memory allocation, a clever
// terminate handler like that may itself perform more memory allocation,
// which will throw another bad_alloc, and cause a recursive call to
// terminate. In some cases this may happen several times before the
// process finally dies.
//
// Short-circuit all this mess by forcing the terminate handler to
// be plain old std::abort, which will invoke Breakpad if it's active
// and crash promptly if not.
CrashHandler::CrashHandler()
: old_terminate_handler(std::set_terminate(std::abort)),
eh(initBreakpad())
{}
CrashHandler::~CrashHandler()
{
delete eh;
std::set_terminate(old_terminate_handler);
}

Some files were not shown because too many files have changed in this diff Show More