תוספים ל-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.