Nhắn tin bằng ứng dụng gốc

Các tiện ích có thể trao đổi thông báo với các ứng dụng gốc bằng cách sử dụng một API tương tự như các API truyền thông báo khác. Các ứng dụng gốc hỗ trợ tính năng này phải đăng ký máy chủ nhắn tin gốc có thể giao tiếp với tiện ích. Chrome khởi động máy chủ lưu trữ trong một quy trình riêng và giao tiếp với máy chủ lưu trữ đó bằng các luồng đầu vào và đầu ra chuẩn.

Máy chủ nhắn tin gốc

Để đăng ký máy chủ nhắn tin gốc, ứng dụng phải lưu một tệp xác định cấu hình máy chủ nhắn tin gốc.

Sau đây là ví dụ về tệp:

{
  "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/"]
}

Tệp kê khai máy chủ nhắn tin gốc phải là JSON hợp lệ và chứa các trường sau:

name
Tên của máy chủ nhắn tin gốc. Ứng dụng sẽ truyền chuỗi này đến runtime.connectNative() hoặc runtime.sendNativeMessage(). Tên này chỉ có thể chứa ký tự chữ-số viết thường, dấu gạch dưới và dấu chấm. Tên không được bắt đầu hoặc kết thúc bằng dấu chấm và không được theo sau dấu chấm đó bằng một dấu chấm khác.
description
Mô tả ngắn về ứng dụng.
path
Đường dẫn đến tệp nhị phân của máy chủ nhắn tin gốc. Trên Linux và macOS, đường dẫn phải là tuyệt đối. Trên Windows, đường dẫn này có thể tương ứng với thư mục chứa tệp kê khai. Quy trình lưu trữ được bắt đầu bằng cách đặt thư mục hiện tại thành thư mục chứa tệp nhị phân lưu trữ. Ví dụ: nếu bạn đặt tham số này thành C:\Application\nm_host.exe, thì tham số sẽ bắt đầu bằng thư mục hiện tại "C:\Application".
type
Loại giao diện dùng để giao tiếp với máy chủ nhắn tin gốc. Tham số này có thể có một giá trị: stdio. Điều này cho biết rằng Chrome sẽ sử dụng stdinstdout để giao tiếp với máy chủ.
allowed_origins
Danh sách các tiện ích có quyền truy cập vào máy chủ nhắn tin gốc. Giá trị allowed-origins không được chứa ký tự đại diện.

Vị trí của máy chủ nhắn tin gốc

Vị trí của tệp kê khai phụ thuộc vào nền tảng.

Trên Windows, tệp kê khai có thể nằm ở vị trí bất kỳ trong hệ thống tệp. Trình cài đặt ứng dụng phải tạo một khoá sổ đăng ký, HKEY_LOCAL_MACHINE\SOFTWARE\Google\Chrome\NativeMessagingHosts\com.my_company.my_application hoặc HKEY_CURRENT_USER\SOFTWARE\Google\Chrome\NativeMessagingHosts\com.my_company.my_application và đặt giá trị mặc định của khoá đó thành đường dẫn đầy đủ đến tệp kê khai. Ví dụ: sử dụng lệnh sau:

REG ADD "HKCU\Software\Google\Chrome\NativeMessagingHosts\com.my_company.my_application" /ve /t REG_SZ /d "C:\path\to\nmh-manifest.json" /f

hoặc sử dụng tệp .reg sau:

Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\Google\Chrome\NativeMessagingHosts\com.my_company.my_application]
@="C:\\path\\to\\nmh-manifest.json"

Khi Chrome tìm máy chủ nhắn tin gốc, trước tiên, sổ đăng ký 32 bit sẽ được truy vấn, sau đó là sổ đăng ký 64 bit.

Trên macOSLinux, vị trí của tệp kê khai của máy chủ nhắn tin gốc thay đổi tuỳ theo trình duyệt (Google Chrome hoặc Chromium). Máy chủ nhắn tin gốc trên toàn hệ thống được tra cứu tại một vị trí cố định, trong khi máy chủ nhắn tin gốc ở cấp người dùng được tra cứu trong thư mục con NativeMessagingHosts/ của thư mục hồ sơ người dùng.

