תיאור
שימוש ב-API של chrome.storage
כדי לאחסן, לאחזר ולעקוב אחרי שינויים בנתוני משתמשים.
הרשאות
storage
סקירה כללית
Storage API מספק דרך ספציפית לתוסף לשמור את נתוני המשתמשים והמצב שלהם. הוא דומה לממשקי ה-API לאחסון של פלטפורמת האינטרנט (IndexedDB ו-Storage), אבל הוא תוכנן לתת מענה לצורכי האחסון של תוספים. ריכזנו כאן כמה מהתכונות העיקריות:
- לכל ההקשרים של התוסף, כולל ל-service worker של התוסף ולסקריפטים של התוכן, יש גישה ל-Storage API.
- הערכים שניתן לבצע בהם סריאליזציה של JSON מאוחסנים כמאפייני אובייקט.
- ה-Storage API הוא אסינכרוני עם פעולות של קריאה וכתיבה בכמות גדולה.
- הנתונים נשמרים גם אם המשתמש מנקה את המטמון ואת היסטוריית הגלישה.
- ההגדרות שנשמרות נשמרות גם כשמשתמשים בפיצול פרטיות.
- כולל אזור אחסון מנוהל בלעדי לקריאה בלבד למדיניות הארגון.
למרות שתוספים יכולים להשתמש בממשק [Storage
][mdn-storage] (שגלוי דרך window.localStorage
) בהקשרים מסוימים (חלונות קופצים ודפי HTML אחרים), לא מומלץ לעשות זאת מהסיבות הבאות:
- ל-Service Worker של התוסף אין גישה אל
Storage
. - סקריפטים של תוכן משתפים את נפח האחסון עם הדף המארח.
- נתונים שנשמרו באמצעות ממשק
Storage
הולכים לאיבוד כשהמשתמש מנקה את היסטוריית הגלישה שלו.
כדי להעביר נתונים מממשקי API של אחסון באינטרנט לממשקי API של אחסון תוספים מ-Service Worker:
- אפשר ליצור מסמך שלא נמצא במסך עם תרחיש המרות ו-handler של [
onMessage
][on-message]. - מוסיפים תרחיש המרות למסמך שלא מוצג במסך.
- ב-service worker של התוסף, בודקים את הנתונים ב-
chrome.storage
. - אם הנתונים לא נמצאים, [יוצרים][create-offscreen] מסמך מחוץ למסך ומפעילים את [
sendMessage()
][send-message] כדי להתחיל את תהליך ההמרה. - בתוך הטיפול
onMessage
של המסמך מחוץ למסך, קוראים לתוכנית ההמרה.
יש גם כמה ניואנסים לגבי האופן שבו ממשקי API לאחסון באינטרנט פועלים בתוספים. מידע נוסף זמין במאמר אחסון וקובצי cookie.
אזורי אחסון
Storage API מחולק לארבעה קטגוריות ('אזורי אחסון'):
storage.local
- הנתונים מאוחסנים באופן מקומי ונמחקים כשהתוסף מוסר. מגבלת המכסה היא כ-10MB, אבל אפשר להגדיל אותה על ידי בקשה להרשאה
"unlimitedStorage"
. כדאי להשתמש בהם כדי לאחסן כמויות גדולות יותר של נתונים.
storage.sync
- אם הסנכרון מופעל, הנתונים מסתנכרנים עם כל דפדפן Chrome שאליו המשתמש מחובר. אם המדיניות מושבתת, היא פועלת כמו
storage.local
. Chrome שומר את הנתונים באופן מקומי כשהדפדפן במצב אופליין, וממשיך את הסנכרון כשהדפדפן חוזר לאינטרנט. מגבלת המכסה היא כ-100KB, 8KB לכל פריט. כדאי להשתמש בו כדי לשמור על הגדרות המשתמש בדפדפנים מסונכרנים.
- storage.session
- שמירת נתונים בזיכרון למשך סשן הדפדפן. כברירת מחדל, הוא לא חשוף לסקריפטים של תוכן, אבל אפשר לשנות את ההתנהגות הזו על ידי הגדרת
chrome.storage.session.setAccessLevel()
. מגבלת המכסה היא כ-10MB. כדאי להשתמש בו כדי לאחסן משתנים גלובליים בכל הריצות של Service Worker.
- storage.managed
- אדמינים יכולים להשתמש בסכימה ובמדיניות הארגון כדי להגדיר את ההגדרות של תוסף תומך בסביבה מנוהלת. אזור האחסון הזה הוא לקריאה בלבד.
מניפסט
כדי להשתמש ב-storage API, מגדירים את ההרשאה "storage"
במניפסט של התוסף. לדוגמה:
{
"name": "My extension",
...
"permissions": [
"storage"
],
...
}
שימוש
בדוגמאות הבאות מוצגים אזורי האחסון local
, sync
ו-session
:
storage.local
chrome.storage.local.set({ key: value }).then(() => {
console.log("Value is set");
});
chrome.storage.local.get(["key"]).then((result) => {
console.log("Value currently is " + result.key);
});
storage.sync
chrome.storage.sync.set({ key: value }).then(() => {
console.log("Value is set");
});
chrome.storage.sync.get(["key"]).then((result) => {
console.log("Value currently is " + result.key);
});
storage.session
chrome.storage.session.set({ key: value }).then(() => {
console.log("Value was set");
});
chrome.storage.session.get(["key"]).then((result) => {
console.log("Value currently is " + result.key);
});
מידע נוסף על אזור האחסון של managed
זמין במניפסט לאזורי אחסון.
מגבלות אחסון וויסות נתונים (throttle)
אל תתייחסו להוספה ל-Storage API כאל הכנסת פריטים למשאית גדולה. כדאי להוסיף אל ואחסון כמו הכנסת משהו בצינור. יכול להיות שכבר יש צינור עם חומר, ואולי הוא אפילו מלא. תמיד צריך להניח שיש עיכוב בין הזמן שבו מוסיפים נתונים לאחסון לבין הזמן שבו הם מתועדים בפועל.
לקבלת פרטים על מגבלות לגבי אזורי אחסון ועל מה שקורה כשחורגים מהן, אפשר לעיין בפרטי המכסות עבור sync
, local
ו-session
.
תרחישים לדוגמה
בקטעים הבאים מוצגים תרחישים נפוצים לשימוש ב-Storage API.
תגובה מסונכרנת לעדכוני אחסון
כדי לעקוב אחרי השינויים שבוצעו באחסון, אפשר להוסיף מאזין לאירוע onChanged
שלו. האירוע הזה מופעל בכל פעם שמתבצע שינוי כלשהו באחסון. הקוד לדוגמה מקשיב לשינויים האלה:
background.js:
chrome.storage.onChanged.addListener((changes, namespace) => {
for (let [key, { oldValue, newValue }] of Object.entries(changes)) {
console.log(
`Storage key "${key}" in namespace "${namespace}" changed.`,
`Old value was "${oldValue}", new value is "${newValue}".`
);
}
});
אנחנו יכולים לקחת את הרעיון הזה אפילו יותר. בדוגמה הזו יש לנו דף אפשרויות
מאפשר למשתמש להחליף מצב של 'מצב ניפוי באגים' (ההטמעה לא מוצגת כאן). דף האפשרויות שומר את ההגדרות החדשות ב-storage.sync
באופן מיידי, ו-service worker משתמש ב-storage.onChanged
כדי להחיל את ההגדרה בהקדם האפשרי.
options.html:
<!-- type="module" allows you to use top level await -->
<script defer src="options.js" type="module"></script>
<form id="optionsForm">
<label for="debug">
<input type="checkbox" name="debug" id="debug">
Enable debug mode
</label>
</form>
options.js:
// In-page cache of the user's options
const options = {};
const optionsForm = document.getElementById("optionsForm");
// Immediately persist options changes
optionsForm.debug.addEventListener("change", (event) => {
options.debug = event.target.checked;
chrome.storage.sync.set({ options });
});
// Initialize the form with the user's option settings
const data = await chrome.storage.sync.get("options");
Object.assign(options, data.options);
optionsForm.debug.checked = Boolean(options.debug);
background.js:
function setDebugMode() { /* ... */ }
// Watch for changes to the user's options & apply them
chrome.storage.onChanged.addListener((changes, area) => {
if (area === 'sync' && changes.options?.newValue) {
const debugMode = Boolean(changes.options.newValue.debug);
console.log('enable debug mode?', debugMode);
setDebugMode(debugMode);
}
});
טעינה מראש אסינכרונית מהאחסון
קובצי שירות (service worker) לא תמיד פועלים, ולכן לפעמים תוספי Manifest V3 צריכים
לטעון נתונים באופן אסינכרוני מהאחסון לפני שהם מפעילים את הגורמים שמטפלים באירועים שלהם. כדי לעשות את זה,
קטע הקוד הבא משתמש ב-handler של אירועים מסוג action.onClicked
אסינכרוני שממתין ל-storageCache
יאוכלס לפני הפעלת הלוגיקה שלו.
background.js:
// Where we will expose all the data we retrieve from storage.sync.
const storageCache = { count: 0 };
// Asynchronously retrieve data from storage.sync, then cache it.
const initStorageCache = chrome.storage.sync.get().then((items) => {
// Copy the data retrieved from storage into storageCache.
Object.assign(storageCache, items);
});
chrome.action.onClicked.addListener(async (tab) => {
try {
await initStorageCache;
} catch (e) {
// Handle error that occurred during storage initialization.
}
// Normal action handler logic.
storageCache.count++;
storageCache.lastTabId = tab.id;
chrome.storage.sync.set(storageCache);
});
דוגמאות לתוספים
אפשר לראות הדגמות נוספות של Storage API כאן:
סוגים
AccessLevel
רמת הגישה של אזור האחסון.
Enum
"TRUSTED_CONTEXTS"
מציין הקשרים שמקורם מהתוסף עצמו.
"TRUSTED_AND_UNTRUSTED_CONTEXTS"
ההגדרה קובעת הקשרים שמקורם מחוץ לתוסף.
StorageArea
מאפיינים
-
onChanged
Event<functionvoidvoid>
Chrome מגרסה 73 ואילךמופעל כשפריט אחד או יותר משתנים.
הפונקציה
onChanged.addListener
נראית כך:(callback: function) => {...}
-
קריאה חוזרת (callback)
פונקציה
הפרמטר
callback
נראה כך:(changes: object) => void
-
שינויים
אובייקט
-
-
-
נקה
void
Promiseהסרת כל הפריטים מהאחסון.
הפונקציה
clear
נראית כך:(callback?: function) => {...}
-
קריאה חוזרת (callback)
פונקציה אופציונלי
הפרמטר
callback
נראה כך:() => void
-
החזרות
Promise<void>
גרסה 88 ואילך של Chromeהבטחות נתמכות רק במניפסט מגרסה V3 ואילך, בפלטפורמות אחרות צריך להשתמש בקריאות חוזרות (callback).
-
-
get
ריק
Promiseמקבל פריט אחד או יותר מהאחסון.
הפונקציה
get
נראית כך:(keys?: string | string[] | object, callback?: function) => {...}
-
מפתחות
string | string[] | object אופציונלי
מפתח יחיד לקבל, רשימת מפתחות לקבל, או מילון שמציין ערכי ברירת מחדל (ראו תיאור של האובייקט). רשימה או אובייקט ריקים יחזירו אובייקט תוצאה ריק. מעבירים את הערך
null
כדי לקבל את כל התוכן של האחסון. -
קריאה חוזרת (callback)
פונקציה אופציונלי
הפרמטר
callback
נראה כך:(items: object) => void
-
פריטים
אובייקט
אובייקט עם פריטים במיפויים של מפתח/ערך.
-
-
החזרות
Promise<object>
Chrome מגרסה 88 ואילךיש תמיכה ב-Promises רק ב-Manifest V3 ואילך. בפלטפורמות אחרות צריך להשתמש ב-callbacks.
-
-
getBytesInUse
ריק
Promiseהפונקציה מקבלת את נפח האחסון (בבייטים) שמשמש פריט אחד או יותר.
הפונקציה
getBytesInUse
נראית כך:(keys?: string | string[], callback?: function) => {...}
-
מפתחות
string | string[] אופציונלי
מקש בודד או רשימת מפתחות לקבלת השימוש הכולל עבורם. רשימה ריקה תחזיר את הערך 0. מעבירים את הערך
null
כדי לקבל את השימוש הכולל בכל נפח האחסון. -
קריאה חוזרת (callback)
פונקציה אופציונלי
הפרמטר
callback
נראה כך:(bytesInUse: number) => void
-
bytesInUse
number
כמות השטח שבשימוש באחסון, בבייטים.
-
-
החזרות
Promise<number>
גרסה 88 ואילך של Chromeהבטחות נתמכות רק במניפסט מגרסה V3 ואילך, בפלטפורמות אחרות צריך להשתמש בקריאות חוזרות (callback).
-
-
getKeys
ריק
Promise Chrome מגרסה 130 ואילךאחזור כל המפתחות מהאחסון.
הפונקציה
getKeys
נראית כך:(callback?: function) => {...}
-
קריאה חוזרת (callback)
פונקציה אופציונלי
הפרמטר
callback
נראה כך:(keys: string[]) => void
-
מפתחות
string[]
מערך עם מפתחות שנקראו מהאחסון.
-
-
החזרות
Promise<string[]>
הבטחות נתמכות רק במניפסט מגרסה V3 ואילך, בפלטפורמות אחרות צריך להשתמש בקריאות חוזרות (callback).
-
-
remove
ריק
Promiseהסרה של פריט אחד או יותר מהאחסון.
הפונקציה
remove
נראית כך:(keys: string | string[], callback?: function) => {...}
-
מפתחות
string | string[]
מפתח יחיד או רשימת מפתחות לפריטים להסרה.
-
קריאה חוזרת (callback)
פונקציה אופציונלי
הפרמטר
callback
נראה כך:() => void
-
החזרות
Promise<void>
גרסה 88 ואילך של Chromeיש תמיכה ב-Promises רק ב-Manifest V3 ואילך. בפלטפורמות אחרות צריך להשתמש ב-callbacks.
-
-
הוגדר
ריק
Promiseהגדרת מספר פריטים.
הפונקציה
set
נראית כך:(items: object, callback?: function) => {...}
-
פריטים
אובייקט
אובייקט שמספק לכל צמד מפתח/ערך שרוצים לעדכן באמצעותו את האחסון. שום צמד מפתח/ערך אחר באחסון לא יושפע.
ערכים פרימיטיביים, כמו מספרים, יופיעו בהסדרים כמצופה. ערכים עם
typeof
"object"
ו-"function"
יופיעו בדרך כלל בסדר טורי ל-{}
, פרט ל-Array
(מעבדים כמצופה),Date
ו-Regex
(יוצרים סריאליזציה באמצעות ייצוגString
שלהם). -
קריאה חוזרת (callback)
פונקציה אופציונלי
הפרמטר
callback
נראה כך:() => void
-
החזרות
Promise<void>
Chrome מגרסה 88 ואילךהבטחות נתמכות רק במניפסט מגרסה V3 ואילך, בפלטפורמות אחרות צריך להשתמש בקריאות חוזרות (callback).
-
-
setAccessLevel
void
הבטחה Chrome 102 ואילךהגדרת רמת הגישה הרצויה לאזור האחסון. ברירת המחדל תהיה רק הקשרים מהימנים.
הפונקציה
setAccessLevel
נראית כך:(accessOptions: object, callback?: function) => {...}
-
accessOptions
אובייקט
-
accessLevel
רמת הגישה של אזור האחסון.
-
-
קריאה חוזרת (callback)
פונקציה אופציונלי
הפרמטר
callback
נראה כך:() => void
-
החזרות
Promise<void>
הבטחות נתמכות רק במניפסט מגרסה V3 ואילך, בפלטפורמות אחרות צריך להשתמש בקריאות חוזרות (callback).
-
StorageChange
מאפיינים
-
newValue
כל אופציונלי
הערך החדש של הפריט, אם יש ערך חדש.
-
oldValue
כל אופציונלי
הערך הישן של הפריט, אם היה ערך ישן.
מאפיינים
local
הפריטים באזור האחסון של local
הם מקומיים לכל מכונה.
סוג
StorageArea ו אובייקט
מאפיינים
-
QUOTA_BYTES
10485760
הכמות המקסימלית (בבייטים) של נתונים שאפשר לאחסן באחסון מקומי, כפי שנמדדת באמצעות מחרוזות JSON של כל ערך ואורך כל מפתח. המערכת תתעלם מהערך הזה אם לתוסף יש את ההרשאה
unlimitedStorage
. עדכונים שעלולים לגרום לחריגה מהמגבלה הזו נכשלים באופן מיידי ומגדירים את הערךruntime.lastError
כשמשתמשים בקריאה חוזרת (callback), או בהבטחה שנדחתה אם משתמשים בפורמט async/await.
managed
הפריטים באזור האחסון managed
מוגדרים על ידי מדיניות ארגונית שמוגדרת על ידי האדמין של הדומיין, והם קריאה בלבד עבור התוסף. ניסיון לשנות את מרחב השמות הזה גורם לשגיאה. למידע נוסף על הגדרת מדיניות, ראו מניפסט לאזורי אחסון.
סוג
session
פריטים באזור האחסון של session
מאוחסנים בזיכרון ולא יישמרו בדיסק.
סוג
StorageArea ו-object
מאפיינים
-
QUOTA_BYTES
10485760
הכמות המקסימלית (בבייטים) של נתונים שאפשר לאחסן בזיכרון, כפי שנמדדת על ידי הערכת השימוש בזיכרון שהוקצה באופן דינמי לכל ערך ומפתח. עדכונים שגורמים לחריגה מהמגבלה הזו נכשלים באופן מיידי ומגדירים את הערך
runtime.lastError
כשמשתמשים בקריאה חוזרת (callback), או כש-Promise נדחה.
sync
הפריטים באזור האחסון sync
מסונכרנים באמצעות סנכרון Chrome.
סוג
StorageArea ו-object
מאפיינים
-
MAX_ITEMS
512
המספר המקסימלי של פריטים שאפשר לאחסן באחסון הסנכרון. עדכונים שגורמים לחריגה מהמגבלה הזו ייכשל באופן מיידי ויגדירו את הערך
runtime.lastError
כשמשתמשים בקריאה חוזרת (callback), או כש-Promise נדחה. -
MAX_SUSTAINED_WRITE_OPERATIONS_PER_MINUTE
1000000
הוצא משימושל-storage.sync API כבר אין מכסה על פעולות כתיבה מתמשכות.
-
MAX_WRITE_OPERATIONS_PER_HOUR
1800
המספר המקסימלי של פעולות
set
,remove
אוclear
שניתן לבצע בכל שעה. כלומר, פעולה אחת כל 2 שניות, מגבלה נמוכה יותר מהמגבלה הגבוהה יותר לכתיבה בדקה לטווח קצר.עדכונים שעלולים לגרום לחריגה מהמגבלה הזו נכשלים באופן מיידי ומגדירים
runtime.lastError
כשמשתמשים בקריאה חוזרת (callback) או כשהבטחה נדחתה. -
MAX_WRITE_OPERATIONS_PER_MINUTE
120
המספר המקסימלי של פעולות
set
,remove
אוclear
שאפשר לבצע בכל דקה. זהו קצב של 2 שניות, שמספק תפוקת נתונים גבוהה יותר מאשר כתיבת בשעה בפרק זמן קצר יותר.עדכונים שגורמים לחריגה מהמגבלה הזו נכשלים באופן מיידי ומגדירים את הערך
runtime.lastError
כשמשתמשים בקריאה חוזרת (callback), או כש-Promise נדחה. -
QUOTA_BYTES
102400
הסכום הכולל המקסימלי (בבייטים) של נתונים שניתן לאחסן באחסון הסנכרון, כפי שנמדד על ידי מחרוזות JSON של כל ערך ואורך כל מפתח. עדכונים שעלולים לגרום לחריגה מהמגבלה הזו נכשלים באופן מיידי ומגדירים
runtime.lastError
כשמשתמשים בקריאה חוזרת (callback) או כשהבטחה נדחתה. -
QUOTA_BYTES_PER_ITEM
8192
הגודל המקסימלי (בבייטים) של כל פריט באחסון לסנכרון, כפי שנמדד על ידי מחרוזת JSON של הערך שלו בתוספת אורך המפתח שלו. עדכונים שמכילים פריטים גדולים מהמגבלה הזו ייכשל באופן מיידי ויגדירו את הערך
runtime.lastError
כשמשתמשים ב-callback, או כש-Promise נדחה.
אירועים
onChanged
chrome.storage.onChanged.addListener(
callback: function,
)
מופעל כשפריט אחד או יותר משתנים.
פרמטרים
-
קריאה חוזרת (callback)
פונקציה
הפרמטר
callback
נראה כך:(changes: object, areaName: string) => void
-
שינויים
אובייקט
-
areaName
מחרוזת
-