Greasemonkey: Exécuter dans des cadres

Créé le 21 sept. 2017  ·  48Commentaires  ·  Source: greasemonkey/greasemonkey

Greasemonkey 4, à ce jour, ne détecte que les événements de navigation au niveau supérieur, il applique donc efficacement @noframes à chaque script.

Commentaire le plus utile

Bonjour,
Allez-vous régler le problème ? C'est un défaut assez ancien et qui a un impact sur tous les scripts basés sur la structure des iframes...

Tous les 48 commentaires

webNavigation.onCommitted ne « voit » pas la création du cadre initial / le rendu de la page, bien que si le cadre navigue ailleurs que sur sa page initiale, l'auditeur l'attrapera. Si les options incluaient la clé 'allFrames': true le problème est _quelque peu_ résolu. Le script sera injecté dans n'importe quel cadre de la page html statique, bien que vous ayez alors des problèmes de correspondance origine/URL. De plus, si un cadre est créé à l'aide de Javascript, le script n'est pas injecté.

La solution la plus simple à laquelle je pourrais penser serait de remplacer webNavigation.onCommitted par webRequest.onResponseStarted avec un filtre de {'urls': ['<all_urls>'], 'types': ['main_frame', 'sub_frame']} .

J'ai fait quelques tests limités et aucun autre changement n'a été nécessaire. J'ai pu exécuter un script dans un cadre et un cadre créé à l'aide de Javascript.

@arantius envisage-t-il de fusionner le correctif de @Sxderp ?

Cela affecte les scénarios où les iframes sont des objets d'origine croisée, il est donc impossible d'effectuer tout type de modification sans exécuter GM sur ces iframes particuliers.

Merci !

J'ai raté ça, je vais y réfléchir bientôt.

Juste une observation lors de mes tests d'anciens scripts, je ne sais pas, si ça aide...

Étant donné un script, qui est censé fonctionner sur un iframe,
il semble qu'il exécute les modifications sur la page,
mais s'actualise à nouveau sur la page non modifiée.

Je ne peux voir le scintillement que lorsque je rafraîchis la page très rapidement.

Juste une observation lors de mes tests d'anciens scripts, je ne sais pas, si ça aide...

Est-ce avec mon patch ou avec la version publiée ?