macOS (trên toàn hệ thống)
Google Chrome: /Library/Google/Chrome/NativeMessagingHosts/com.my_company.my_application.json
Chromium: /Library/Application Support/Chromium/NativeMessagingHosts/com.my_company.my_application.json
macOS (đường dẫn mặc định, dành riêng cho người dùng)
Google Chrome: ~/Library/Application Support/Google/Chrome/NativeMessagingHosts/com.my_company.my_application.json
Chromium: ~/Library/Application Support/Chromium/NativeMessagingHosts/com.my_company.my_application.json
Linux (toàn hệ thống)
Google Chrome: /etc/opt/chrome/native-messaging-hosts/com.my_company.my_application.json
Chromium: /etc/chromium/native-messaging-hosts/com.my_company.my_application.json
Linux (đường dẫn mặc định, dành riêng cho người dùng)
Google Chrome: ~/.config/google-chrome/NativeMessagingHosts/com.my_company.my_application.json
Chromium: ~/.config/chromium/NativeMessagingHosts/com.my_company.my_application.json

Giao thức nhắn tin gốc

Chrome khởi động từng máy chủ nhắn tin gốc trong một quy trình riêng biệt và giao tiếp với máy chủ đó bằng đầu vào chuẩn (stdin) và đầu ra chuẩn (stdout). Định dạng tương tự được dùng để gửi thông báo theo cả hai hướng; mỗi thông báo được chuyển đổi tuần tự bằng JSON, được mã hoá UTF-8 và đứng trước là độ dài thông báo 32 bit theo thứ tự byte gốc. Kích thước tối đa của một thư từ máy chủ nhắn tin gốc là 1 MB, chủ yếu để bảo vệ Chrome khỏi các ứng dụng gốc hoạt động không đúng cách. Kích thước tối đa của thông báo được gửi đến máy chủ nhắn tin gốc là 4 GB.

Đối số đầu tiên cho máy chủ nhắn tin gốc là nguồn gốc của phương thức gọi, thường là chrome-extension://[ID of allowed extension]. Điều này cho phép các máy chủ nhắn tin gốc xác định nguồn của thông báo khi nhiều tiện ích được chỉ định trong khoá allowed_origins trong tệp kê khai máy chủ nhắn tin gốc.

Trên Windows, máy chủ nhắn tin gốc cũng được truyền một đối số dòng lệnh có một tay cầm đến cửa sổ gốc Chrome gọi: --parent-window=<decimal handle value>. Điều này cho phép máy chủ nhắn tin gốc tạo các cửa sổ giao diện người dùng gốc được liên kết chính xác. Lưu ý rằng giá trị này sẽ là 0 nếu ngữ cảnh gọi là một trình chạy dịch vụ.

Khi một cổng nhắn tin được tạo bằng runtime.connectNative(), Chrome sẽ bắt đầu quy trình lưu trữ thông báo gốc và duy trì quy trình này cho đến khi cổng bị huỷ. Mặt khác, khi một thông báo được gửi bằng runtime.sendNativeMessage() mà không tạo cổng nhắn tin, Chrome sẽ bắt đầu một quy trình máy chủ nhắn tin gốc mới cho mỗi thông báo. Trong trường hợp đó, thông báo đầu tiên do quá trình lưu trữ tạo ra sẽ được xử lý dưới dạng phản hồi cho yêu cầu ban đầu và Chrome sẽ chuyển thông báo đó đến lệnh gọi lại phản hồi được chỉ định khi runtime.sendNativeMessage() được gọi. Trong trường hợp đó, tất cả các thông báo khác do máy chủ nhắn tin gốc tạo ra sẽ bị bỏ qua.

Kết nối với ứng dụng gốc

Việc gửi và nhận thông báo đến và từ một ứng dụng gốc cũng tương tự như việc gửi thông báo giữa các tiện ích. Điểm khác biệt chính là runtime.connectNative() được dùng thay cho runtime.connect()runtime.sendNativeMessage() được dùng thay cho runtime.sendMessage().

Để sử dụng các phương thức này, bạn phải khai báo quyền "nativeMessaging" trong tệp kê khai của tiện ích.

Các phương thức này không có trong tập lệnh nội dung, chỉ có trong trang và worker dịch vụ của tiện ích. Nếu bạn muốn giao tiếp từ tập lệnh nội dung đến ứng dụng gốc, hãy gửi thông báo đến worker dịch vụ để chuyển thông báo đó đến ứng dụng gốc.

Ví dụ sau đây sẽ tạo một đối tượng runtime.Port được kết nối với máy chủ nhắn tin gốc com.my_company.my_application, bắt đầu theo dõi thông báo từ cổng đó và gửi một tin nhắn đi:

var port = chrome.runtime.connectNative('com.my_company.my_application');
port.onMessage.addListener(function (msg) {
  console.log('Received' + msg);
});
port.onDisconnect.addListener(function () {
  console.log('Disconnected');
});
port.postMessage({text: 'Hello, my_application'});

