תוספים יכולים להחליף הודעות עם אפליקציות מקומיות באמצעות API שדומה לממשקי API אחרים להעברת הודעות. אפליקציות נייטיב שתומכות בתכונה הזו צריכות לרשום מארח להעברת הודעות נייטיב שיכול לתקשר עם התוסף. Chrome מפעיל את המארח בתהליך נפרד ומתקשר איתו באמצעות זרמי קלט רגילים ופלט רגילים.
מארח להעברת הודעות נייטיב
כדי לרשום מארח להעברת הודעות נייטיב, האפליקציה צריכה לשמור קובץ שמגדיר את התצורה של המארח להעברת הודעות נייטיב.
דוגמה לקובץ:
{
"name": "com.my_company.my_application",
"description": "My Application",
"path": "C:\\Program Files\\My Application\\chrome_native_messaging_host.exe",
"type": "stdio",
"allowed_origins": ["chrome-extension://knldjmfmopnpolahpmmgbagdohdnhkik/"]
}
קובץ המניפסט של מארח ההודעות המקומיות חייב להיות JSON תקין ולהכיל את השדות הבאים:
name- השם של מארח להעברת הודעות נייטיב. הלקוחות מעבירים את המחרוזת הזו אל
runtime.connectNative()או אלruntime.sendNativeMessage(). השם יכול להכיל רק תווים אלפאנומריים באותיות קטנות, קווים תחתונים ונקודות. השם לא יכול להתחיל או להסתיים בנקודה, ואי אפשר להשתמש בשתי נקודות ברצף. description- תיאור קצר של האפליקציה.
path- הנתיב לקובץ הבינארי של המארח להעברת הודעות נייטיב. ב-Linux וב-macOS הנתיב חייב להיות מוחלט. ב-Windows, הנתיב יכול להיות יחסי לספרייה שמכילה את קובץ המניפסט. תהליך המארח מתחיל כשהספרייה הנוכחית מוגדרת לספרייה שמכילה את הקובץ הבינארי של המארח. לדוגמה, אם הפרמטר הזה מוגדר כ-
C:\Application\nm_host.exe, הוא יתחיל עם הספרייה הנוכחית C:\Application. type- סוג הממשק שמשמש לתקשורת עם מארח להעברת הודעות נייטיב. לפרמטר הזה יש ערך אפשרי אחד:
stdio. היא מציינת ש-Chrome צריך להשתמש ב-stdinוב-stdoutכדי לתקשר עם המארח. allowed_origins- רשימת התוספים שצריכים לקבל גישה למארח להעברת הודעות נייטיב. הערכים של
allowed_originsלא יכולים להכיל תווים כלליים לחיפוש.
מיקום של מארח להעברת הודעות נייטיב
המיקום של קובץ המניפסט תלוי בפלטפורמה.
ב-Windows, קובץ המניפסט יכול להיות ממוקם בכל מקום במערכת הקבצים. תוכנת ההתקנה של האפליקציה צריכה ליצור מפתח רישום, או HKEY_LOCAL_MACHINE\SOFTWARE\Google\Chrome\NativeMessagingHosts\com.my_company.my_application או HKEY_CURRENT_USER\SOFTWARE\Google\Chrome\NativeMessagingHosts\com.my_company.my_application, ולהגדיר את ערך ברירת המחדל של המפתח הזה לנתיב המלא לקובץ המניפסט. לדוגמה, משתמשים בפקודה הבאה:
REG ADD "HKCU\Software\Google\Chrome\NativeMessagingHosts\com.my_company.my_application" /ve /t REG_SZ /d "C:\path\to\nmh-manifest.json" /f
או באמצעות קובץ .reg הבא:
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\Google\Chrome\NativeMessagingHosts\com.my_company.my_application]
@="C:\\path\\to\\nmh-manifest.json"
כש-Chrome מחפש מארחים של העברת הודעות מקוריות, הוא קודם שולח שאילתה למאגר הרישום של 32 ביט, ואז למאגר הרישום של 64 ביט.
ב-macOS וב-Linux, המיקום של קובץ המניפסט של מארח ההודעות המקומי משתנה בהתאם לדפדפן (Google Chrome, Google Chrome for Testing או Chromium). המערכת מחפשת את המארחים להעברת הודעות באפליקציות מקוריות במיקום קבוע, ואת המארחים להעברת הודעות באפליקציות מקוריות ברמת המשתמש היא מחפשת בספריית המשנה NativeMessagingHosts/ של ספריית פרופיל המשתמש.
- macOS (כלל המערכת)
- Google Chrome:
/Library/Google/Chrome/NativeMessagingHosts/com.my_company.my_application.json
- Google Chrome for Testing:
/Library/Google/ChromeForTesting/NativeMessagingHosts/com.my_company.my_application.json
- Chromium:
/Library/Application Support/Chromium/NativeMessagingHosts/com.my_company.my_application.json - macOS (נתיב ברירת המחדל שספציפי למשתמש)
- Google Chrome:
~/Library/Application Support/Google/Chrome/NativeMessagingHosts/com.my_company.my_application.json
- Google Chrome for Testing:
~/Library/Application Support/Google/ChromeForTesting/NativeMessagingHosts/com.my_company.my_application.json
- Chromium:
~/Library/Application Support/Chromium/NativeMessagingHosts/com.my_company.my_application.json - Linux (כלל המערכת)
- Google Chrome:
/etc/opt/chrome/native-messaging-hosts/com.my_company.my_application.json
- Google Chrome for Testing:
/etc/opt/chrome_for_testing/native-messaging-hosts/com.my_company.my_application.json
- Chromium:
/etc/chromium/native-messaging-hosts/com.my_company.my_application.json - Linux (ספציפי למשתמש, נתיב ברירת המחדל)
- Google Chrome:
~/.config/google-chrome/NativeMessagingHosts/com.my_company.my_application.json
- Google Chrome for Testing:
~/.config/google-chrome-for-testing/NativeMessagingHosts/com.my_company.my_application.json
- Chromium:
~/.config/chromium/NativeMessagingHosts/com.my_company.my_application.json
פרוטוקול להעברת הודעות נייטיב
Chrome מפעיל כל מארח להעברת הודעות נייטיב בתהליך נפרד, ומתקשר איתו באמצעות קלט סטנדרטי (stdin) (stdin) ופלט סטנדרטי (stdout) (stdout). אותו פורמט משמש לשליחת הודעות בשני הכיוונים. כל הודעה עוברת סריאליזציה באמצעות JSON, מקודדת ב-UTF-8 ומקדימה אותה אורך ההודעה ב-32 ביט בסדר הבייטים המקורי. הגודל המקסימלי של הודעה יחידה ממארח ההודעות המקומי הוא 1MB, בעיקר כדי להגן על Chrome מפני אפליקציות מקומיות שמתנהגות בצורה לא תקינה. הגודל המקסימלי של ההודעה שנשלחת למארח להעברת הודעות נייטיב הוא 64MiB.
הארגומנט הראשון למארח להעברת הודעות נייטיב הוא המקור של המתקשר, בדרך כלל chrome-extension://[ID of allowed extension]. כך מארחים להעברת הודעות נייטיב יכולים לזהות את המקור של ההודעה כשמציינים כמה תוספים במפתח allowed_origins במניפסט של מארח להעברת הודעות נייטיב.
ב-Windows, מארח להעברת הודעות נייטיב מקבל גם ארגומנט של שורת פקודה עם נקודת אחיזה לחלון הנייטיב של Chrome שקורא לו: --parent-window=<decimal handle value>. כך מארח ההודעות הנייטיב יכול ליצור חלונות של ממשק משתמש נייטיב עם הורה נכון. הערה: הערך הזה יהיה 0 אם ההקשר של הקריאה הוא service worker.
כשיוצרים יציאה להעברת הודעות באמצעות runtime.connectNative(), Chrome מפעיל תהליך מארח של העברת הודעות מקורית וממשיך להפעיל אותו עד שהיציאה נהרסת. לעומת זאת, כששולחים הודעה באמצעות runtime.sendNativeMessage(), בלי ליצור יציאת העברת הודעות, Chrome מתחיל תהליך חדש של מארח להעברת הודעות נייטיב לכל הודעה. במקרה כזה, ההודעה הראשונה שנוצרת על ידי תהליך המארח מטופלת כתגובה לבקשה המקורית, ו-Chrome יעביר אותה לקריאה החוזרת של התגובה שצוינה כשמתבצעת קריאה ל-runtime.sendNativeMessage(). המערכת מתעלמת מכל שאר ההודעות שנוצרו על ידי מארח להעברת הודעות נייטיב במקרה הזה.
התחברות לאפליקציית נייטיב
שליחה וקבלה של הודעות לאפליקציית נייטיב וממנה דומות מאוד להעברת הודעות בין תוספים. ההבדל העיקרי הוא שבמקום runtime.connect() משתמשים ב-runtime.connectNative(), ובמקום runtime.sendMessage() משתמשים ב-runtime.sendNativeMessage().
כדי להשתמש בשיטות האלה, צריך להצהיר על ההרשאה nativeMessaging בקובץ המניפסט של התוסף.
השיטות האלה לא זמינות בסקריפטים של תוכן, אלא רק בדפים וב-service worker של התוסף. כדי לתקשר מסקריפט תוכן לאפליקציית הנייטיב, שולחים את ההודעה ל-service worker כדי להעביר אותה לאפליקציית הנייטיב.
בדוגמה הבאה נוצר אובייקט runtime.Port שמחובר למארח להעברת הודעות נייטיב com.my_company.my_application, מתחיל להאזין להודעות מהיציאה הזו ושולח הודעה יוצאת אחת:
const port = chrome.runtime.connectNative('com.my_company.my_application');
port.onMessage.addListener((msg) => {
console.log('Received', msg);
});
port.onDisconnect.addListener(() => {
if (chrome.runtime.lastError) {
console.error(
'Disconnected due to error:',
chrome.runtime.lastError.message
);
} else {
console.log('Disconnected');
}
});
port.postMessage({text: 'Hello, my_application'});
משתמשים ב-runtime.sendNativeMessage כדי לשלוח הודעה לאפליקציית נייטיב בלי ליצור יציאה, למשל:
chrome.runtime.sendNativeMessage(
'com.my_company.my_application',
{text: 'Hello'},
(response) => {
if (chrome.runtime.lastError) {
console.error(
'Error sending native message:',
chrome.runtime.lastError.message
);
return;
}
console.log('Received', response);
}
);
ניפוי באגים בהעברת הודעות מקומית
כשמתרחשות שגיאות בהעברת הודעות מקוריות, פלט אבחון נכתב ביומן השגיאות של Chrome.
Linux ו-macOS
# Linux
google-chrome --enable-logging=stderr --log-level=1 2>&1 | \
grep -E "native_messag|launch_context"
# macOS
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome \
--enable-logging=stderr --log-level=1 2>&1 | \
grep -E "native_messag|launch_context"
Windows
מפעילים את Chrome עם רישום ביומן מופעל:
chrome.exe --enable-logging --log-level=1
מעבירים את --user-data-dir="%TEMP%\nm-debug" כדי להפעיל מופע נפרד בלי לצרף אותו לתהליך קיים של Chrome.
כדי לראות את הפלט, מריצים את הפקודה chrome_debug.log באמצעות PowerShell:
$log = "$env:LOCALAPPDATA\Google\Chrome\User Data\chrome_debug.log"
Get-Content -Wait $log | Select-String "native_messag|launch_context"
אפשר גם לפתוח את chrome_debug.log בעורך טקסט ולחפש את launch_context.cc או native_message_process_host.cc.
פרטים עיקריים ביומן
- חיפושים וניתוחים של מניפסטים שנכשלו ב-
launch_context.ccנרשמים ביומן כאזהרות. משתמשים ב---log-level=1במקום ב-2(ERROR), כדי להשבית את האבחון של ההפעלה. - מחפשים
launch_contextכדי למצוא שגיאות בהפעלת מניפסט וקובץ בינארי, ומחפשיםnative_messagכדי למצוא שגיאות בגודל מטען הייעודי ובצינור תקשורת.
שגיאות נפוצות
ריכזנו כאן כמה שגיאות נפוצות וטיפים לפתרון שלהן:
ההפעלה של מארח להעברת הודעות נייטיב נכשלה.
בודקים אם יש לכם הרשאות מספיקות להפעלת קובץ המארח להעברת הודעות נייטיב.
צוין שם מארח להעברת הודעות נייטיב לא תקין.
בודקים אם השם מכיל תווים לא חוקיים. מותר להשתמש רק בתווים אלפאנומריים באותיות קטנות, בקו תחתון ובנקודות. שם לא יכול להתחיל או להסתיים בנקודה, ואי אפשר להוסיף נקודה אחרי נקודה.
המארח המקומי יצא.
הצינור למארח המקומי להעברת הודעות נשבר לפני ש-Chrome קרא את ההודעה. הפעולה הזו כנראה מתבצעת ממארח להעברת הודעות נייטיב.
מארח להעברת הודעות נייטיב שצוין לא נמצא.
בדוק את הפרטים הבאים:
- האם האיות של השם נכון בתוסף ובקובץ המניפסט?
- ב-Windows, האם מפתח הרישום קיים ב-
HKEY_CURRENT_USERאו ב-HKEY_LOCAL_MACHINE, והאם ערך ברירת המחדל שלו מצביע על הנתיב המלא של המניפסט? Chrome שולח שאילתות לתצוגת הרישום של 32-bit קודם, ואז לתצוגת הרישום של 64-bit. משתמשים בregeditכדי לאמת את המפתח. מידע נוסף על מיקום של מארח להעברת הודעות נייטיב - ב-macOS וב-Linux, האם קובץ המניפסט נמצא בספרייה הצפויה והשם שלו זהה לשם המארח (למשל
com.my_company.my_application.json)? מידע נוסף זמין במאמר בנושא מיקום מארח להעברת הודעות נייטיב. - האם קובץ המניפסט בפורמט הנכון? בפרט, האם ה-JSON תקין ומעוצב היטב, והאם הערכים תואמים להגדרה של מניפסט של מארח להעברת הודעות נייטיב?
- האם הקובץ שצוין ב-
pathקיים? ב-Windows, הנתיבים יכולים להיות יחסיים, אבל ב-macOS וב-Linux, הנתיבים חייבים להיות מוחלטים.
הגישה למארח להעברת הודעות נייטיב שצוין אסורה.
האם המקור של התוסף מופיע ב-allowed_origins?
שגיאה בתקשורת עם מארח להעברת הודעות נייטיב.
השגיאה הזו מציינת הטמעה שגויה של פרוטוקול התקשורת במארח להעברת הודעות נייטיב.
- מוודאים שכל הפלט ב-
stdoutתואם לפרוטוקול של העברת הודעות באפליקציות מקוריות. אם רוצים להדפיס חלק מהנתונים לצורך ניפוי באגים, אפשר לכתוב אלstderr. - חשוב לוודא שאורך ההודעה של 32 ביט הוא בפורמט המספרים המקורי של הפלטפורמה (little-endian / big-endian).
- אורך ההודעה לא יכול להיות יותר מ-1,048,576.
- גודל ההודעה צריך להיות שווה למספר הבייטים בהודעה. יכול להיות שהערך הזה יהיה שונה מהערך של 'אורך' של מחרוזת, כי יכול להיות שתווים מיוצגים על ידי כמה בייטים.
- ב-Windows בלבד: מוודאים שמצב הקלט/פלט של התוכנית מוגדר ל-
O_BINARY. כברירת מחדל, מצב הקלט/פלט הואO_TEXT, שגורם לשיבוש בפורמט ההודעה כי מעברי שורה (\n=0A) מוחלפים בסיומי שורה בסגנון Windows (\r\n=0D 0A). אפשר להגדיר את מצב הקלט/פלט באמצעות__setmode.