Euh, je pense que c'était la version 4.0...
J'ÉTAIS @4.1b3, mais pour les tests, je suis presque sûr que j'ai réinstallé la version finale (jusqu'à maintenant !)

Idem ici avec les iframes comme le décrit Eselce. D'une certaine manière, il est exécuté, puis arrêté après le chargement de l'iframe ou de la page.

Si j'injecte ce script, je n'obtiens que 1 et "self !== top":

console.log('1');
if (self !== top) {
   console.log('self !== top');
   setTimeout(function() {
      console.log('Timeout');
   }, 2000);  
} else {
   console.log('self === top');
}

"Timeout" n'est pas affiché dans le journal, ni toutes les fonctions et liaisons.

J'utilise 4.1b3.

J'ai le même problème avec GM 4.0 sur Quantum. J'ai écrit un exemple factice très simple avec deux pages : main.html et framed.html , et un script GM qui est chargé sur chaque page et affiche l'URL de la page sur laquelle il est chargé.

La plupart du temps, je ne reçois que des notifications concernant main.html , mais dans environ 5% des cas, surtout si je maintenez la touche F5 enfoncée, je peux également recevoir une notification concernant framed.html .

Existe-t-il un hack pour forcer de manière fiable GM 4.0 à s'exécuter à l'intérieur des iframes jusqu'à la sortie d'un correctif ?

Je viens de découvrir que les scripts utilisateur sont exécutés de manière fiable dans <embed src="..."> mais pas dans <iframe src="..">
J'ai écrit un petit script de test :
https://openuserjs.org/scripts/cuzi/iframe_embed_Test_Greasemonkey_4

Quelques détails supplémentaires : Dans certains cas, mes scripts sont complètement exécutés dans le cadre (mais la vue est écrasée plus tard par les scripts de page et ainsi de suite).
Parfois, les parties synchrones de mon script sont terminées, mais les parties asynchrones sont soudainement interrompues par l'activité de la page...
J'espère que cela pourra aider!

Quelqu'un a-t-il plus d'infos à ce sujet ?

Juste un bref résumé de ce fil (problème):

  • Oubliez la plupart des affichages, ils ne s'appliquent pas
  • Probablement, les scripts sont toujours exécutés (mais pas jusqu'à la fin)
  • Malheureusement, la page est rafraîchie plus tard - la mise en page est recalculée, l'exécution est interrompue
  • Cela s'applique principalement (mais pas entièrement) aux parties asynchrones des scripts

Je ne suis pas tellement dans ces internes, mais probablement quelqu'un est...

En tant que correctif temporaire, j'ai remplacé les iframes par des embeds ( exemple de script ), ce qui fonctionne pour obtenir un script correspondant au cadre à déclencher (crédit à @cvzi pour avoir compris que <embed src="..."> fonctionne) .

Il peut être intéressant de noter que Violentmonkey et Tampermonkey fonctionnent très bien dans les cadres intégrés. Puisque VM est open source, peut-être voyez-vous comment ils l'ont fait ?

Malheureusement, Violentmonkey et Tampermonkey utilisent toujours l'ancien schéma de nommage GM_ pour les fonctions spéciales, donc les scripts ne sont pas encore portables.

https://github.com/greasemonkey/gm4-polyfill

Tampermonkey => GM.* appelle, si non fourni
Violentmonkey => GM.* appelle
Greasemonkey -3.17 / FF -56.0 => appels GM.*
Greasemonkey 4.0+ / FF 57.0+ => appels GM.* intégrés

// <strong i="11">@grant</strong>        GM.getValue
// <strong i="12">@grant</strong>        GM.setValue
// <strong i="13">@require</strong>      https://greasemonkey.github.io/gm4-polyfill/gm4-polyfill.js
// <strong i="14">@grant</strong>        GM_getValue
// <strong i="15">@grant</strong>        GM_setValue

Le correctif de déjà été intégré à la branche principale ? Sinon, comment dois-je procéder pour installer sa fourche ?

Le correctif de déjà été intégré à la branche principale ? Sinon, comment dois-je procéder pour installer sa fourche ?

  1. Non, ce n'est pas le cas.
  2. Malheureusement, c'est l'un de mes PR que je n'ai pas synchronisé avec le maître et qui n'a donc pas été rebasé. Ainsi, la branche elle-même manque certains des changements actuels.
  3. Je n'ai également jamais mis en œuvre les changements suggérés dans les commentaires des relations publiques. Honnêtement, ces changements _ne devraient pas_ être nécessaires, mais parce que Mozilla fait continuellement des bêtises, les changements sont nécessaires.
  4. Si vous souhaitez toujours l'utiliser (non recommandé), vous pouvez suivre les étapes ci-dessous.

  1. git clone -b use-on-response-started-for-execute --single-branch https://github.com/Sxderp/greasemonkey.git [1]
  2. Exécutez ./package.sh , cela créera un fichier XPI.
  3. Accédez à about:config dans Firefox et définissez xpinstall.signatures.required sur false
  4. Accédez à about:addons dans Firefox, cliquez sur le rouage puis sélectionnez Installer à partir d'un fichier.
  5. Sélectionnez le XPI qui a été créé à l'étape 2.

[1] Si votre version de git ne supporte pas les drapeaux -b et/ou --single-branch (ancienne version de git) alors vous pouvez faire git clone https://github.com/Sxderp/greasemonkey.git et git checkout use-on-response-started-for-execute .

Bonjour,
Allez-vous régler le problème ? C'est un défaut assez ancien et qui a un impact sur tous les scripts basés sur la structure des iframes...

Pour rappel, que nous avons le 13 mars demain (voir Firefox 59.0 )...

Je veux faire référence à @Sxderp :

webNavigation.onCommitted ne « voit » pas la création du cadre initial / le rendu de la page, bien que si le cadre navigue ailleurs que sur sa page initiale, l'auditeur l'attrapera. Si les options incluaient la clé 'allFrames' : true le problème est quelque peu résolu. Le script sera injecté dans n'importe quel cadre de la page html statique, bien que vous ayez alors des problèmes de correspondance origine/URL. De plus, si un cadre est créé à l'aide de Javascript, le script n'est pas injecté.

En fait, j'ai la preuve que (sur mon système) l'auditeur executeUserscriptOnNavigation est appelé de manière fiable avec chrome.webNavigation.onCommitted , de sorte que chrome.tabs.executeScriptInFrame est appelé avec le bon frameId . Pourquoi cela ne résout-il pas tous nos problèmes avec les cadres ? On ne devrait pas avoir besoin de chrome.webRequest.onResponseStarted pour réagir sur une iframe ! (Ou voulez-vous dire, il réagit sur l'événement, mais le cadre n'est pas visible ?) Il s'appelle définitivement...

Existe-t-il un bug connu avec chrome.tabs.executeScriptInFrame et frameId ? Il y a eu des problèmes il y a des années, mais ils sont résolus maintenant. all_frames n'est pas défini, donc frameId devrait être valide. Le réglage de l'option matchAboutBlank à true semble important (sinon executeScript renvoyé une erreur <unavailable> ), bien que je n'aie pas bien compris que about:blank trucs (où est-ce que c'est ?)...

Des idées?

Caractéristiques? Il s'agit d'une fonctionnalité de base manquante depuis le début... J'espère que j'ai mal interprété cela.

@Eselce , c'était il y a longtemps et je ne suis pas sûr de me souvenir entièrement de ce à quoi je faisais référence, mais je vais

Maintenant, sur la question. Lorsque j'ai fait mes premiers tests, j'avais une page statique avec un même cadre d'origine et un cadre distant. Lors du chargement initial de la page, je n'ai pu déclencher le rappel onCommitted qu'une seule fois. Il s'est déclenché pour le document principal mais ne s'est déclenché pour aucune des trames statiques du document [1]. Ainsi, aucun script ne leur serait injecté.

Cependant, après le chargement initial, si je faisais "naviguer" l'un des cadres quelque part, le rappel onCommitted serait appelé et des scripts seraient injectés dans le cadre au nouvel emplacement.

Une tentative d'utilisation de la clé d'option all_frames été effectuée afin de contourner le problème ci-dessus. Alors que l'utilisation de la clé provoquait l'injection des scripts dans les cadres de la page, il y avait l'inconvénient évident de ne pas faire correspondre correctement l'origine + le chemin du cadre à ce sur quoi le script devrait ou ne devrait pas s'exécuter.

En passant, j'ai également mentionné que l'utilisation de la clé all_frames n'injecterait pas de scripts dans les cadres créés par Javascript.

[1] Je ne sais pas si ce problème est toujours présent. Si je me souviens bien ce problème n'était pas présent dans FF 52 ESR mais était présent dans 56 (57 ?) (donc régression). Peut-être qu'il a été corrigé.

Je suis d'accord avec toi sur presque tous les points.

Et vous avez raison, chaque cadre est mis en correspondance séparément, comme s'il s'agissait d'un onglet entier (avec son propre window et son propre document , intégré dans un cadre).

Eh bien, j'ai utilisé presque toujours la même structure de menu/cadre, alors je devrais peut-être en tester une autre.

Quand tu dis "ça a tiré", tu veux dire le pur appel de l'auditeur ?

Comme je l'ai dit, j'ai rencontré quelques exemples avec executeScript produisant une condition d'erreur, mais l'écouteur a quand même été appelé.

all_frames ne peut pas fonctionner, à cause du mauvais location (différent window , différent document ). BTW: Le menu ne gère que les URL mainframe de chaque onglet - si le menu est faux, cela ne veut pas dire que le script n'est pas appelé...

Quand tu dis "ça a tiré", tu veux dire le pur appel de l'auditeur ?

Dans ce message particulier, je voulais dire "La fonction transmise à onCommitted.addListener été appelée".

Bonjour,

J'ai lu attentivement ce post mais je ne comprends pas comment utiliser votre solution alternative sur mon script local ".user.js". Comment puis-je appliquer votre solution? Désolé, je suis nouveau.

(Depuis la mise à jour de Firefox, un popup-iframe généré n'est plus reconnu par le script supplémentaire, mais si j'ouvre le même popup dans une nouvelle fenêtre, le script est appliqué.)

Merci d'avance pour votre aide

Vous avez décrit exactement le problème : c'est comme si @noframes était activé. L'URL du contenu du cadre n'active pas correctement votre script. Espérons que cela soit bientôt corrigé (l'ouverture de cadres dans des fenêtres supplémentaires est ennuyeuse) ...

