Extensions Chrome: API étendue pour prendre en charge la navigation instantanée

Dave Tapuska
Dave Tapuska

Résumé: L'API Extensions a été mise à jour pour prendre en charge le cache amélioré et le préchargement des navigations. Pour en savoir plus, reportez-vous aux informations ci-dessous.

Chrome s'efforce d'accélérer la navigation. Les technologies de navigation instantanée telles que le cache amélioré (expédié sur ordinateur dans Chrome 96) et les règles de spéculation (expédiées dans Chrome 103) améliorent à la fois l'expérience de navigation précédente et ultérieure. Dans cet article, nous allons explorer les mises à jour que nous avons apportées aux API des extensions de navigateur pour les adapter à ces nouveaux workflows.

Comprendre les types de pages

Avant l'introduction du cache amélioré et du prérendu, un onglet individuel ne comportait qu'une seule page active. C'était toujours celui qui était visible. Si un utilisateur revient à la page précédente, la page active est détruite (page B) et la page précédente de l'historique est entièrement reconstruite (page A). Les extensions n'avaient pas à se soucier de la partie du cycle de vie des pages, car il n'y en avait qu'une par onglet, c'est-à-dire l'état actif/visible.

Éviction de la page active
Éviction de la page active.

Avec le cache amélioré et le prérendu, il n'existe plus de relation de type un à un entre les onglets et les pages. Désormais, chaque onglet stocke en fait plusieurs pages, et les pages passent d'un état à l'autre au lieu d'être détruites et reconstruites.

Par exemple, une page peut commencer sa vie en tant que page prérendue (non visible), passer à une page active (visible) lorsque l'utilisateur clique sur un lien, puis être stockée dans le cache amélioré (non visible) lorsque l'utilisateur accède à une autre page, sans que la page ne soit détruite. Plus loin dans cet article, nous examinerons les nouvelles propriétés exposées pour aider les extensions à comprendre en quoi consistent les pages d'état.

Types de page
Types de pages
:

Notez qu'un onglet peut avoir une série de pages prérendues (pas une seule), une seule page active (visible) et une série de pages mises en cache avant/arrière.

Qu'est-ce qui change pour les développeurs d'extensions ?

FrameId == 0

Dans Chromium, le cadre supérieur/principal est le cadre externe.

Les auteurs d'extensions qui supposent que le frameId de l'image externe est 0 (bonne pratique précédente) peuvent rencontrer des problèmes. Étant donné qu'un onglet peut désormais avoir plusieurs frames externes (pages prérendues et mises en cache), l'hypothèse selon laquelle il existe un seul cadre externe pour un onglet est incorrecte. frameId == 0 continuera à représenter le cadre le plus externe de la page active, mais les cadres externes des autres pages du même onglet seront différents. Un nouveau champ frameType a été ajouté pour résoudre ce problème. Consultez la section Comment déterminer si un cadre est le cadre le plus externe ? de cet article.

Cycle de vie des frames et des documents

Un autre concept qui pose problème avec les extensions est le cycle de vie du frame. Un frame héberge un document (qui est associé à une URL validée). Le document peut changer (par exemple, en naviguant), mais pas le frameId. Il est donc difficile d'associer qu'un événement se produit dans un document spécifique à des frameIds uniquement. Nous introduisons le concept d'un documentId, qui est un identifiant unique pour chaque document. Si l’on navigue dans un cadre et qu’il ouvre un nouveau document, l’identifiant changera. Ce champ est utile pour déterminer à quel moment l'état du cycle de vie des pages change (entre le prérendu/actif/en cache), car il reste le même.

Événements de navigation Web

Les événements de l'espace de noms chrome.webNavigation peuvent se déclencher plusieurs fois sur la même page en fonction du cycle de vie dans lequel elle se trouve. Consultez les sections Comment déterminer le cycle de vie de la page ? et Comment déterminer quand une page passe d'une page à l'autre ?.

Comment déterminer le cycle de vie de la page ?

