תוספים ל-Chrome: הרחבת ממשק ה-API לתמיכה בניווט מיידי

Dave Tapuska
Dave Tapuska

אמ;לק: Extensions API עודכן כדי לתמוך במטמון לדף הקודם/הבא, טעינה מראש של ניווטים. פרטים נוספים מופיעים בהמשך.

אנחנו משקיעים מאמצים רבים כדי שהניווט ב-Chrome יהיה מהיר. טכנולוגיות של ניווט מיידי, כמו מטמון לדף הקודם/הבא (שולחים למחשבים בגרסה 96 של Chrome) וכללי השערה (שולחים בגרסה 103 של Chrome), משפרות את חוויית המשתמש גם בחזרה וגם קדימה. בפוסט הזה נסביר על העדכונים שביצענו בממשקי ה-API של התוספים לדפדפן כדי להתאים אותם לתהליכי העבודה החדשים האלה.

הסבר על סוגי הדפים

לפני ההשקה של המטמון לדף הקודם/הבא והעיבוד מראש, בכרטיסייה מסוימת היה רק דף פעיל אחד. זה תמיד היה החשבון שמוצג. אם משתמש יחזור לדף הקודם, הדף הפעיל (דף ב') ייהרס והדף הקודם בהיסטוריה יבנה מחדש לגמרי (דף א'). למפתחי התוספים לא היה צורך לדאוג לגבי השלב במחזור החיים שבו הדפים נמצאים, כי היה רק שלב אחד לכרטיסייה – המצב הפעיל/גלוי.

פינוי הדף הפעיל
הוצאה של הדף הפעיל.

כשמשתמשים במטמון לדף הקודם/הבא ובעיבוד מראש, אין יותר יחס אחד לאחד בין הכרטיסיות לדפים. עכשיו כל כרטיסייה מאחסנת כמה דפים, והדפים עוברים בין מצבים במקום להימחק ולהיבנות מחדש.

לדוגמה, דף יכול להתחיל את חייו כדף שעבר רינדור מראש (לא גלוי), לעבור לדף פעיל (גלוי) כשהמשתמש לוחץ על קישור, ולאחר מכן להישמר במטמון לדף הקודם/הבא (לא גלוי) כשהמשתמש מנווט לדף אחר, והכול בלי שהדף יימחק. בהמשך המאמר נבחן את המאפיינים החדשים שאנחנו חושפים כדי לעזור לתוספים להבין את המצב של דפי הסטטוס.

סוגי דפים
סוגי דפים.

חשוב לזכור שכרטיסייה יכולה לכלול סדרה של דפים שעברו עיבוד מראש (לא רק דף אחד), דף פעיל (גלוי) אחד וסדרה של דפים שנשמרו במטמון לדף הקודם/הבא.

מה משתנה מבחינת מפתחי התוספים?

FrameId == 0

ב-Chromium, אנחנו מתייחסים למסגרת העליונה או הראשית כאל המסגרת החיצונית ביותר.

יכול להיות שייווצרו בעיות אצל מחברי התוספים שמניחים שהערך של frameId של הפריים החיצוני ביותר הוא 0 (שיטה מומלצת קודמת). מאחר שכרטיסייה יכולה לכלול עכשיו כמה מסגרות חיצוניות (דפים שעבר עליהם עיבוד מראש וששמורים במטמון), ההנחה שיש מסגרת חיצונית אחת לכרטיסייה שגויה. הערך של frameId == 0 עדיין ימשיך לייצג את המסגרת החיצונית ביותר של הדף הפעיל, אבל הערכים של המסגרות החיצוניות ביותר של דפים אחרים באותה כרטיסייה לא יהיו אפס. כדי לפתור את הבעיה הזו, הוספנו את השדה החדש frameType. אפשר לעיין בקטע איך בודקים אם פריים הוא הפריים החיצוני ביותר? בפוסט הזה.

מחזור החיים של מסגרות לעומת מסמכים

רעיון נוסף שעלול לגרום לבעיות בהרחבות הוא מחזור החיים של המסגרת. מסגרת מארחת מסמך (שמשוייך לכתובת URL שהובטחה). המסמך יכול להשתנות (למשל, באמצעות ניווט), אבל הערך של frameId לא ישתנה, ולכן קשה לשייך אירוע למסמך ספציפי רק באמצעות frameIds. אנחנו משיקים את המושג documentId, שהוא מזהה ייחודי לכל מסמך. אם עוברים לפריים אחר ופותחים מסמך חדש, המזהה ישתנה. השדה הזה שימושי כדי לקבוע מתי דפים משנים את מצב מחזור החיים שלהם (בין עיבוד מראש/פעיל/שמור במטמון), כי הוא נשאר ללא שינוי.

אירועי ניווט באינטרנט

אירועים במרחב השמות chrome.webNavigation יכולים להתרחש כמה פעמים באותו דף, בהתאם למחזור החיים שבו הם נמצאים. אפשר לעיין בקטעים איך אפשר לדעת באיזה שלב במחזור החיים הדף נמצא? ואיך אפשר לקבוע מתי דף עובר מעבר?

איך אפשר לדעת באיזה שלב מחזור חיים הדף נמצא?

