Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Safari 12 (mojave) asking for user feedback on opening local .html redirect #29

Open
vobu opened this issue Oct 5, 2018 · 22 comments
Open

Comments

@vobu
Copy link

vobu commented Oct 5, 2018

Upon running a test in karma and launching Safari via this plugin, Safari 12 on macOS mojave asks for user feedback to confirm opening the local $tmp/[safari|redirect].html

Only after explicitly confirming loading the .html, karma tests continue running.

bildschirmfoto 2018-10-05 um 17 35 02

Would have liked to PR this breaking usage change, but couldn't find any documentation on how to either provide cmd line switches to Safari or otherwise tackle this :(

FTR: env:
macOS 10.14
Safari 12.0 (14606.1.36.1.9)
karma-safari-launcher 1.0.0

@muthu90ec
Copy link

Upon running a test in karma and launching Safari via this plugin, Safari 12 on macOS mojave asks for user feedback to confirm opening the local $tmp/[safari|redirect].html

Only after explicitly confirming loading the .html, karma tests continue running.

bildschirmfoto 2018-10-05 um 17 35 02

Would have liked to PR this breaking usage change, but couldn't find any documentation on how to either provide cmd line switches to Safari or otherwise tackle this :(

FTR: env:
macOS 10.14
Safari 12.0 (14606.1.36.1.9)
karma-safari-launcher 1.0.0

Hi, I ran into this problem,
What I think is the problem here, is that with the latest MAC release, Safari has more restrictions on opening a .html file from certain location on the machine.
For eg: opeing from a tmp dir is asking for user permission.
Instead if you try opening the .html file from userhome directory safari12 is happy. It seems to work on my machine give this a try. Just replace the SafariBrowser function with the code i have pasted below.

I worked around it by modifying the code in index.js.

var SafariBrowser = function(baseBrowserDecorator) {
  baseBrowserDecorator(this);

  this._start = function(url) {
    var HTML_TPL = path.normalize(__dirname + '/safari.html');
    var self = this;

    fs.readFile(HTML_TPL, function(err, data) {
      var content = data.toString().replace('%URL%', url);
      var staticHtmlPath = self._tempDir + '/redirect.html';

      fs.writeFile(staticHtmlPath, content, function(err) {
        var safariData = path.join(process.env.HOME, 'Library/Containers/com.apple.Safari/Data/redirect.html');
        fs.createReadStream(staticHtmlPath).pipe(fs.createWriteStream(safariData));
        self._execCommand(self._getCommand(), [safariData]);
      });
    });
  };
};

@vobu
Copy link
Author

vobu commented Oct 18, 2018

Hi! Good idea, didn't think of trying this out myself :)
Unfortunately doesn't work, as there seems to be a permission issue on ~/Library/Containers/com.apple.Safari:

Box: ~/Library/Containers > pwd
/Users/bla/Library/Containers
Box: ~/Library/Containers > ls -al com.apple.Safari
ls: com.apple.Safari: Operation not permitted

So the node runtime can't create the file either:

errno: -1,
code: 'EPERM',
syscall: 'open',
path:
'/Users/bla/Library/Containers/com.apple.Safari/Data/redirect.html'

How do the permission on ~/Library/Containers/com.apple.Safari look on your mac?
I'm on a clean install of macOS mojave.

BTW: modified your code a little for brevity:

var SafariBrowser = function (baseBrowserDecorator) {
    baseBrowserDecorator(this);

    this._start = function (url) {
        var HTML_TPL = path.normalize(__dirname + '/safari.html');
        var self = this;

        fs.readFile(HTML_TPL, function (err, data) {
            var content = data.toString().replace('%URL%', url);

            // var staticHtmlPath = self._tempDir + '/redirect.html';
            var staticHtmlPath = path.join(process.env.HOME, 'Library/Containers/com.apple.Safari/Data/redirect.html');


            fs.writeFile(staticHtmlPath, content, function (err) {
                if (err) {
                    console.error(err);
                    return false;
                }
                self._execCommand(self._getCommand(), [staticHtmlPath]);
            });
        });
    };
};

@muthu90ec
Copy link

