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

Tiện ích và ứng dụng có thể trao đổi thông báo với ứng dụng gốc bằng cách sử dụng 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ột máy chủ nhắn tin gốc biết cách giao tiếp với tiện ích. Chrome khởi động máy chủ trong một quy trình riêng biệt và giao tiếp với quy trình đó 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 cài đặt một tệp kê khai xác định cấu hình máy chủ nhắn tin gốc. Dưới đây là ví dụ về tệp kê khai:

{
  "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:

TênMô tả
nameTên của máy chủ nhắn tin gốc. Ứng dụng chuyể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 đó.
descriptionMô 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à OSX, đường dẫn phải là đường dẫn tuyệt đối. Trên Windows, giá trị này có thể tương ứng với thư mục chứa tệp kê khai. Quá trình lưu trữ được bắt đầu với thư mục hiện tại được đặt thành thư mục chứa tệp nhị phân của máy chủ lưu trữ. Ví dụ: nếu bạn đặt tham số này thành C:\Application\nm_host.exe, thì tham số này sẽ bắt đầu bằng thư mục hiện tại là C:\Application\.
typeLoại giao diện dùng để giao tiếp với máy chủ nhắn tin gốc. Hiện tại, chỉ có thể có một giá trị cho tham số này: stdio. Nhãn này cho biết Chrome sẽ sử dụng stdinstdout để giao tiếp với máy chủ lưu trữ.
allowed_originsDanh sách các tiện ích cần có quyền truy cập vào máy chủ nhắn tin gốc. Không cho phép sử dụng các ký tự đại diện như chrome-extension://*/*.

Vị trí 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 ở bất cứ đâu trong hệ thống tệp. Ứng dụng người cài đặt phải tạo khoá đă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ụ: việc sử dụng sau đây:

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 kiếm máy chủ nhắn tin gốc, trước tiên hãy truy vấn sổ đăng ký 32 bit, sau đó truy vấn sổ đăng ký 64 bit sổ đăng ký tên miền.

Trên OS XLinux, vị trí của tệp kê khai của máy chủ nhắn tin gốc sẽ thay đổi 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 vị trí, trong khi máy chủ nhắn tin gốc ở cấp người dùng được tra cứu trong một thư mục con trong thư mục hồ sơ người dùng có tên là NativeMessagingHosts.

  • OS X (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
  • OS X (đườ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 và giao tiếp với máy chủ nhắn tin gốc bằng đầu vào chuẩn (stdin) và đầu ra chuẩn (stdout). Định dạng này được dùng để gửi thư bằng 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 sau 32 bit độ dài thông báo theo thứ tự byte gốc. Kích thước tối đa của một tin nhắn trong ứng dụng nhắn tin gốc 1 MB, chủ yếu để bảo vệ Chrome khỏi các ứng dụng gốc hoạt động sai. Kích thước tối đa của tin nhắn 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 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. Cảnh báo: Trên Windows, từ Chrome 54 trở xuống, nguồn gốc đã được truyền dưới dạng tham số thứ hai thay cho tham số đầu tiên.

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

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

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 rất giống với tiện ích chéo nhắn tin. Điểm khác biệt chính là runtime.connectNative được sử dụng thay vì runtime.connectruntime.sendNativeMessage được sử dụng thay vì runtime.sendMessage. Chỉ có thể sử dụng các phương thức này nếu phương thức "nativeMessaging" quyền được khai báo trong tệp kê khai.

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

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" });

Có thể 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 nhắn tin gốc

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

Dưới đây là một số lỗi và mẹo để giải quyết vấn đề:

  • 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 hay không.
  • Đã 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ệ nào không. Chỉ được ký tự chữ-số viết thường, được phép sử dụ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à dấu chấm cũng không được rồi đến một dấu chấm khác.
  • Máy chủ lưu trữ gốc đã thoát.
    • Đường dẫn đến máy chủ nhắn tin gốc đã bị hỏng trước khi Chrome đọc thư. Đây là có thể được bắt đầu từ máy chủ nhắn tin gốc của bạn.
  • Không tìm thấy máy chủ nhắn tin gốc được chỉ định.
    • Tên có được viết đúng chính tả trong tiện ích và trong tệp kê khai không?
    • Tệp kê khai có được đặt trong đúng thư mục và với tên chính xác không? Xem máy chủ nhắn tin gốc location cho các định dạng dự kiến.
    • Tệp kê khai có ở định dạng chính xác không? Cụ thể, cú pháp JSON có chính xác không và 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, các đường dẫn có thể là tương đối, nhưng trên OS X và Linux, các đường dẫn phải 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ý của Windows. Xác minh bằng regedit liệu khoá có thực sự được tạo và khớp với định dạng bắt buộc như được ghi trong gốc vị trí của máy chủ nhắn tin.
  • Quyền truy cập vào máy chủ nhắn tin gốc đượ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.
    • Đây là lỗi rất phổ biến và cho biết cách triển khai giao thức truyền thông 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 đều tuân thủ giao thức thông báo 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.
    • Đả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).
    • Thông báo không được dài 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 "length" 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: Hãy đảm bảo rằng chế độ I/O của chương trình được đặt thành O_BINARY. Theo mặc định, I/O là O_TEXT, chế độ này làm hỏng định dạng thông báo khi ngắt dòng (\n = 0A) được thay thế bằng Đuôi dòng kiểu Windows (\r\n = 0D 0A). Bạn có thể đặt chế độ I/O bằng cách sử dụng __setmode.