Merci Eselce.
Et toujours depuis la mise à jour de Firefox, je suis obligé dans l'entête de déclarer tous les scipts '.js' (avec require) déjà utilisés sur le site cible. (y compris jquerry)
Et ce n'est pas pareil... Cela crée des bugs ou des conflits.
Connaissez-vous aussi ce problème ?

2945 contient un autre exemple pour l'observation, que les scripts sont démarrés dans des trames, mais abandonnés après quelques millisecondes.

J'hésite à donner les URL spécifiques que je teste car elles sont hors de mon contrôle, mais je trouve un comportement cohérent mais étrange à transmettre.

J'ai un site avec lequel j'ai besoin d'interagir. Il charge initialement un jeu de cadres/cadre avec rows="100%,0" (un cadre pour remplir l'écran) sur un domaine différent. Cette trame contient un jeu de trames / 3 trames dans le domaine du jeu de trames/trame intermédiaire.

Certains des scripts GM des trames enfants 1+3 apparaîtront, puis disparaîtront après le cycle initial -- ils ne reviendront jamais après une opération asynchrone. Cela correspond à un comportement décrit sur ce fil. Notez que ceux qui « blip » et le comportement décrit ci-dessous varient selon la version du navigateur / GM, mais ce n'est pas aléatoire ; les modèles sont étranges mais reproductibles à 100% pour n'importe quelle configuration donnée.

  1. Le premier jeu de cadres/cadre n'apparaîtra JAMAIS. J'ai essayé de détacher et de reconstruire la balise du cadre, à la fois via window.document et unsafeWindow.document, à la fois dans le cycle initial et après un délai, mais rien n'empêchera le script GM de ce cadre de signaler quoi que ce soit à console.log. (Le @include est *, sans @exclude ou autre filtrage d'URL.)
  2. Certains des comportements ultérieurs différeront entre Firefox 52.8 / GM 4.1 et Firefox 60.0 / GM 4.3, mais je peux faire apparaître les scripts GM des cadres dans chaque cas, que @noframes soit défini ou non. C'est avec @includes *, pas d'autres filtres d'URL. Ceux-ci ne devraient jamais bipper avec
  3. Dans Firefox 52.8 / GM 4.1, le prochain jeu de cadres / 3 cadres apparaîtra TOUJOURS. Dans Firefox 60.0 / GM 4.3, ils ne "blip" pas lors du chargement initial de la trame.
  4. Dans Firefox 60.0 / GM 4.3, cliquer sur un lien dans l'un des 3 cadres qui navigue dans un autre des 3 cadres (via un attribut "cible" sur le lien d'ancrage, pas le script) fera "échouer" -- pas la nouvelle URL, mais l' ancienne URL du cadre parcouru. (Il s'agit de l'une des images qui s'est déclenchée lors du chargement initial dans l'élément n ° 3.)
  5. Voici la partie la plus étrange. Dans les deux configurations de navigateur --- En suivant les étapes, nous avons ouvert la page initiale avec 2 couches de jeux de cadres, 4 cadres au total, et cliqué sur un lien dans un cadre pour naviguer dans un autre cadre sur la même page. Pour donner des noms à cela, notre jeu de cadres de deuxième niveau initialement affiché avait des cadres "top.htm", "menu.htm" et "start,htm". Nous avons cliqué sur un lien dans le cadre "menu.htm" pour que le cadre contenant "start.htm" navigue vers "content.htm", avec un comportement similaire mais légèrement différent selon la configuration du navigateur, indiqué ci-dessus. Maintenant, nous cliquons sur un lien à l'intérieur du cadre "content.htm", pour naviguer dans le même cadre, même domaine.