Hi! Good idea, didn't think of trying this out myself :)
Unfortunately doesn't work, as there seems to be a permission issue on ~/Library/Containers/com.apple.Safari:

Box: ~/Library/Containers > pwd
/Users/bla/Library/Containers
Box: ~/Library/Containers > ls -al com.apple.Safari
ls: com.apple.Safari: Operation not permitted

So the node runtime can't create the file either:

errno: -1,
code: 'EPERM',
syscall: 'open',
path:
'/Users/bla/Library/Containers/com.apple.Safari/Data/redirect.html'

How do the permission on ~/Library/Containers/com.apple.Safari look on your mac?
I'm on a clean install of macOS mojave.

BTW: modified your code a little for brevity:

var SafariBrowser = function (baseBrowserDecorator) {
    baseBrowserDecorator(this);

    this._start = function (url) {
        var HTML_TPL = path.normalize(__dirname + '/safari.html');
        var self = this;

        fs.readFile(HTML_TPL, function (err, data) {
            var content = data.toString().replace('%URL%', url);

            // var staticHtmlPath = self._tempDir + '/redirect.html';
            var staticHtmlPath = path.join(process.env.HOME, 'Library/Containers/com.apple.Safari/Data/redirect.html');


            fs.writeFile(staticHtmlPath, content, function (err) {
                if (err) {
                    console.error(err);
                    return false;
                }
                self._execCommand(self._getCommand(), [staticHtmlPath]);
            });
        });
    };
};

Interesting, my HOME var has following out:
cmd: printenv HOME
out: /home/unixid
cmd: cd /home/unixid/Library/Containers/com.apple.Safari/Data
cmd: vi test.txt -> save
cmd: ls -al test.txt
out: -rw-r--r-- -> I have read write permission in that dir.
Not sure why your id lacks privileges in dir: home/unixid/Library/Containers/com.apple.Safari/Data

@gkatsev
Copy link

gkatsev commented Oct 29, 2018

Just tried it out and it seems to be working for me.

I just made the change here and in the STP launcher

// const staticHtmlPath = self._tempDir + '/redirect.html';
var staticHtmlPath = path.join(process.env.HOME, 'Library/Containers/com.apple.Safari/Data/redirect.html');
// const staticHtmlPath = self._tempDir + '/redirect.html';
var staticHtmlPath = path.join(process.env.HOME, 'Library/Containers/com.apple.SafariTechnologyPreview/Data/redirect.html');

Would one of you be interested in making a PR for these? Maybe we can get the maintainers to merge and release them as this is a major issue.

@rmi22186
Copy link

Just came across this problem after upgrading to Mojave on my work laptop. I am having the exact same error message output as @vobu after modifying karma-safari-launcher/index.js
@muthu90ec - when i CD into Users/ring/Library/Containers/com.apple.Safari/Data, I'm not able to perform any

cmd: touch test.txt
out: Operation not permitted
cmd: ls
out: Operation not permitted

Even when I sudo, nothing works. However, when in the Finder if I manually go into /Data, and do Get Info, it says I have read/write access. Additionally, I can drag files in there with no problem.

@vobu did you ever figure this out?

@muthu90ec
Copy link

Just came across this problem after upgrading to Mojave on my work laptop. I am having the exact same error message output as @vobu after modifying karma-safari-launcher/index.js
@muthu90ec - when i CD into Users/ring/Library/Containers/com.apple.Safari/Data, I'm not able to perform any

cmd: touch test.txt
out: Operation not permitted
cmd: ls
out: Operation not permitted

Even when I sudo, nothing works. However, when in the Finder if I manually go into /Data, and do Get Info, it says I have read/write access. Additionally, I can drag files in there with no problem.

@vobu did you ever figure this out?

@rmi22186, Instead of /Users/ring/Li... directory could you try from /home, directory. you should have privileges in your HOME dir.

Please confirm, thanks.

@rmi22186
Copy link

@muthu90ec
There doesn't seem to be anything in my root home folder. perhaps it's the way our sys admins set up our computers, as the icon is also different for it vs what I was expecting.

image

@vobu
Copy link
Author

vobu commented Nov 19, 2018

Hi,

