ariya/phantomjs

Unsafe JavaScript attempt to access frame in 1.9.8

artjomb opened this issue ยท 55 comments

I see some questions on StackOverflow with Unsafe JavaScript attempt to access frame notices with the new PhantomJS version 1.9.8. I have created a small sample script

var page = require('webpage').create();

// notices disappear when removing the event handler
page.onConsoleMessage = function(msg) {
    console.log(msg.length);
};

page.open("http://google.com/", function(status) {
    page.evaluate(function() {
        function embedImg(org) {
            var img = new Image();
            img.src = org.src;
            img.onload = function() {
                var canvas = document.createElement("canvas");
                canvas.width = this.width;
                canvas.height = this.height;

                var ctx = canvas.getContext("2d");
                ctx.drawImage(this, 0, 0);

                var dataURL = canvas.toDataURL("image/png");

                org.src = dataURL;
                // notices disappear when removing the console.log
                console.log(dataURL);
            }
        }
        var imgs = document.getElementsByTagName("img");
        for (var index=0; index < imgs.length; index++) {
            embedImg(imgs[index]);
        }
    });
    // notices disappear when 'asynchronizing' exit using setTimeout even with a 0 timeout
    //setTimeout(function(){
        phantom.exit()
    //}, 0);
});

This didn't happen in 1.9.7.

Complete error

Unsafe JavaScript attempt to access frame with URL  from frame with URL file://test46_google.js. Domains, protocols andports must match.

Unsafe JavaScript attempt to access frame with URL  from frame with URL file://test46_google.js. Domains, protocols andports must match.

Unsafe JavaScript attempt to access frame with URL about:blank from frame with URL file://test46_google.js. Domains, protocols and ports must match.

Unsafe JavaScript attempt to access frame with URL about:blank from frame with URL file://test46_google.js. Domains, protocols and ports must match.

Unsafe JavaScript attempt to access frame with URL about:blank from frame with URL file://test46_google.js. Domains, protocols and ports must match.

Unsafe JavaScript attempt to access frame with URL about:blank from frame with URL file://test46_google.js. Domains, protocols and ports must match.

Unsafe JavaScript attempt to access frame with URL about:blank from frame with URL file://test46_google.js. Domains, protocols and ports must match.

Unsafe JavaScript attempt to access frame with URL about:blank from frame with URL file://test46_google.js. Domains, protocols and ports must match.

Unsafe JavaScript attempt to access frame with URL about:blank from frame with URL file://test46_google.js. Domains, protocols and ports must match.

Unsafe JavaScript attempt to access frame with URL about:blank from frame with URL file://test46_google.js. Domains, protocols and ports must match.

Unsafe JavaScript attempt to access frame with URL about:blank from frame with URL file://test46_google.js. Domains, protocols and ports must match.

This is the smallest code that reproduces this for CasperJS (run as casperjs test script.js):

casper.test.begin('test unsafe', function(test) {
    test.done();
});

I suspect this happens when PhantomJS tries to exit, but there is currently data exchange between page context and outer context. I've also searched for the error string in the sources here on github, but couldn't find any reference for this notice. The notices don't go way when PhantomJS is run with --web-security=false and similar.

The setTimeout work-around only worked for me if I closed the page first. So I came up with this wrapper function that also halts the script as expected:

function exit(code) {
    if (page) page.close();
    setTimeout(function(){ phantom.exit(code); }, 0);
    phantom.onError = function(){};
    throw new Error('');
}

+1
waiting for fix

+1

@vitallium : would you mind to ping CasperJs team when the issue is resolved ?
We may want to add the (probably) last 1.9.x release of phantomjs support for our 1.1 release.

Sorry to not help, I'm not very easy with C++, thank you for the great job you have done ๐Ÿ‘

a short example of this problem.

If I copy and paste this code in the phantomjs "interpret"

var webPage = require('webpage');
var page = webPage.create();

page.open("http://www.google.com", function start(status) {
  page.render('google_home.jpeg', {format: 'jpeg', quality: '100'});
  phantom.exit();
});