הסוג DocumentLifecycle התווסף למספר ממשקי API של תוספים שבהם הסוג frameId היה זמין בעבר. אם הסוג DocumentLifecycle מופיע באירוע (למשל onCommitted), הערך שלו הוא המצב שבו האירוע נוצר. תמיד אפשר לשלוח שאילתות לגבי מידע מהשיטות WebNavigation getFrame() ו-getAllFrames(), אבל תמיד עדיף להשתמש בערך מהאירוע. אם משתמשים באחת מהשיטות, חשוב לזכור שהמצב של המסגרת עשוי להשתנות בין הזמן שבו האירוע נוצר לבין הזמן שבו הפתרון של ההבטחות שחוזרות בשתי השיטות.

הערכים של DocumentLifecycle הם:

  • "prerender" : לא מוצג כרגע למשתמש, אבל ייתכן שהוא יוצג לו.
  • "active": מוצגת כרגע למשתמש.
  • "cached": מאוחסן במטמון לדף הקודם/הבא.
  • "pending_deletion": המסמך מושמד.

איך אפשר לקבוע אם מסגרת מסוימת היא המסגרת החיצונית ביותר?

בעבר, תוספים אולי בדקו אם frameId == 0 כדי לקבוע אם האירוע שמתרחש הוא לפריים החיצוני ביותר או לא. כשיש כמה דפים בכרטיסייה, עכשיו יש כמה מסגרות חיצוניות, ולכן ההגדרה של frameId בעייתית. לעולם לא תקבלו אירועים לגבי מסגרת שנשמרה במטמון לדף הקודם/הבא. עם זאת, עבור פריימים שעברו עיבוד מראש, הערך של frameId יהיה שונה מאפס עבור המסגרת החיצונית ביותר. לכן, שימוש ב-frameId == 0 כאות לקביעת אם זהו המסגרת החיצונית הוא שגוי.

כדי לעזור בכך, הוספנו סוג חדש שנקרא FrameType, כך שקל יותר לקבוע אם המסגרת היא אכן המסגרת החיצונית ביותר. ל-FrameType יש את הערכים הבאים:

  • "outermost_frame": בדרך כלל נקראת המסגרת העליונה. שימו לב שיש ערכים מרובים של כל אחד מהם. לדוגמה, אם יש לכם דפים שעברו עיבוד מראש ונשמרו במטמון, לכל אחד מהם יש מסגרת חיצונית שאפשר לכנות אותה המסגרת העליונה.
  • "fenced_frame": שמור לשימוש עתידי.
  • "sub_frame": בדרך כלל iframe.

אפשר לשלב את DocumentLifecycle עם FrameType ולקבוע אם מסגרת מסוימת היא המסגרת החיצונית הפעילה. לדוגמה: tab.documentLifecycle === “active” && frameType === “outermost_frame”

איך פותרים בעיות שקשורות לזמן השימוש בפריימים?

כפי שציינו למעלה, מסגרת מארחת מסמך, והמסגרת עשויה לנווט למסמך חדש, אבל הערך של frameId לא ישתנה. זה יוצר בעיות כשמקבלים אירוע עם frameId בלבד. אם מחפשים את כתובת ה-URL של המסגרת, יכול להיות שהיא תהיה שונה מזו שהיתה בזמן האירוע. זוהי בעיה שנקראת 'בעיה בזמן השימוש'.

כדי לטפל בבעיה הזו, הוספנו את documentId (וגם את parentDocumentId). השיטה webNavigation.getFrame() מאפשרת עכשיו להשתמש ב-frameId באופן אופציונלי אם מציינים documentId. הערך של documentId ישתנה בכל פעם שעוברים לפריים אחר.

איך אפשר לקבוע מתי מתבצע מעבר בין דפים?

יש אותות מפורשים שבעזרתם אפשר לקבוע מתי דף עובר בין מצבים.

נבחן את האירועים מסוג WebNavigation.

בפעם הראשונה שתבצעו ניווט בדף כלשהו, יוצגו לכם ארבעה אירועים בסדר שמופיע בהמשך. חשוב לזכור שארבעת האירועים האלה יכולים להתרחש כאשר המצב של DocumentLifecycle הוא "prerender" או "active".

onBeforeNavigate
onCommitted
onDOMContentLoaded
onCompleted

התהליך הזה מוצג בתרשים הבא, שבו אפשר לראות את השינוי מ-documentId ל-"xyz" כשהדף שעבר עיבוד מראש הופך לדף הפעיל.

השדה documentId משתנה כשהדף שעבר עיבוד מראש הופך לדף הפעיל
הערך של documentId משתנה כשהדף שעבר עיבוד מראש הופך לדף הפעיל.

כשדף עובר מהמטמון לדף הקודם/הבא או מעיבוד מראש למצב פעיל, מתרחשים שלושה אירועים נוספים (אבל הערך של DocumentLifecyle הוא "active").

onBeforeNavigate
onCommitted
onCompleted

הערך של documentId יישאר זהה לזה שבאירועים המקוריים. הדוגמה שלמעלה ממחישה את המצב הזה כשהביטוי documentId == xyz מופעל. חשוב לזכור שאותם אירועי ניווט מופעלים, מלבד האירוע onDOMContentLoaded, כי הדף כבר נטען.

אם יש לכם הערות או שאלות, אתם מוזמנים לפרסם אותן בקבוצה chromium-extensions.