Just came across this problem after upgrading to Mojave on my work laptop. I am having the exact same error message output as @vobu after modifying karma-safari-launcher/index.js
@muthu90ec - when i CD into Users/ring/Library/Containers/com.apple.Safari/Data, I'm not able to perform any

cmd: touch test.txt
out: Operation not permitted
cmd: ls
out: Operation not permitted

Even when I sudo, nothing works. However, when in the Finder if I manually go into /Data, and do Get Info, it says I have read/write access. Additionally, I can drag files in there with no problem.

@vobu did you ever figure this out?

unfortunately no; the issue got pushed back on my todo list, but it's still on there. Haven't had time to revisit yet.
Am sharing your assumption that @muthu90ec gets his home dir served per AFP/NFS in a corporate environment; as opposed to us 2 using our macs in "standalone" mode.
@gkatsev you seem to have merged a fix regarding this issue; however I couldn't find a new version of karma-safari-launcher on npm (yet)...anything coming up or you need a hand with?

@jeffsaremi
Copy link

The same issue happens on my machine. Is there a fix for this?

Safari 12.0.1
Mac OS X 10.14.1
karma-safari-laucnher 1.0.0

@vobu
Copy link
Author

vobu commented Dec 7, 2018

I figured out a workaround: when using karma-safari-private-launcher https://www.npmjs.com/package/karma-safari-private-launcher, Safari doesn't open the File Popup. The tests via karma then ran fine.
But: upon first launch I had to both allow the launching instance (WebStorm in my case) to control the computer (in preferences) and confirm the privileges pop-up.
After that, happy Safari-karma test runs here.

@vobu
Copy link
Author

vobu commented Dec 7, 2018

Just tried it out and it seems to be working for me.

I just made the change here and in the STP launcher

// const staticHtmlPath = self._tempDir + '/redirect.html';
var staticHtmlPath = path.join(process.env.HOME, 'Library/Containers/com.apple.Safari/Data/redirect.html');
// const staticHtmlPath = self._tempDir + '/redirect.html';
var staticHtmlPath = path.join(process.env.HOME, 'Library/Containers/com.apple.SafariTechnologyPreview/Data/redirect.html');

this unfortunately never worked for me. I'm on a fresh install of Mojave.
And it bugged me to the extent that I filed a bug report: https://bugreport.apple.com/web/?problemID=46549321

@vobu
Copy link
Author

vobu commented Jan 28, 2019

And it bugged me to the extent that I filed a bug report: https://bugreport.apple.com/web/?problemID=46549321

for $whoever is interested: Apple closed the bug and says "feature":

This appears to be a System Integrity Protection issue. In macOS 10.14 system-integrity-protection prevents creating files in ~/Library/Safari. It is expected behavior. We’re sorry this took so long to diagnose.

Doesn't explain, why ~/Library/Containers/com.apple.Safari** isn't accessible. I commented the closed bug accordingly, hoping to receive some more insight from Apple support. So we'll see.

@muthu90ec
Copy link

muthu90ec commented Jan 28, 2019

And it bugged me to the extent that I filed a bug report: https://bugreport.apple.com/web/?problemID=46549321

for $whoever is interested: Apple closed the bug and says "feature":

This appears to be a System Integrity Protection issue. In macOS 10.14 system-integrity-protection prevents creating files in ~/Library/Safari. It is expected behavior. We’re sorry this took so long to diagnose.

Doesn't explain, why ~/Library/Containers/com.apple.Safari** isn't accessible. I commented the closed bug accordingly, hoping to receive some more insight from Apple support. So we'll see.

Thanks.
There is another way to work around this problem.
We can use MAC OS's native apis (Launch services) to open urls in Safari browser.
https://developer.apple.com/documentation/coreservices/lslaunchurlspec
https://developer.apple.com/documentation/coreservices/1441986-lsopenfromurlspec

But this will require a binary to be built first. Here is a swift code which will accept a url as a command line argument. And will load the url in Safari even if the default web browser is set to something else.

import Foundation


let args = CommandLine.arguments
let argCount = CommandLine.argc
if (argCount != 2) {
    print("The safari url launcher app needs exactly one argument. Exiting with code: 1")
    exit(1)
}
let userUrl = args[1]
let url = URL(string: userUrl)
let safariString = CFStringCreateCopy(nil, "Safari" as CFString)