À ce stade, le script pour "content.htm" ne fera pas que "blip"... il restera également actif après la fin d'un GM.xmlHttpRequest -- un événement asynchrone. À ce stade, "content.htm" n'est nulle part sur l'affichage du navigateur, mais son script continuera à fonctionner.

Il me semble donc que la raison pour laquelle les scripts GM sur les pages dans les cadres ne fonctionnent pas est que le script est chargé lors du déchargement de la page au lieu du chargement de la page. Définir @run-at sur document-start et placer le script dans un événement DOMContentReady de unsafeWindow.document n'a eu aucune amélioration. (Le définir sur window.document ne déclenche jamais l'événement.)

-Ryan

Dans Firefox 52.8 / GM 4.1, le prochain jeu de cadres / 3 cadres apparaîtra TOUJOURS. Dans Firefox 60.0 / GM 4.3, ils ne "blip" pas lors du chargement initial de la trame.

Lors de la transition vers Firefox 57, Mozilla a changé _quelque chose_. Quoi qu'il en soit, cela a changé (ou cassé) la façon dont les Frames pouvaient être déclenchées. Cela a été brièvement évoqué dans un autre numéro. En conséquence, les scripts ne s'exécuteraient pas lors du chargement initial de la trame (57+).

Le passage éventuel aux API userScript ou contentScript devrait résoudre tout cela de toute façon.