Le type DocumentLifecycle a été ajouté à un certain nombre d'API d'extensions dans lesquelles frameId était précédemment disponible. Si le type DocumentLifecycle est présent sur un événement (tel que onCommitted), sa valeur correspond à l'état dans lequel l'événement a été généré. Vous pouvez toujours interroger des informations à partir des méthodes WebNavigation getFrame() et getAllFrames(), mais il est toujours préférable d'utiliser la valeur de l'événement. Si vous utilisez l'une ou l'autre de ces méthodes, sachez que l'état de la trame peut changer entre le moment où l'événement a été généré et le moment où les promesses renvoyées par les deux méthodes sont résolues.

DocumentLifecycle a les valeurs suivantes:

  • "prerender" : actuellement non présenté à l'utilisateur, mais en préparation d'être éventuellement présenté à l'utilisateur.
  • "active": actuellement affiché à l'utilisateur.
  • "cached": stocké dans le cache amélioré.
  • "pending_deletion": le document est en cours de destruction.

Comment déterminer si une trame est la plus externe ?

Auparavant, les extensions pouvaient vérifier si frameId == 0 pour déterminer si l'événement se trouvait sur la frame la plus externe ou non. Lorsqu'un onglet contient plusieurs pages, nous disposons désormais de plusieurs cadres externes. La définition de frameId est donc problématique. Vous ne recevrez jamais d'événements à propos d'une image mise en cache en arrière-plan. Toutefois, pour les frames prérendus, la valeur frameId sera différente de zéro pour le frame le plus externe. Il est donc incorrect d'utiliser frameId == 0 comme signal pour déterminer s'il s'agit de la trame la plus externe.

Pour vous aider, nous avons introduit un nouveau type appelé FrameType. Il est donc maintenant facile de déterminer si le cadre est bien le cadre le plus externe. FrameType a les valeurs suivantes:

  • "outermost_frame": généralement appelé "cadre supérieur". Notez qu'il y en a plusieurs. Par exemple, si vous avez des pages prérendues et mises en cache, chacune dispose d'un cadre externe qui pourrait être appelé le cadre supérieur.
  • "fenced_frame": réservé pour une utilisation ultérieure.
  • "sub_frame": généralement un iFrame.

Nous pouvons combiner DocumentLifecycle avec FrameType et déterminer si une frame est la trame externe active. Exemple : js tab.documentLifecycle == “active” && frameType == “outermost_frame”

Comment résoudre les problèmes d'utilisation des cadres ?

Comme nous l'avons dit ci-dessus, un cadre héberge un document et peut accéder à un nouveau document, mais le frameId ne sera pas modifié. Cela crée des problèmes lorsque vous recevez un événement avec seulement un frameId. Si vous recherchez l'URL du frame, elle peut ne pas correspondre au moment où l'événement s'est produit, on parle de problème de temps d'utilisation.

Pour résoudre ce problème, nous avons introduit documentId (et parentDocumentId). La méthode webNavigation.getFrame() rend désormais la frameId facultative si un documentId est fourni. Le documentId change chaque fois que l'utilisateur navigue dans un frame.

Comment déterminer à quel moment une page effectue une transition ?

Des signaux explicites permettent de déterminer quand une page passe d'un état à un autre.

Examinons les événements WebNavigation.

Pour la toute première navigation d'une page, vous verrez quatre événements dans l'ordre indiqué ci-dessous. Notez que ces quatre événements peuvent se produire avec l'état DocumentLifecycle défini sur "prerender" ou "active".

onBeforeNavigate
onCommitted
onDOMContentLoaded
onCompleted

Ceci est illustré dans le schéma ci-dessous, qui montre que documentId devient "xyz" lorsque la page prérendue devient la page active.

L'ID du document change lorsque la page prérendue devient la page active.
La valeur documentId change lorsque la page prérendue devient la page active.

Lorsqu'une page passe du cache amélioré ou du prérendu à l'état actif, trois événements supplémentaires se produisent (mais DocumentLifecyle est "active").

onBeforeNavigate
onCommitted
onCompleted

Le documentId restera le même que dans les événements d'origine. Ceci est illustré ci-dessus lorsque documentId == xyz s'active. Notez que les mêmes événements de navigation se déclenchent, à l'exception de l'événement onDOMContentLoaded, car la page a déjà été chargée.

Si vous avez des commentaires ou des questions, n'hésitez pas à les poser dans le groupe chromium-extensions.