let safariApp = URL(string: "file:///Applications/Safari.app" ) as CFURL?

let safariUnManagedURL = Unmanaged<CFURL>.passUnretained(safariApp!)

let userURLs: CFArray = [url] as CFArray
let unManagedUserURLs = Unmanaged<CFArray>.passUnretained(userURLs)

var launchSpec = LSLaunchURLSpec(appURL: safariUnManagedURL, itemURLs: unManagedUserURLs, passThruParams: nil, launchFlags: LSLaunchFlags.newInstance, asyncRefCon: nil)

let stat = LSOpenFromURLSpec(&launchSpec, nil)
if (stat == 0) {
    print("success:", stat)
    exit(0)
} else {
    print("error:", stat)
    exit(1)
}

Quick patch to test the binary out:

//safariUrlLauncher is the built binary using above code
//The url is the karma server's url and not the redirect.html url
require('child_process').spawnSync(safariUrlLauncher, [url], {"encoding" : "utf8", "cwd": os.tmpdir()});

@vobu
Copy link
Author

vobu commented Jan 29, 2019

Thanks.
There is another way to work around this problem.
We can use MAC OS's native apis (Launch services) to open urls in Safari browser.
https://developer.apple.com/documentation/coreservices/lslaunchurlspec
https://developer.apple.com/documentation/coreservices/1441986-lsopenfromurlspec

But this will require a binary to be built first. Here is a swift code which will accept a url as a command line argument. And will load the url in Safari even if the default web browser is set to something else.

nice idea!
does this allow handing require('child_process').spawnSync(...) as module.exports = {...} just like https://github.com/karma-runner/karma-safari-launcher/blob/master/index.js?

Would be cool if you could do a feature-branch on this.
I'd be on board for testing.

@muthu90ec
Copy link

muthu90ec commented Feb 3, 2019

Thanks.
There is another way to work around this problem.
We can use MAC OS's native apis (Launch services) to open urls in Safari browser.
https://developer.apple.com/documentation/coreservices/lslaunchurlspec
https://developer.apple.com/documentation/coreservices/1441986-lsopenfromurlspec
But this will require a binary to be built first. Here is a swift code which will accept a url as a command line argument. And will load the url in Safari even if the default web browser is set to something else.

nice idea!
does this allow handing require('child_process').spawnSync(...) as module.exports = {...} just like https://github.com/karma-runner/karma-safari-launcher/blob/master/index.js?

Would be cool if you could do a feature-branch on this.
I'd be on board for testing.

Hi,
Please clone this repo and try using using in your node_modules,
https://github.com/muthu90ec/karma-safarinative-launcher

For easy access created npm package:
https://www.npmjs.com/package/karma-safarinative-launcher

I tested it on my machine and it works

@vobu
Copy link
Author

vobu commented Feb 6, 2019

And it bugged me to the extent that I filed a bug report: https://bugreport.apple.com/web/?problemID=46549321

for $whoever is interested: Apple closed the bug and says "feature":

This appears to be a System Integrity Protection issue. In macOS 10.14 system-integrity-protection prevents creating files in ~/Library/Safari. It is expected behavior. We’re sorry this took so long to diagnose.

Doesn't explain, why ~/Library/Containers/com.apple.Safari** isn't accessible. I commented the closed bug accordingly, hoping to receive some more insight from Apple support. So we'll see.

FTR: Apple support finally stated in https://bugreport.apple.com/web/?problemID=46549321:

Yes, system protection applies to ~/Library/Containers as well.

So there's that. Now it's either using https://www.npmjs.com/package/karma-safari-private-launcher or following up with @muthu90ec's proposed solution (which I haven't had the time to test yet, but will).

@3cp
Copy link

3cp commented Jun 12, 2019

There is another way to supply a url to safari without using an html file to redirect.

open -F -W -n -b com.apple.Safari https://www.kernel.org

The problem is I now got the process pid of open command, not the Safari process itself. So I can only programmerly kill the open process, but safari process is still running.