Alors les gens n'arrêtent pas de le dire, mais Violentmonkey continue de s'exécuter en images. VM ne sépare pas correctement les scripts utilisateur du contenu de la page Web (les CSP bloquent les scripts utilisateur, les pages Web peuvent réécrire des objets globaux, etc.), ou j'aurais jeté Greasemonkey il y a longtemps. Ce sont peut-être des problèmes liés, mais j'utilise des moteurs de script utilisateur, je n'ai donc pas à explorer suffisamment le chrome de Firefox pour le découvrir par moi-même.

Hmm c'est un problème difficile, certains de mes scripts ne fonctionnent plus car ils ne peuvent pas fonctionner avec les iframes. Il semble donc qu'il ne soit pas vraiment possible de le réparer, et nous devons faire en sorte que Mozilla implémente une API ? N'y a-t-il rien que nous puissions faire nous-mêmes, comme une solution de contournement ? J'ai juste besoin de faire quelques trucs sur une page dans un iframe, souvent même à partir du même domaine.

Ma propre solution de contournement pour le moment consiste à exécuter Greasemonkey dans les cadres supérieurs et Violentmonkey dans les cadres enfants. Je ne peux pas utiliser Tampermonkey car il a une licence maison ambiguë, mais si ce n'est pas un problème pour vous, alors cela pourrait ou non fonctionner mieux.

Gardez à l'esprit que VM dépose le script dans le propre contexte de la page. C'est comme unsafeWindow de GM sans l'équivalent sûr. L'un des moments les plus mémorables que j'ai eu a été de déboguer un script où le contenu de la page avait défini une méthode "toJSON ()" sur Array.prototype, ce qui a amené JSON.stringify () à cracher du JSON invalide dans mon script. J'ai dû piègez défensivement et réparez-les comme je les ai trouvés.

Un autre problème majeur avec VM est qu'il respecte la politique de sécurité du contenu de la page de contenu, donc toute directive qui limite les sources de script fera que le script VM ne s'exécutera jamais. Vous pouvez le voir dans la console du navigateur (mais pas dans la console Web). C'est pourquoi je ne peux pas exécuter VM entièrement et me débarrasser de GM. Je n'ai pas encore rencontré de frme enfant avec un ensemble CSP, mais quand je le ferai, ce sera complètement inutilisable.

@RyanHanekamp Merci pour le conseil ! Peut-être que j'utiliserai Violentmonkey pour certains scripts, alors.

Violent a-t-il également quelque chose comme GM_getValue synchrone ? C'est un autre problème problématique qui casse une tonne de scripts dans le nouveau Greasemonkey. Je fais toujours confiance à Greasemonkey, cependant, pour diverses raisons, donc je ne le quitterai pas.

Quant aux iframes, j'ai essayé de les remplacer par des balises d'objet, auxquelles on peut apparemment accéder directement en utilisant Javascript, comme ceci :

myObject= document.createElement('object');
myObject.setAttribute('id', 'myObject'); 
document.body.appendChild(myObject);
myObject.setAttribute('src', 'https://example.com');

Ensuite, une fois l'objet chargé :
document.querySelector('#myObject').contentDocument.defaultView.document.querySelectorAll('someElementInsideObjectPage')
Au moins, cela fonctionne pour moi dans un script où l'objet est sur le même hôte que la page principale. Vous pouvez également envoyer des messages depuis et vers ( ... contentDocument.defaultView.postMessage('hello, object') ) l'objet.

Je ne suis pas un expert en VM, mais je pense qu'il implémente au moins la plupart de l'API GM_* d'origine. Je pense qu'il vaut mieux adapter vos scripts à l'asynchrone que de revenir en arrière sur une plate-forme synchrone à long terme. D'après ce que j'ai compris, Greasemonkey a fait cela pour améliorer les performances dans le nouveau framework Quantum, qui n'autorise pas les appels synchrones entre les scripts d'arrière-plan et de contenu.

Quant à la solution objet, elle ne résoudra pas mon problème particulier, mais je suis content que d'autres l'aient trouvée utile. Mis à part le marshaling CSS / properties / etc et le faire fonctionner avec des cadres ainsi que des iframes, je dois filtrer les objets dans un processus de capture comme potentiellement dangereux. Il existe des moyens de contourner tous ces problèmes, mais VM était l'intérim le plus facile jusqu'à ce que GM fasse enfin ce qu'il dit sur l'étain.

