על מה מדובר?
המעבר מ-Manifest V2 ל-Manifest V3 כולל שינוי מהותי. ב-Manifest V2, התוספים היו בדף רקע. דפי הרקע ניהלו את התקשורת בין התוספים לדפי האינטרנט. במקום זאת, ב-Manifest V3 נעשה שימוש ב-service workers.
בפוסט הזה נתעמק בבעיה של בדיקת עובדים בשירותי התוספים. במיוחד, נראה איך לוודא שהמוצר שלנו פועל כמו שצריך במקרה שגורם כלשהו יפסיק את השירות של עובד השירות.
מי אנחנו?
eyeo היא חברה שמטרתה לאפשר למשתמשים, לדפדפנים, למפרסמים ולבעלי תוכן דיגיטלי להפיק ערך מאוזן ובר-קיימא באינטרנט. יש לנו יותר מ-300 מיליון משתמשים ברחבי העולם שמשתמשים בסינון מודעות ומאפשרים את הצגת 'מודעות מקובלות' – תקן מודעות שפותח באופן עצמאי ומאפשר לקבוע אם מודעה מקובלת ולא פולשנית.
צוות Extension Engine שלנו מספק טכנולוגיית סינון מודעות שמפעילה חלק מהתוספים הפופולריים ביותר לחסימת מודעות בדפדפן בשוק, כמו AdBlock ו-Adblock Plus, שיש להם יותר מ-110 מיליון משתמשים ברחבי העולם. בנוסף, אנחנו מציעים את הטכנולוגיה הזו כספרייה של קוד פתוח, כך שהיא זמינה לתוספים אחרים לדפדפן לסינון מודעות.
מהו רכיב Service Worker?
שירותי העבודה של התוסף הם הגורם המרכזי שמטפל באירועים של תוסף הדפדפן. הם פועלים באופן עצמאי ברקע. באופן כללי, זה בסדר. אנחנו יכולים לבצע את רוב הפעולות שאנחנו צריכים לבצע בדף רקע ב-service worker החדש. עם זאת, יש כמה שינויים בהשוואה לדפים ברקע:
- השירותים של עובדים נגמרים כשהם לא בשימוש. לשם כך, אנחנו צריכים לשמור את מצבי האפליקציה במקום להסתמך על משתנים גלובליים. המשמעות היא שכל נקודות הכניסה למערכת שלנו צריכות להיות מוכנות לקריאה לפני שהמערכת מופעלת.
- צריך לצרף מאזינים לאירועים לפני שממתינים להודעות חזרה (callbacks) אסינכררוניות. שירותי עובדים שהושהו עדיין יכולים לקבל אירועים שהם נרשמו אליהם. אם מאזין האירוע לא רשום בסיבוב הראשון של לולאת האירועים, הוא לא יקבל את האירוע אם האירוע הזה עורר את ה-service worker.
- סיום במצב חוסר פעילות יכול להפריע למערכי הזמן לפני שהם מסתיימים.
מתי שירותי ה-Workers מושהים?
ב-Chrome 119, גילינו ששירותי ה-workers מושהים:
- אחרי 30 שניות ללא קבלת אירועים או קריאה לממשקי API של תוספים.
- אף פעם אם הכלים למפתחים פתוחים או אם אתם משתמשים בספריית בדיקות שמבוססת על ChromeDriver (בקשת תכונת).
- אם לוחצים על Stop בכתובת chrome://serviceworker-internals.
למידע עדכני יותר, אפשר לעיין במאמר מחזור החיים של קובצי שירות (service worker).
למה קשה לבדוק את זה?
באופן אידיאלי, היה רצוי לקבל הנחיות רשמיות בנושא 'איך לבדוק שירותי עובדים בצורה יעילה' או דוגמאות לבדיקות שפועלות. במהלך הניסויים שלנו בבדיקת שירותי העבודה, נתקלו בכמה אתגרים:
- יש לנו מצב בתוסף הבדיקה. כשה-service worker מפסיק לפעול, אנחנו מאבדים את המצב שלו ואת האירועים הרשומים שלו. איך נשמור נתונים בתהליך הבדיקה?
- אם אפשר להשעות את שירותי ה-Worker בכל שלב, אנחנו צריכים לבדוק שכל התכונות פועלות גם אם הן מופסקות.
- גם אם נוסיף למבדקים שלנו מנגנון להשעיה אקראית של שירותי העבודה, אין בדפדפן ממשק API שאפשר להשתמש בו כדי להשעות אותם בקלות. ביקשנו מצוות W3C להוסיף את התכונה הזו, אבל זהו תהליך מתמשך.
בדיקת השעיה של קובץ שירות
ניסינו כמה גישות להפעלת השעיה של שירות העבודה במהלך הבדיקות:
גישה | בעיות בגישה |
ממתינים פרק זמן שרירותי (לדוגמה, 30 שניות) | לכן, הבדיקה איטית ולא מהימנה, במיוחד כשמריצים כמה בדיקות. האפשרות הזו לא פועלת כשמשתמשים ב-WebDriver, כי WebDriver משתמש ב-DevTools API של Chrome, ו-service worker לא מושעה כש-DevTools פתוח. גם אם נוכל לעקוף את הבעיה, עדיין נצטרך לבדוק אם קובץ השירות הושעה, ואין לנו דרך לעשות זאת. |
הפעלת לולאה אינסופית ב-service worker | לפי המפרט, הדבר עלול להוביל לביטול, בהתאם לאופן שבו הדפדפן מטמיע את הפונקציונליות הזו. Chrome לא מסיים את קובץ השירות במקרה כזה, ולכן אנחנו לא יכולים לבדוק את התרחיש שבו קובץ השירות מושעה. |
הצגת הודעה ב-service worker כדי לבדוק אם הוא הושעה | שליחת הודעה מעוררת את ה-service worker. אפשר להשתמש באפשרות הזו כדי לבדוק אם שירות ה-worker היה במצב שינה, אבל היא גורמת לתוצאות שגויות בבדיקות שצריכות לבצע בדיקות מיד אחרי השעיית שירות ה-worker. |
סגירת התהליך של ה-service worker באמצעות chrome.processes.terminate() | קובץ השירות של התוסף משתף תהליך עם חלקים אחרים של התוסף, כך שהפסקת התהליך באמצעות chrome.process.terminate() או באמצעות ממשק המשתמש של מנהל התהליכים של Chrome תגרום להפסקה של קובץ השירות וגם של כל דפי התוסף. |
בסופו של דבר, יצרנו בדיקה שבה אנחנו בודקים איך הקוד שלנו מגיב להשעיית ה-service worker. לשם כך, אנחנו מפעילים את Selenium WebDriver כדי לפתוח את chrome://serviceworker-internals/ ולוחצים על הלחצן 'stop' (עצירה) של ה-service worker.
זו האפשרות הטובה ביותר עד כה, אבל היא לא אידיאלית כי הבדיקות של Mocha (שפועלות בדף של התוסף) לא יכולות לעשות זאת בעצמן, ולכן הן צריכות לתקשר חזרה לתוכנית הצומת של WebDriver. המשמעות היא שאי אפשר להריץ את הבדיקות האלה באמצעות התוסף בלבד, אלא צריך להפעיל אותן באמצעות Selenium WebDriver.
זהו תרשים של האופן שבו אנחנו מתקשרים עם ממשק ה-API של הדפדפן באמצעות תהליכים שונים, והאופן שבו הוספת המנגנון 'השעיית שירותי העבודה' משפיעה עליו.
בתהליך חדש להשעיית שירותי העבודה (כחול), הוספנו את Selenium WebDriver כדי "ללחוץ" על השהיה דרך ממשק המשתמש, שמפעיל פעולה ב-API של הדפדפן.
חשוב לציין שזוהתה באג ב-Chrome שבו ביצוע הפעולה הזו באמצעות Selenium WebDriver גרם לכך ששירות ה-worker לא יכול להתחיל שוב. הבעיה תוקנה ב-Chrome 116, ולמזלנו יש גם פתרון עקיף: הגדרת Chrome כך שיפתח את כלי הפיתוח באופן אוטומטי בכל כרטיסייה גורמת לשירות העובד להתחיל בצורה תקינה.
זו הגישה שאנחנו משתמשים בה במהלך הבדיקה, למרות שהיא לא אידיאלית כי לחיצה על הלחצן עשויה להיות ממשק API לא יציב, ויש עלות ביצועים לפתיחת DevTools (בדפדפנים ישנים יותר).
איך אנחנו מכסים את כל הפונקציונליות? בדיקות Fuzz
אחרי שיצרנו מנגנון לבדיקה של השעיה, נאלצנו להחליט איך לחבר אותו לחבילות הבדיקות האוטומטיות שלנו. הרצנו את הבדיקות הרגילות בסביבה שבה לפני כל אינטראקציה עם דף הרקע, ה-service worker מושעה על ידי WebDriver בלחיצה על Stop בדף chrome://serviceworker-internals/.
אנחנו מריצים את רוב הבדיקות, אבל לא את כולן, כי מנגנון ההשעיה לא יציב לחלוטין ולפעמים הוא גורם לבעיות. בנוסף, הפעלת כל חבילות הבדיקה במצב fuzz אורכת הרבה זמן. לכן, במקום לכסות את כל המקרים "הדומים", בחרנו את הנתיבים הקריטיים ביותר לבדיקה במצב fuzz. חשוב לציין שכדי להריץ בדיקות פונקציונליות במצב 'fuzz', נאלצנו להגדיל את זמן הקצאת הזמן לתפוגה של הבדיקות, כי השהיה והפעלה מחדש של שירותי ה-Workers דורשות זמן נוסף.
הבדיקות האלה הן בדיקה ראשונית ברמת פירוט נמוכה, שמאפשרת לזהות מקומות רבים שבהם הקוד נכשל, אבל יכול להיות שהן לא יחשפו את כל הדרכים העדינות שבהן השעיית ה-service worker עלולה לגרום לבעיות.
אנחנו קוראים לבדיקות מהסוג הזה 'בדיקות Fuzz'. באופן מסורתי, בדיקת fuzz היא הכנסת קלט לא תקין לתוכנית ומוודאים שהיא מגיבה בצורה סבירה, או לפחות שהיא לא קורסה. במקרה שלנו, 'הקלט הלא חוקי' הוא העובד הווירטואלי (service worker) שמושעה בכל שלב, ו'ההתנהגות הסבירה' שאנחנו מצפים לה היא שהפונקציונליות של סינון המודעות תמשיך לפעול כמו קודם. זה לא ממש קלט לא חוקי, כי זו התנהגות צפויה ב-Manifest V3, אבל זה היה לא חוקי ב-Manifest V2, ולכן נראה שזו טרמינולוגיה סבירה.
סיכום
שירותי העבודה הם אחד מהשינויים הגדולים ביותר ב-Manifest V3 (מלבד כללי declarativeNetRequest). כדי לעבור ל-Manifest V3, יכול להיות שתצטרכו לבצע שינויים רבים בקוד של תוספים לדפדפנים וליישם שיטות חדשות לבדיקות. בנוסף, המפתחים של תוספים עם מצב מתמיד צריכים להכין את התוספים שלהם כדי לטפל בהשעיה לא צפויה של שירות העבודה בצורה חלקה.
לצערנו, אין ממשק API לטיפול בהשעיה בצורה פשוטה שתתאים לתרחיש לדוגמה שלנו. מאחר שרצינו לבדוק את חוזק קוד הבסיס של התוסף מול מנגנוני ההשעיה בשלב מוקדם, נאלצנו למצוא דרך לעקוף את הבעיה. מפתחי תוספים אחרים שנתקלים באתגרים דומים יכולים להשתמש בפתרון החלופי הזה. אמנם הוא גוזל זמן בשלב הפיתוח והתחזוקה, אבל כדאי להשתמש בו כדי שנוכל להבטיח שהתוספים שלנו יוכלו לפעול בהצלחה בסביבה שבה שירותי העבודה מושהים באופן קבוע.
כבר יש תמיכה בסיסית לבדיקת השעיית שירותי עובדים, אבל אנחנו רוצים להוסיף בעתיד תמיכה טובה יותר בפלטפורמה לבדיקת שירותי עובדים מתוך התוספים, כי זה יכול להפחית באופן משמעותי את זמני ביצוע הבדיקות ואת מאמצי התחזוקה.