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 précharger les navigations. Pour en savoir plus, reportez-vous aux informations ci-dessous.

Chrome met tout en œuvre pour 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 retour et de suite. Dans ce post, nous allons passer en revue les mises à jour que nous avons apportées aux API des extensions de navigateur pour s'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 avait qu'une seule partie pour un onglet, à savoir 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'y a plus de relation un à un entre les onglets et les pages. Désormais, chaque onglet stocke plusieurs pages, et les pages passent d'un état à un 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, le tout sans jamais être détruite. Plus loin dans cet article, nous examinerons les nouvelles propriétés exposées pour aider les extensions à comprendre l'état des pages.

Types de page
Types de pages

Notez qu'un onglet peut contenir une série de pages prérendues (pas seulement une), une seule page active (visible) et une série de pages mises en cache aller/retour.

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

Identifiant frame == 0

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

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

Cycle de vie des cadres par rapport aux documents

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

Événements de navigation sur le 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 ils se trouvent. Consultez les sections Comment savoir dans quel cycle de vie se trouve la page ? et Comment déterminer à quel moment une page effectue une transition.

Comment savoir dans quel cycle de vie se trouve la page ?

Le type DocumentLifecycle a été ajouté à un certain nombre d'API d'extensions où frameId était auparavant disponible. Si le type DocumentLifecycle est présent sur un événement (par exemple, 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 méthode, 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" : non présenté à l'utilisateur pour le moment, mais en préparation pour éventuellement l'afficher.
  • "active": présentation présentée à l'utilisateur.
  • "cached": stocké dans le cache amélioré.
  • "pending_deletion": le document est en cours de destruction.

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

Auparavant, les extensions avaient peut-être vérifié si frameId == 0 pour déterminer si l'événement se produisait concerne le frame le plus externe ou non. Avec plusieurs pages dans un onglet, nous avons désormais plusieurs frames les plus externes. La définition de frameId pose donc problème. Vous ne recevrez jamais d'événements concernant un frame mis en cache amélioré. 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 ainsi facile de déterminer si le frame est effectivement le frame le plus externe. FrameType a les valeurs suivantes:

  • "outermost_frame": généralement appelé cadre supérieur. Notez qu'il existe des multiples de ces valeurs. Par exemple, si vous avez des pages prérendues et mises en cache, chacune comporte un cadre de plus haut niveau pouvant être appelé cadre supérieur.
  • "fenced_frame": réservé pour une utilisation ultérieure.
  • "sub_frame": il s'agit généralement d'un iFrame.

Nous pouvons combiner DocumentLifecycle avec FrameType et déterminer si un frame est le frame le plus externe actif. Par exemple, js tab.documentLifecycle == “active” && frameType == “outermost_frame”.

Comment résoudre les problèmes liés au temps d'utilisation avec les frames ?

Comme nous l'avons dit ci-dessus, un cadre héberge un document, et le cadre peut accéder à un nouveau document, mais le frameId ne change pas. Cela crée des problèmes lorsque vous recevez un événement avec simplement un frameId. Si vous recherchez l'URL du frame, elle peut être différente du moment où l'événement s'est produit. C'est ce qu'on appelle un problème lié au moment de l'utilisation.

Pour résoudre ce problème, nous avons introduit documentId (et parentDocumentId). La méthode webNavigation.getFrame() rend désormais frameId facultatif si un documentId est fourni. documentId change à chaque navigation dans un cadre.

Comment déterminer à quel moment une page passe à la suivante ?

Des signaux explicites permettent de déterminer à quel moment 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 listé ci-dessous. Notez que ces quatre événements peuvent se produire avec l'état DocumentLifecycle correspondant à "prerender" ou "active".

onBeforeNavigate
onCommitted
onDOMContentLoaded
onCompleted

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

Le documentId change lorsque la page prérendue devient la page active.
Le 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 étant "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 sur le groupe chromium-extensions.