De plus, si vous avez un cadre/iframe de même origine, vous pouvez également accéder directement au contenu de ceux-ci. La partie la plus difficile est l'origine croisée, c'est pourquoi j'ai besoin de scripts utilisateur à l'intérieur du cadre. Il configure un canal window.postMessage() pour répondre à la fenêtre parent.

@RyanHanekamp Bon à savoir que Violent Monkey a toujours l'ancien et simple GM_*. J'aurais vraiment aimé que Greasemonkey conserve l'ancien GM_getValue synchrone pour la compatibilité descendante, en plus de la nouvelle version. Je pourrais essayer d'implémenter la nouvelle fonction asynchrone dans un nouveau script, mais je ne suis pas un programmeur et je ne sais pas si je pourrais le faire fonctionner. Et je suis certainement incapable de refactoriser l'utilisation de l'ancien GM_getValue dans un ancien script de 2000 lignes que j'ai trouvé en ligne... tellement de scripts sont cassés maintenant.

Je comprends pourquoi Violent était la meilleure option pour vous. Espérons qu'Anthony ou Sxderp ou quelqu'un d'autre découvre comment implémenter cela éventuellement. J'aimerais vraiment pouvoir contribuer, mais je suis un profane total.

Oh, vous pouvez accéder directement au contenu d'un iframe de même origine (sans postMessage etc.) ? Je me souviens avoir passé beaucoup de temps à essayer de trouver un moyen, mais cela ne semblait pas possible. C'est pourquoi je suis également passé à postMessage.

Les cadres et les iframes ont une propriété contentWindow équivalente à la propriété window. Les deux ont une propriété de document pour accéder au DOM.

La partie la plus difficile de travailler avec des iframes (sur la même origine) est de détecter quand son contenu est chargé, car vous ne pouvez pas faire de squat avant que cela ne se produise. onload ne fonctionne pas à quoi il ressemble. Firefox fournit un événement DOMFrameContentLoaded qui se déclenche pour CHAQUE trame chargée, y compris les trames petits-enfants / arrière-petits-enfants, etc., que vous pouvez faire correspondre à l'élément frame / iframe d'origine avec la propriété event.target. Si vous contrôlez le contenu du frame/iframe, vous pouvez également le faire répondre au parent avec postMessage ou en appelant une méthode globale sur l'objet window.parent.

En parlant de ça... c'est une solution de contournement potentielle pour ce problème. S'il existe ou pourrait exister un moyen de coder un script GM pour injecter manuellement un script utilisateur dans une référence de fenêtre inter-domaines, cela prendrait beaucoup plus de codage pour le créateur du script utilisateur, mais cela pourrait faire le travail. Le modèle serait d'écouter DOMFrameContentLoaded, de vérifier si event.target est de première génération et d'injecter manuellement le script si c'est le cas. (En supposant que le script du cadre de première génération puisse écouter DOMContentLoaded pour les cadres de deuxième génération, et ainsi obtenir une chaîne complète.) Il n'y aurait aucun moyen d'obtenir le comportement @run-at dom-start, et il pourrait également y avoir des problèmes de synchronisation, mais nous pourrions probablement les contourner pour la plupart des cas d'utilisation.

J'ai personnellement renoncé à ce que ce problème soit résolu et je suis plutôt passé au codage direct d'une extension. Ce qui fonctionne bien dans tous les cadres!

La différence entre Greasemonkey et Violentmonkey sur ce point semble être que Violentmonkey est déclenché à partir de scripts de contenu avec all_frames défini sur true, tandis que Greasemonkey n'a pas de scripts de contenu au moment de l'installation et repose entièrement sur la capacité douteuse du script d'arrière-plan à renifler lorsqu'un le cadre de l'onglet a navigué. (Et Violentmonkey échoue sur les pages CSP car il injecte temporairement une balise SCRIPT au lieu d'utiliser le tabs.executeScript() bien plus sûr.)

Insérez un script de contenu statique avec all_frames, run_at start, correspond à tout pour notifier le processus d'arrière-plan pour start / document.DOMContentLoaded / document.Idle pour déclencher des scripts utilisateur pour chaque run_at, et vous êtes prêt à partir. Une quantité de travail non négligeable mais gérable pour faire disparaître ce problème. Je le réparerais moi-même, mais je n'ai aucun intérêt à parcourir vos dépendances de développement et je ne pourrais produire que le code de sortie.

@Ryan Hanekamp