@brandonocasey
Copy link

I created a workaround for this via a new launcher that uses applescript. https://www.npmjs.com/package/karma-safari-applescript-launcher

@jdmarshall
Copy link

Is there a reason for trampolining safari through an html file instead of passing a url to it?

thewtex added a commit to thewtex/itk-vtk-viewer that referenced this issue Mar 1, 2021
Can be executed with:

  npm run test -- --browsers Safari

Currently has a few failing tests.

Cannot use karma-safari-launcher due to
karma-runner/karma-safari-launcher#29
@heidemn-faro
Copy link

heidemn-faro commented Jun 29, 2021

In Azure Pipelines, using a Microsoft macOS-10.15 agent, these are my results:

  • karma-safari-launcher - not working 👎
  • karma-safari-private-launcher - not working 👎
  • karma-safari-applescript-launcher - not working 👎
  • karma-safarinative-launcher - Works! 🚀

For the applescript launcher, I get this error:

29 06 2021 08:16:19.847:INFO [karma-server]: Karma v5.1.0 server started at http://0.0.0.0:9876/
29 06 2021 08:16:19.856:INFO [launcher]: Launching browsers Safari with concurrency unlimited
29 06 2021 08:16:19.874:INFO [launcher]: Starting browser Safari
29 06 2021 08:18:19.912:WARN [launcher]: Safari have not captured in 120000 ms, killing.
29 06 2021 08:18:24.672:ERROR [karma-server]: UnhandledRejection: Command failed: osascript -e 
    set wasopen to false
    if application "Safari" is running then set wasopen to true
    tell application "Safari"
      make new document with properties {URL:"http://localhost:9876/?id=39841744"}
    end tell
    return wasopen
    
118:203: execution error: Safari got an error: AppleEvent timed out. (-1712)


29 06 2021 08:18:24.674:ERROR [karma-server]: Error: Command failed: osascript -e 
    set wasopen to false
    if application "Safari" is running then set wasopen to true
    tell application "Safari"
      make new document with properties {URL:"http://localhost:9876/?id=39841744"}
    end tell
    return wasopen
    
118:203: execution error: Safari got an error: AppleEvent timed out. (-1712)

    at makeError (/Users/runner/work/1/s/3_tools/node_modules/execa/index.js:172:9)
    at /Users/runner/work/1/s/3_tools/node_modules/execa/index.js:277:16
    at processTicksAndRejections (internal/process/task_queues.js:95:5) {
  code: 1,
  stdout: '',
  stderr: '118:203: execution error: Safari got an error: AppleEvent timed out. (-1712)\n',
  failed: true,
  signal: null,
  cmd: 'osascript -e \n' +
    '    set wasopen to false\n' +
    '    if application "Safari" is running then set wasopen to true\n' +
    '    tell application "Safari"\n' +
    '      make new document with properties {URL:"http://localhost:9876/?id=39841744"}\n' +
    '    end tell\n' +
    '    return wasopen\n' +
    '    ',
  timedOut: false,
  killed: false
}
>> Tests failed with exit code 1
(node:2236) UnhandledPromiseRejectionWarning: Error: Command failed: osascript -e 
    tell application "Safari"
      close documents where URL = "http://localhost:9876/?id=39841744"
      quit
    end tell
    
37:101: execution error: Safari got an error: AppleEvent timed out. (-1712)

   at makeError (/Users/runner/work/1/s/3_tools/node_modules/execa/index.js:172:9)
    at /Users/runner/work/1/s/3_tools/node_modules/execa/index.js:277:16
    at processTicksAndRejections (internal/process/task_queues.js:95:5)
(Use `node --trace-warnings ...` to show where the warning was created)
(node:2236) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 4)
(node:2236) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

@fosemberg
Copy link

The same issue happens on my machine.

macOS: Monterey 12.2.1 (21D62)
Safari: 15.3 (17612.4.9.1.8)
karma-safari-launcher: 1.0.0

@jdmarshall
Copy link

It's been a while, but I fixed this on my project by modifying how safari opens so it doesn't use a trampoline html file and just opens Safari directly.

Is there a reason for trampolining safari through an html file instead of passing a url to it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants