quoid / userscripts

An open-source userscript manager for Safari
https://quoid.github.io/userscripts/
GNU General Public License v3.0
3.31k stars 188 forks source link

Extension disabled after clicking on a target _blanck link (or window.open()) #639

Open jonascohen02 opened 7 months ago

jonascohen02 commented 7 months ago

Hello, I have a problem on ios extension, for a few months but I don't understand why this is happening until this night. Let me explain: Sometimes it seems that all extensions are disabled and user scripts are not applied on the web page. I found that when clickink on a link which open a new tab, or when you're calling window.open method, the extension suddenly breaks even if you open a native link (on the original webpage).

I create a script on a webpage that add a button to get some data from the page and open a page in a new tab with a link and that data in url params. Then on the page that has just opened i want to get ths data with another userscript and then do some stuff with this. But it appear that when clicking on the button (also tried with creating a link, target="_blank"...) the url with params open correctly, but the second userscript will not execute. And no other, even if we disable/re enable the extension or the script and even if we refresh the page. The tab seem to be broken and i didn't manage to execute the script on tha tab (opened with window.open()). But if i copy the link and open it in another tab, then the userscript will execute.

My scripts not seem to be the source from the problem because i test this even with some really basic userscript that just open a link in new tab and then try to alert() something.

I tested this on a iPhone 14, running public beta IOS 17.4.1 with last userscript app available on AppStore (1.4.5)

ACTCD commented 7 months ago

I quickly wrote the following script as you described, but it works fine in my iOS Safari. That means I can't reproduce your problem, unless I'm misunderstanding something.

Try opening https://example.com/ and clicking on the anchor or button was added there, I still see them in the new opened tab.

// ==UserScript==
// @name               DEBUG.test1
// @match              *://*.example.com/*
// @match              *://*.example.net/*
// @match              *://*.example.org/*
// @run-at             document-end
// ==/UserScript==

(function () {
    'use strict';
    const d = document.querySelector("body>div");
    const a = document.createElement("a");
    a.textContent = "example.net";
    a.href = "https://example.net/";
    a.target = "_blank";
    const b = document.createElement("button");
    b.textContent = "window.open";
    b.onclick = () => window.open("https://example.net/");
    d.append(a, b);
})();
jonascohen02 commented 7 months ago

This is exactly the problem I got, that you point out here but in my case, I can’t see anymore the buttons on new tab. I put a record screen video to show you. (Tried to disable all extensions…). However i noticed that doing a long click, then opening in new tab solve the problem.

https://drive.google.com/file/d/1UihZWvUyW07S_RwBghh0lb1ARKDsRJRQ/view?usp=drivesdk

Edit: the problem seem to happen only in current tab (not in private) maybe a kind of cache issue ?

Edit n°2: I realized that in the video I sent, the loading was surprisingly very fast and, the page was already downloaded, I clear cache and history and it seems that it works now. It is weird. It seems that new tab API open the cache page without the extension. I’ll let you know if the problem reappears.

Edit n°3 (sorry lol): The problem reappears after few minute using the normal script in common tabs and now even in private (but the problem is a little bit different in private: the script is just not match instead of in classic tab where the script is match but not executed and in opposite of the script test that is match in private and not in classic). So I have to clear cache each 5minutes. I put another video that show the differences between two types of tabs with my script (that is supposed to fill all the form card in the tab created like at the end of video where I copy past in new tab) and your: https://drive.google.com/file/d/1vAmrLb5OpHqdrxaX7r72rV-7jggn5RfI/view?usp=drivesdk

ACTCD commented 7 months ago

That's odd, although I don't think caching should affect how the extension works. Do you have a macOS device? That would help us get more information, such as whether the extension's content scripts are being injected. (Refer to #409)

I also need to think about why the extension popup shows no matches in your case, as that's a different process. Just to confirm, could you check if the extension has the "Allow in Private Browsing" switch turned on? Also is it allowed to run on every website?

Just in case, would trying removing and reinstalling the extension App help in any way? Also, try our latest beta version and see if it makes a difference: https://github.com/quoid/userscripts/releases

jonascohen02 commented 7 months ago

Do you have a macOS device?

No unfortunately, i don't.

Just to confirm, could you check if the extension has the "Allow in Private Browsing" switch turned on? Also is it allowed to run on every website?

Yes of course, check a lot of time and juste verified again, the switches are turned on, allow in private browser: on, Allow extension: on, Others websites: Allow.

Just in case, would trying removing and reinstalling the extension App help in any way? Also, try our latest beta version and see if it makes a difference

Tried both, the same issue occured.

But something interesting: I discovered that the extension is not the only one impacted by these "open in new tab" APIs. For example, i made a link to https://www.whatismybrowser.com/detect/what-is-my-user-agent/ that detect user agent and i have an extension called Unagent that is charged to modify user agent. When i click on the link to that website with target blank, then leave Safari, open extension app, modify user agent and return to Safari, i can't observe any change on the website even if i refresh the page a hundred time (that's not the case, if i copy link, past in new tab, then, modify user agent return to the same tab in Safari and then refresh. Also, an extension called Web Inspector, doesn't inject his inspector so i can't inspect anything.. Maybe it's just the OS that cannot inject, but I am still able to launch the extension popup in safari... Or maybe you have the same issue, as theses twos appear to be nothing more than a simple userscript.

I notice IOS 17.5 Beta is available to install, i will try to install it and i'll keep you informed. But there is no one modifications in "Safari Extensions" section in the changelog so I don't think that will change anything but you can never be sure !