et sont plutôt passés au codage direct d'une extension. Ce qui fonctionne bien dans tous les cadres!

Seriez-vous prêt à partager votre code d'extension ?

Mon extension n'est pas d'usage général. Le fait est qu'en utilisant un content_script statique dans le manifeste avec all_urls, all_frames exécutera le script chaque fois qu'un cadre est chargé ou parcouru, et peut même eval / Function le code du constructeur très bien quelle que soit la Content-Security-Policy de la page.

Je n'ai pas testé avec des cadres/fenêtres construits par programmation, mais j'imagine qu'ils s'exécuteraient lors de la création initiale quel que soit le paramètre run_at, car ces cadres sont initialement créés vides puis remplis - le moteur ne verra probablement que la création initiale. Je n'ai pas non plus testé les données : urls, qui pourraient nécessiter une correspondance explicite -- je ne sais pas si all_urls les couvre, ou simplement http/https.

Il n'est peut-être pas nécessaire qu'il s'agisse d'une référence content_script statique non plus, mais il semble incertain d'après la documentation si les scripts de contenu invoqués dynamiquement se chargent automatiquement lorsque la page est parcourue. J'ai l'impression qu'ils ne sont injectés que dans les onglets/cadres correspondants actuellement selon le modèle de correspondance fourni, et la navigation ne déclenche pas de réinjection. Mais je ne vois aucun inconvénient à utiliser un content_script statique à cette fin.

Greasemonkey ne peut évidemment pas inclure de scripts utilisateur en tant que ressources statiques dans le manifeste, et les scripts de contenu ne semblent pas avoir un accès direct à tabs.executeScript (bien que je ne sois guère un expert en la matière car je ne suis que depuis quelques jours), mais ce qu'un script de contenu statique PEUT faire, c'est envoyer un message au processus d'arrière-plan pour lui faire savoir que le frameId a été parcouru et vers quelle URL. Ce serait plus fiable que la façon dont je perçois les tentatives mentionnées sur ce fil pour accrocher le bon événement dans webRequest ou webNavigation. Le signal du content_script statique devient l'événement que nous recherchons pour déclencher le chargeur/injecteur de script utilisateur de Greasemonkey.

Il y aurait peut-être un délai pour les scripts utilisateur qui DOIVENT strictement run_at document_start. L'appel au script d'arrière-plan est asynchrone et le document aura progressé au moment où le script utilisateur est appelé. C'est très probablement pourquoi Violentmonkey utilise une balise de script temporaire au lieu de tabs.executeScript, car l'injection de balise de script peut être effectuée directement à partir de content_script, de manière synchrone. Je trouverais qu'être obligé de contourner l'incertitude de l'état du document pour run_at document_start est gênant, mais préférable au script qui ne s'exécute pas du tout.

Greasemonkey ... PEUT [utiliser un script de contenu statique pour] envoyer un message au processus d'arrière-plan pour lui faire savoir que le frameId a été parcouru et vers quelle URL ...

C'est ce que nous utilisons pour faire pour détecter .user.js navigations. Cela semble être une bonne solution évidente : détecter le contenu en exécutant un script de contenu !