Sử dụng runtime.sendNativeMessage để gửi thông báo đến ứng dụng gốc mà không cần tạo cổng, ví dụ:

chrome.runtime.sendNativeMessage(
  'com.my_company.my_application',
  {text: 'Hello'},
  function (response) {
    console.log('Received ' + response);
  }
);

Gỡ lỗi tính năng nhắn tin gốc

Khi xảy ra một số lỗi thông báo gốc, kết quả sẽ được ghi vào nhật ký lỗi của Chrome. Điều này bao gồm cả trường hợp máy chủ nhắn tin gốc không khởi động được, ghi vào stderr hoặc vi phạm giao thức liên lạc. Trên Linux và macOS, bạn có thể truy cập vào nhật ký này bằng cách khởi động Chrome từ dòng lệnh và xem dữ liệu đầu ra của Chrome trong thiết bị đầu cuối. Trên Windows, hãy sử dụng --enable-logging như giải thích trong phần Cách bật tính năng ghi nhật ký.

Dưới đây là một số lỗi thường gặp và mẹo giải quyết:

Không khởi động được máy chủ nhắn tin gốc.

Kiểm tra xem bạn có đủ quyền để thực thi tệp máy chủ nhắn tin gốc hay không.

Bạn đã chỉ định tên máy chủ nhắn tin gốc không hợp lệ.

Kiểm tra xem tên có chứa ký tự không hợp lệ không. Chỉ được dùng ký tự chữ-số viết thường, dấu gạch dưới và dấu chấm. Tên không được bắt đầu hoặc kết thúc bằng dấu chấm và không được có dấu chấm theo sau dấu chấm khác.

Máy chủ gốc đã thoát.

Ống dẫn đến máy chủ nhắn tin gốc bị hỏng trước khi Chrome đọc được thông báo. Quá trình này rất có thể được bắt đầu từ máy chủ nhắn tin gốc.

Không tìm thấy máy chủ nhắn tin gốc được chỉ định.

Kiểm tra những điều sau:

  • Tên có được viết đúng chính tả trong phần mở rộng và trong tệp kê khai không?
  • Tệp kê khai có nằm trong thư mục đúng và có tên chính xác không? Xem vị trí máy chủ nhắn tin gốc để biết các định dạng dự kiến.
  • Tệp kê khai có đúng định dạng không? Cụ thể, JSON có hợp lệ và được định dạng đúng cách không, đồng thời các giá trị có khớp với định nghĩa của tệp kê khai máy chủ nhắn tin gốc không?
  • Tệp được chỉ định trong path có tồn tại không? Trên Windows, đường dẫn có thể là tương đối, nhưng trên macOS và Linux, các đường dẫn đó phải là tuyệt đối.

Tên máy chủ của máy chủ nhắn tin gốc chưa được đăng ký. (Chỉ dành cho Windows)

Không tìm thấy máy chủ nhắn tin gốc trong sổ đăng ký Windows. Kiểm tra kỹ bằng regedit xem khoá có thực sự được tạo và khớp với định dạng bắt buộc như được ghi nhận tại vị trí lưu trữ thông báo gốc hay không.

Quyền truy cập vào máy chủ nhắn tin gốc đã chỉ định bị cấm.

Nguồn gốc của tiện ích có được liệt kê trong allowed_origins không?

Lỗi khi giao tiếp với máy chủ nhắn tin gốc.

Lỗi này cho biết bạn đã triển khai giao thức giao tiếp không chính xác trong máy chủ nhắn tin gốc.

  • Đảm bảo rằng tất cả đầu ra trong stdout tuân thủ giao thức nhắn tin gốc. Nếu bạn muốn in một số dữ liệu cho mục đích gỡ lỗi, hãy ghi vào stderr.
  • Hãy đảm bảo độ dài thông báo 32 bit thuộc định dạng số nguyên gốc của nền tảng (little-endian/big-endian).
  • Độ dài thông báo không được vượt quá 1024*1024.
  • Kích thước thư phải bằng số byte trong thư. Điều này có thể khác với "độ dài" của một chuỗi, vì các ký tự có thể được biểu thị bằng nhiều byte.
  • Chỉ dành cho Windows:Đảm bảo rằng chế độ I/O của chương trình được đặt thành O_BINARY. Theo mặc định, chế độ I/O là O_TEXT, làm hỏng định dạng thông báo khi dấu ngắt dòng (\n = 0A) được thay thế bằng dấu kết thúc dòng kiểu Windows (\r\n = 0D 0A). Bạn có thể đặt chế độ I/O bằng __setmode.