I get this

Unsafe JavaScript attempt to access frame with URL about:blank from frame with URL file:. Domains, protocols and ports must match.

Unsafe JavaScript attempt to access frame with URL about:blank from frame with URL file:. Domains, protocols and ports must match.

Fix in 1.9 branch (though it won't be part of any release).

@ariya thanks.
For the casperJS project, this means at this point:
we support from 1.8.2 to 1.9.7 and master branch.

Am I correct considering this bug resolution ?
Is this fix ported to 2.x future release ?

Regards

I don't think this bug applies to PhantomJS 2. But better double check and verify it.

Not sure how critical it is for 1.9.8 to be excluded from CasperJS. Despite it's being annoying, the message is only a warning and AFAICS doesn't cause any functionality regression. Does the workaround with async exit solve it for CasperJS?

The bug does break my use cases for CasperJS (where I'm managing scripts through stdio from another app, and since the message is submitted to stdout, not even stderr, it breaks havoc), and forced me to rollback to 1.9.7.

As far as I'm concerned for my app, I agree with @mickaelandrieu, CasperJS simply does not work with PhantomJS 1.9.8.

The CasperJS test suite is broken with 1.9.8 release of phantomjs but I will test the workaround.
I prefer "not exclude" a release of phantomjs, need to think about it ...

Thanks for your comment @jsotuyod

Are there binary packages of the fixed 1.9 branch available? Or do we need to build it ourselves if we want to use it?

gniw commented

I use CasperJS 1.1.0-beta3, and PhantomJS 1.9.8 are installed with homebrew.
It seems that the problem still exist.

casper.test.begin 'open google', (test)->
  casper
    .start 'https://www.google.com', ->
      test.assertTitle 'Google'
    .run ->
      test.done()

It works, but CasperJS (PhantomJS) says "Unsafe Javascript attempt....".

# open google
PASS Page title is: "Google"
PASS 1 test executed in 0.915s, 1 passed, 0 failed, 0 dubious, 0 skipped.
Unsafe JavaScript attempt to access frame with URL about:blank from frame with URL file. Domains, protocols and ports must match.

So, I changed my code just a little like below.

casper.test.begin 'open google', (test)->
  casper
    .start 'https://www.google.com', ->
      test.assertTitle 'Google'
    .run ->
      setTimeout ->
        test.done()
        phantom.exit()
      , 0

After that, I got no error.

# open google
PASS Page title is: "Google"

If I should have posted on CasperJS issue, please let me know.

Same problem here. We rely on STDOUT and STDERR from our Casper scripts and this bug hoses that. We'll be forced to stick to 1.9.7 if this fix doesn't make it into a future 1.9 release (unless a reliable workaround for Casper is found)

I tried to use DocBrown's exit code, but got errors related to the page variable not being set, so I whittled it down to this:

function exit(code) {
setTimeout(function(){ phantom.exit(code); }, 0);
phantom.onError = function(){};
}

and I call exit, with exit(0) after the last test.done(); call in the casperjs script.

I hope this helps someone else.

There is something odd about doing this:

If I try this script:

casper.test.begin("Hello, Test!", 1, function(test) {
test.assert(true);
test.done();
setTimeout(function(){ phantom.exit(code); }, 0);
phantom.onError = function(){};
});

function exit(code) {
setTimeout(function(){ phantom.exit(code); }, 0);
phantom.onError = function(){};
}

which just calls the two lines in exit but inline test.begin() function, I still get the "Unsafe...." error, whereas calling the exit(0); suppresses the error, maybe someone can explain that?

So to be explicit:

// hello-test.js
casper.test.begin("Hello, Test!", 1, function(test) {
test.assert(true);
test.done();
exit(0);
});

function exit(code) {
setTimeout(function(){ phantom.exit(code); }, 0);
phantom.onError = function(){};
}

suppresses the error.

Is this fixed?? I use casperjs and phantomjs v 1.9.8 and still get the
Unsafe JavaScript attempt to access frame with URL about:blank from frame with URL

hi @ecuan, did you use casperjs master branch ?

can you post an issue with a test, I will take a look tomorrow.

Hey @MikeMcQuaid actually i have 1.1.0-beta3 version... that's the one that gets installed with npm. I'll try with master thanks!

For anyone stumbling onto this after Googling, I was able to resolve this issue on Mac OSX by using the latest PhantomJS 2 build, installing the latest CasperJS master, and patching CasperJS's bootstrap.js. For convenience, I've documented all the steps below.

Install PhantomJS 2.0

Download the latest PhantomJS 2.0 binary for Mac OSX from eugene1g's releases. (Or build it yourself if you have 30 minutes to wait.)

https://github.com/eugene1g/phantomjs/releases

Copy that phantomjs into your /usr/local/bin/ directory.

You should see the following in Terminal:

$ phantomjs --version
2.0.0

Install CasperJS from master branch

Per http://docs.casperjs.org/en/1.1-beta1/installation.html#installing-from-git

$ cd /usr/local/Cellar
$ git clone git://github.com/n1k0/casperjs.git
$ cd casperjs
$ ln -sf `pwd`/bin/casperjs /usr/local/bin/casperjs

Patch CasperJS bootstrap.js

AS OF 2015-02-12, this step is unnecessary, as it was patched in the master branch of CasperJS.

Per https://groups.google.com/forum/#!topic/casperjs/_Rw7Rm6CRIQ

In the /usr/local/Cellar/casperjs/bin/bootstrap.js file, paste the following 4 lines at the top of the file:

var system = require('system');
var argsdeprecated = system.args;
argsdeprecated.shift();
phantom.args = argsdeprecated;

Test that it works!

$ casperjs
Warning PhantomJS v2.0 not yet released. There will not be any official support for any bugs until stable version is released!
CasperJS version 1.1.0-beta3 at /usr/local/Cellar/casperjs, using phantomjs version 2.0.0

I fixed this bug by downgrading to 1.9.7

Hey @rscheuermann , I think your patch solves a different problem.

Yes, to be clear, it's not "my" patch. Credit goes to Charlie. But you're right, that patch allows PhantomJS 2 to work on the latest master build of CasperJS. Which, coincidentally, was the only way I was able to resolve the "Unsafe JavaScript attempt to access frame" problem I had.

@rscheuermann this is now merged in master branch, which I guess work with PhantomJS 2 => casperjs/casperjs@d211035

We need a build for linux to be able to add PhantomJS2 to the travis stack, but afaik the linux build fails 'cause of libicu issue.

@mickaelandrieu That's excellent. I've revised my comment with a note.

Since this doesn't sound like it's going to be fixed in any release, I found the easiest way to solve it is to build from source and cherry-pick the commit that fixes it:

$ git clone git://github.com/ariya/phantomjs.git
$ cd phantomjs
$ git checkout 1.9.8
$ git reset --hard
$ git cherry-pick 016ae98b2b84ff972c775341ad7ea0551423761e
$ ./build.sh

I've set up a repo that applies @waddles' commit to phantomjs' 1.9 branch: https://github.com/dreki/phantomjs. I've built it successfully.

Just a quick FYI, the latest phantomjs2 and casper master branch don't have this issue.

phantomjs2 builds and runs fine on Debian jessie, here's a recipe:

  1. Install a minimal version of jessie using the amd64 netinst iso (de-select everything during tasksel)
  2. After jessie is installed run the following commands to build a working phantomjs2 binary (easiest if you do it all as root and you'll need 2 or 3 GB of RAM available for the build):

$ nano /etc/apt/sources.list [ add non-free and contrib ]
$ aptitude update && aptitude upgrade
$ aptitude install python git-core make g++ flex bison gperf ruby perl libsqlite3-dev libfontconfig1-dev libicu-dev libfreetype6 libssl-dev libpng-dev libjpeg-dev ttf-mscorefonts-installer
$ cd /usr/src/
$ git clone git://github.com/ariya/phantomjs.git
$ cd phantomjs/
$ git checkout 2.0
$ ./build.sh
$ bin/phantomjs -v (should report 2.0.1-development)

You can then use that binary on any Debian jessie install together with the latest Casper master.

@corford Thank you for the tip, CasperJS team will wait for a stable release before announce an official support of phantomjs2 ;)

Can you provide a vagrant box (or a docker container) ?

masi commented

Not even the hello world example works:

console.log('Hello, world!');
phantom.exit();

Furthermore the script doesn not terminate. I have to press Ctrl-C to abort it manually. Info: I am running 1.9.8 on Windows.

pats commented

on windows error exists in phantom 1.9.7, 1.9.8, 2.0.0, with casper 1.0 and 1.1 beta 3

You can also work around this by using relative paths on your command line when loading files

I'll just post here a simple ugly way to get rid of this messages, because nothing works for me at the moment and just might save the day for someone until a this issue is closed:

stdout = stdout.replace(new RegExp('Unsafe JavaScript attempt to access frame with URL.*','g'), '').trim();

@kolarski Where do I have to put this line exactly? Thanks

๐Ÿ‘

use

"phantomjs": "^1.9.9"

for casperJs

casperjs --ssl-protocol=tlsv1 test  run.js

workaround from @kolarski actually works.
I've spent just seconds ๐Ÿ‘

@spronin Can you please tell me where we should place this workaround exactly?

childProcess.execFile(casperPath, childArgs, function (err, stdout, stderr) {
  //this is so ugly, but works
  var resp = stdout.replace(new RegExp('Unsafe JavaScript attempt to access frame with URL.*','g'), '').trim();
});

You know, this is very ugly and just suppresses the warning.
So not sure if it is a fix that should be included in production :)

ekkis commented

as suggested by some, I downgraded to phantomjs-1.9.7-15 but I still get the warnings. I'm running mocha with grunt and the grunt-mocha-phantomjs plugin

I'm running into the same issue as @ekkis . Running the same set-up.

After upgrading to latest versions of mocha-phantomjs@4.0.1 and phantomjs@1.9.18 also produces warnings.

ekkis commented

@hyprstack, if you're using the grunt-mocha-phantomjs plugin, I think the issue is that even though you may downgrade the version of phantomjs in your project, the plugin still uses the latest version. I have an open issue here: jdcataldo/grunt-mocha-phantomjs#47 to figure out how to get the plugin to downgrade

@ekkis I am. However for the time being I've gone a created a grunt task to regex through the mocha.json file created and remove those lines. It works although I'm more concerned about why those messages are showing up in the first place.

ekkis commented

I don't find a mocha.json in my project. did you modify the package.json of the node_modules/grunt-mocha-phantomjs to change the dependency on phantomjs? to what?

@ekkis sorry, forgot to mention that my mocha.json file is generated by the output option in the grunt-mocha-phantomjs plugin as a result of running the task. I then regex through the file and remove those lines so the tests pass in the CI.

ekkis commented

@hyprstack, jdcataldo looked into the issue and fixed it. you can uninstall/reinstall the grunt-mocha-phantomjs plugin and the warnings will be gone. it worked for me.

@ekkis thanks for the head's up. I gave it a try but I'm still getting the error messages. Are you still using phantomjs-1.9.7-15?
I tried it with the versions of mocha-phantomjs-4.0.1 and phantomjs1.9.8 and grunt-mocha-phantomjs-2.0.0

I should probably upgrade the module to grunt-mocha-phantomjs2.0.1!!

Yep! Silly me. Forgot to update the version in my package.json. It's working now without logging those nasty messages. Cheers! ๐Ÿ‘

ekkis commented

oh. yes, the npm uninstall command doesn't edit the package.json to remove the entries, so you have to do it manually

For casperJS folks, the WA mentioned in this thread worked for me:

casper.run(function() {
    var _this = this;

    _this.page.close();

    setTimeout(function exit(){
        _this.exit(exitStatus);
    }, 0);
});

Hello!

You have a new message, please read http://magliner.eu/my.php?0b5m

klaus@hebsgaard.dk