edabg / jsprintsetup

JSPrintSetup Firefox addon
Mozilla Public License 2.0
76 stars 39 forks source link

jsPrintSetup requests permission for active tab #36

Open ErnestoNCarrea opened 7 years ago

ErnestoNCarrea commented 7 years ago

When a page in an inactive tab requests permission, jsPrintSetup will show the request bar for the current, active tab instead.

This is:

Tab 1 (inactive) : Site X doing background work, uses jsPrintSetup and fires a permission request Tab 2 (active): Some other site (Google or whatever) shows the permission request bar

In my setup, Site X is already allowed permission, so if Site X is the active tab, jsPrintSetup will success and setup printing normally. But if Site X is in background and the active tab is, for example, www.google.com, Firefox will show the permission bar as if Google was requesting permission.

Even worst, if the active tab is the Firefox's internal new tab page, issue #35 will occur and closing Firefox is the only way out.

This is using Firefox 50.1.0 in 64-bit Fedora 25.

mitkola commented 7 years ago

What is your javascript code in page where jsPrintSetup is used?

ErnestoNCarrea commented 7 years ago

It's roughly this code, called on document.ready and after loading AJAX content that changes print parameters. Also tested using full page refresh (like hitting F5, quickly switching to another tab and then receiving the notification on the wrong tab).

function SetPrintSettings(printSettings) {
    if (typeof jsPrintSetup === 'undefined' || jsPrintSetup === null) {
        if(printSettings !== undefined && printSettings !== null) {
            console.warn('Please install jsPrintSetup.');
        }
    } else {
        console.log('Using jsPrintSetup to set print parameters');
        var perm = jsPrintSetup.getPermissions();
        if (perm == jsPrintSetup.JSPS_DENY_ACTION) {
           jsPrintSetup.askUserPermissions(null);
        }// else jsPrintSetup will request automatically

        jsPrintSetup.setOption('headerStrLeft', '');
        jsPrintSetup.setOption('headerStrCenter', '');
        jsPrintSetup.setOption('headerStrRight', '');
        jsPrintSetup.setOption('footerStrLeft', '');
        jsPrintSetup.setOption('footerStrCenter', '');
        jsPrintSetup.setOption('footerStrRight', '');

        jsPrintSetup.setOption('printBGColors', true);
        jsPrintSetup.setOption('printBGImages', true);

        jsPrintSetup.setOption('shrinkToFit', 0);
        jsPrintSetup.setOption('scaling', 100);

        jsPrintSetup.setPaperSizeData(10);    // A4

        if(printSettings && printSettings.Orientacion == 'apaisada') {
            jsPrintSetup.setOption('orientation', jsPrintSetup.kLandscapeOrientation);
        } else {
            jsPrintSetup.setOption('orientation', jsPrintSetup.kPortraitOrientation);
        }

        if(printSettings && printSettings.Predefinido == 'a4_ajustado') {
            jsPrintSetup.setOption('marginTop', 10);
            jsPrintSetup.setOption('marginBottom', 10);
            jsPrintSetup.setOption('marginLeft', 10);
            jsPrintSetup.setOption('marginRight', 10);
        } else {
            jsPrintSetup.setOption('marginTop', 10);
            jsPrintSetup.setOption('marginBottom', 10);
            jsPrintSetup.setOption('marginLeft', 25);
            jsPrintSetup.setOption('marginRight', 10);
        }

        if(printSettings && printSettings.Rango !== undefined) {
            jsPrintSetup.setOption('printRange', jsPrintSetup.kRangeSpecifiedPageRange);
            jsPrintSetup.setOption('startPageRange', printSettings.Rango.Desde);
            jsPrintSetup.setOption('endPageRange', printSettings.Rango.Hasta);
        }

        jsPrintSetup.refreshOptions();
        jsPrintSetup.saveOptions(jsPrintSetup.kSaveAll);
    }    
}
mitkola commented 7 years ago

jsPrintSetup.askUserPermissions always ask for permissions. The confirmation bar is displayed in window independently of active tab (this is behavior of FF permission manager). I suppose that your code is executed in the time while you in other tab.

ErnestoNCarrea commented 7 years ago

In my setup, the site executing the code is already allowed. If this site's tab is active tab when askUserPermissions is executed, it will NOT ask for permission, and jsPrintSetup successfully sets printing parameters. This is correct and the expected behavior.

However, if -at the time of askUserPermissions- the active tab is, for example, the Github website, the request bar shows in the Github tab. Not on the correct tab, not even on all tabs, only on the active tab. Even worst: if I click allow, Github is added to the allowed sites. Github does not use jsPrintSetup and never asked for permissions.

This is not desired behavior as it has two problems:

I have zero experience in Firefox extension development, but this guy seems to have a similar problem: http://stackoverflow.com/questions/12609753/get-window-object-from-tab

According to Mozilla docs, perhaps Notification Box is better suited for this task:

"these notifications are inside the current tab, so switching tabs will make a notification disappear. The notification shows up again when you come back to the tab that displayed it. This means that these notifications make the most sense when they are related to the page currently being displayed"

https://developer.mozilla.org/en-US/Add-ons/Overlay_Extensions/XUL_School/User_Notifications_and_Alerts

mitkola commented 7 years ago

If I understand correctly there is possibility in your code to call askUserPermissions while is not active tab. In this case jsPrintSetup gets active window (tab) from browser and this may be issue. If you can call jsPrintSetup methods explicitly on user interaction this can solve the problem. jsPrintSetup is using Notification Box that you are referred https://github.com/edabg/jsprintsetup/blob/master/src/components/jsPrintSetup.js#L495

ErnestoNCarrea commented 7 years ago

Yes, my code can call jsPrintSetup while it's not the active tab. I can't call jsPrintSetup on user interaction because the user might not interact with the page, perhaps just load the page and print it.

I was using "page ready" event, but changed it to "on before print" event, so there are less chances that tab is not active. However, sometimes issue #35 shows up when printing as well as doing print preview. It looks like with "on before print" I have to let the page rest for 2 or 3 seconds before trying to print and it works but if i print immediately after page load, it gives the error on issue #35.

In any case, leaving possible workarounds aside, I think it's a bug / serious limitation / design problem to assume what the active tab is. I mean, it's a multi-tab, multi-window, multi-threaded browser, and jsPrintSetup as it's name implies is a JavaScript utility. JavaScript is often used for doing things programmatically, not interactively, so we shouldn't assume the user is actually looking at the page or interacting with it. Issue #35 is also caused by this design problem.

Perhaps it's no easy feat, but I think the correct way to do this is to act on the calling tab, not on the active tab. I'll take a look at the code to see if with my limited experience and time can come up with a PR.

PS: The Mozilla documentation calls it "notification box", but it's actually talking about the "remember password" box, "share location" box, etc. Like this:

https://yikyak.zendesk.com/hc/en-us/article_attachments/201792983/Firefox_41_on_Windows.png http://cdn.ghacks.net/wp-content/uploads/2016/06/firefox-custom-permissions-visibility.jpg