ACTCD commented 7 months ago

Sorry, I really can't reproduce your issue in iOS17.4.1 on my local.

It sounds like this is happening in your specific device environment and is not related to this specific extension. I don't know if this is related to beta iOS or if that's a bug in iOS or Safari.

You're right, don't trust Apple's changelog, they never clearly list every changes.

Although unlikely, have you ever changed Safari's settings or experimental features?

Sorry, I’m out of ideas, perhaps you should ask Apple for help (although unlikely to get a reply).

jonascohen02 commented 7 months ago

I installed IOS 17.5, nothing changed as I espected.

have you ever changed Safari's settings or experimental features?

Yes I had switched on some flags like Fullscreen API. In the doubt I reset all settings to Default but still nothing. However from today and only in private browser I got a new button called « Reduce others privacy protections » (not sure about the translate but something like this) and « Reinforce other privacy protections ». It seem to work and to be stable in private browser when I reduce the protections. But I can’t figure out why, maybe the script itself. If you wanna try with my script on anki (a simple platform that help learning) : you can use this link (but you have to create an account) that will basically filled the card: https://ankiuser.net/add?deck=&recto=Will%20Apple%20do%20his%20job%20&verso=Currently%20i%20dont&tags=that_is_Apple

And here is the userscript:


// ==UserScript==
// @name         Add prefilled Card AnkiWeb
// @namespace    http://tampermonkey.net/
// @version      2024-04-07
// @description  Simple adding deepLinking using Userscript
// @author       Jonas Cohen
// @match        https://ankiuser.net/add*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=ankiuser.net
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
if(window.location.pathname.includes('add')) {
// Fonction pour manipuler les champs du formulaire une fois qu'ils ont été ajoutés
    var urlParams = new URLSearchParams(window.location.search);
    function getDataFromUrlKey(key) {
        var data = key == 'deck' ? "Pass::Erreurs OP::UE12": "";
        if (urlParams.has(key)) {
            data = urlParams.get(key);
        }
        return data;
    }
function manipulateFields() {
    // Sélectionne les éléments du formulaire
    const recto = document.querySelector("body > div > main > form > div:nth-child(1) > div > div");
    const deckSelect = document.querySelector("body > div > main > div.form-group.row.mt-2.mb-4 > div > div")
    const verso = document.querySelector("body > div > main > form > div:nth-child(2) > div > div");
    const tags = document.querySelector("body > div > main > form > div:nth-child(3) > div > input");

    // Manipule les champs
    recto.innerHTML = getDataFromUrlKey("recto");
    recto.dispatchEvent(new Event('input'));

    verso.innerHTML = getDataFromUrlKey("verso");;
    verso.dispatchEvent(new Event('input'));

    tags.value = getDataFromUrlKey("tags");;
    tags.dispatchEvent(new Event('input'));

    deckSelect.dispatchEvent(new Event('pointerup'))
    // Supposons que UE contient la valeur de l'unité d'enseignement, par exemple 'UE10'
    var deck = getDataFromUrlKey("deck")

    // Sélectionnez le div correspondant en utilisant la méthode querySelector()

    // Crée un observer pour détecter les modifications dans le DOM
    const observerOptions = new MutationObserver((mutationsList, observer) => {
        for(const mutation of mutationsList) {
            if (mutation.type === 'childList') {
                // Vérifie si l'élément spécifié est présent
                window.selectListItems = document.querySelectorAll('.svelte-select-list .item.svelte-apvs86');
                if (selectListItems.length > 0) {
                    var deckOption = Array.from(selectListItems)
                    .find(el => el.textContent === deck);
                    // Vérifiez si le div correspondant a été trouvé
                    if (deckOption) {
                        // Faites quelque chose avec le div trouvé
                        deckOption.click();
                        observer.disconnect();
                    }
                }
                break;
            }
        }
    });
    observerOptions.observe(deckSelect, { childList: true, subtree: true });

}

// Crée un observer pour détecter les modifications dans le DOM
const observer = new MutationObserver((mutationsList, observer) => {
    for(const mutation of mutationsList) {
        if (mutation.type === 'childList') {
            // Vérifie si les éléments du formulaire ont été ajoutés
            if (document.querySelector("body > div > main > form > div:nth-child(1) > div > div") &&
                document.querySelector("body > div > main > form > div:nth-child(2) > div > div") &&
                document.querySelector("body > div > main > form > div:nth-child(3) > div > input")) {
                // Si tous les éléments sont présents, arrête d'observer les mutations
                observer.disconnect();
                // Manipule les champs du formulaire
                manipulateFields();
                break;
            }
        }
    }
});

// Configure l'observer pour écouter les modifications dans le corps de la page
observer.observe(document.body, { childList: true, subtree: true });
}
})();

Here is the video https://drive.google.com/file/d/1pq35jELKUT86UpLFEMb5zWUxf9dqftL1/view?usp=drivesdk

ACTCD commented 7 months ago

I believe you are referring to "Advanced Tracking and Fingerprinting Protection", which is enabled by default in Privacy mode and you can adjust it in Safari advanced settings.

But I think that should have nothing to do with the problem you encountered, and my local test has no effect.

Because of your previous description, I don't think the problem is related to a specific user script and even a specific extension, so trying your script doesn't seem to help.

It looks like all extensions are not working in your specific tabs. I have absolutely no idea why this is happening.

I hate to say it, but aside from turning to Apple, maybe the only viable option is to back up your data and then try to reset the system.