Mais il s'avère que même les scripts de contenu d'extension peuvent être cassés par CSP (#2631 et http://bugzil.la/1267027 et http://bugzil.la/1411641).

Je peux exécuter mon propre plugin, y compris un constructeur Function() directement dans content_script, sur Firefox 60.0.1 et 52.8.1ESR avec l'ensemble CSP suivant :

données frame-src : ; object-src 'aucun'; script-src "aucun" ; données de style-src 'unsafe-inline' : ; connect-src "aucun" ; media-src 'aucun';

2631 a été fermé, apparemment parce que Firefox a corrigé son bogue sous-jacent. Le premier bugzilla fait référence à l'injection de balises de script (la méthode Violentmonkey), pas au content_script lui-même. Le second fait référence à l'attribut sandbox pour CSP, ce qui n'est pas surprenant car il oblige le domaine à ne jamais réussir une correspondance de domaine, même avec lui-même. Un peu comme NaN !==NaN.

Lorsque cela a été déposé pour la première fois il y a plusieurs mois, nous avons fait les choses différemment. Aujourd'hui, nous utilisons webNavigation.onCommitted pour détecter la navigation, et dans le test que

Bonjour, est-ce résolu maintenant ?

Je n'ai pas pu lancer un script que j'ai créé pour Tampermonkey sur une iframe avec Greasemonkey.

Le code d'exécution n'a pas été modifié de notre côté. Donc, à moins que Mozilla n'ait changé quelque chose de leur côté, c'est toujours en panne. Cependant, #2663 devrait le résoudre.

Il peut être intéressant de noter que Violentmonkey et Tampermonkey fonctionnent très bien dans les cadres intégrés.

Tampermonkey a des problèmes avec les iframes dans Chrome, du moins pour moi.

Il peut être intéressant de noter que Violentmonkey et Tampermonkey fonctionnent très bien dans les cadres intégrés.

Tampermonkey a des problèmes avec les iframes dans Chrome, du moins pour moi.

Mais cela fonctionne pour moi dans Firefox Violentmonkey. Alors je me demande comment ça peut fonctionner là-bas?

Je viens de remarquer qu'un script utilisant l'ancienne synchronisation GM_GetValue fonctionne toujours correctement dans Violentmonkey. Comment est-ce possible? Je pensais que Firefox avait forcé GM.GetValue asynchrone ? Je suis tellement confus maintenant : Violentmonkey a probablement dû sacrifier autre chose pour continuer à prendre en charge la synchronisation et les autres éléments ?

@Cerberus-tm Le changement dans Firefox signifiait que les données ne pouvaient être demandées qu'à partir du stockage d'extension ou du contexte d'arrière-plan de manière asynchrone (les scripts utilisateur eux-mêmes sont envoyés au script de contenu de manière asynchrone). Cependant, les données pourraient être fournies aux scripts utilisateur de manière synchrone, si chaque script de contenu GM4 prélecture et met en cache dans le script de contenu les données stockées pour chaque script utilisateur chargé dans cette page.

Un tel cache permettrait au script de contenu de répondre de manière synchrone aux demandes de données du script utilisateur. La mise en œuvre d'un cache se heurte à des problèmes de maintien de la cohérence entre les différents scripts de contenu, mais cela peut être résolu en faisant en sorte que les scripts de contenu écoutent toutes les modifications apportées au stockage d'extension de GM4. De plus, si un script utilisateur stocke une grande quantité de données, la mise en cache dans chaque script de contenu où le script utilisateur est exécuté augmente également considérablement la mémoire requise pour chaque script de contenu.

TM et VM ont choisi de faire quelque chose de similaire à ce qui précède afin de ne pas rompre la compatibilité avec les API Greasemonkey d'origine lorsque ces gestionnaires de script utilisateur ont été implémentés pour Chrome, qui a les mêmes restrictions. communication asynchrone avec stockage d'extension, etc. Étant donné qu'ils le font déjà pour Chrome, il n'y avait aucune raison pour qu'ils changent une fois implémentés pour Firefox.

Ainsi, le basculement de FF57 vers WebExtensions a forcé une réécriture de GM, mais il n'a pas forcé l'adoption des API asynchrones pour GM.getValue , GM.setValue , etc. WebExtensions a utilisé Les API basées sur l'async sont plus faciles à implémenter que ne le seraient les synchrones, mais cela ne les rendait pas nécessaires.

Personnellement, je pense que le choix, et d'autres choix pour rompre la compatibilité, étaient/sont malheureux. Le manque de rétrocompatibilité avec les scripts qui fonctionnaient bien dans GM3 et/ou la compatibilité avec TM a poussé de nombreuses personnes à choisir de ne pas utiliser GM4. Mon expérience est que bien plus de 30 des scripts utilisateur que j'utilise, qui ont tous bien fonctionné dans GM3, ne fonctionnent pas avec GM4 (ou du moins ne fonctionnaient pas avant d'être réécrits pour être compatibles avec GM4). Il y a encore 28 userscripts que j'utilise quotidiennement qui fonctionnaient bien sous GM3 qui ne fonctionnent pas avec GM4.

J'ai publié une solution de contournement à ce problème sur Stack Overflow comme réponse à la façon d' appliquer un Greasemonkey/‌Tampermonkey/‌userscript à un iframe . Fondamentalement, j'attends que la trame se charge, puis j'opère sur le tableau window.frames . J'utilise un marqueur personnalisé dans le corps de chaque cadre pour indiquer que j'ai déjà vu le cadre.

Peut-être que Greasemonkey pourrait implémenter une solution de la même manière ?

Ce serait génial si nous avions aussi un GM.waitFor(css_selector, action_function) comme waitForKeyElements() , mais c'est un aparté.

Cette page vous a été utile?
0 / 5 - 0 notes