Я сделал два расширения, одно для firefox и одно для chrome (здесь будет публиковаться только код firefox, если необходимо опубликовать код Chrome, дайте мне знать, но он очень похож), у которого есть некоторые действия, вызовы нативное хост-приложение. Один из этих вызовов возвращает сообщение размером › 1 мб. Согласно https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_messaging, максимальный размер одного сообщения от приложения — 1 МБ. Согласно нативный обмен сообщениями Chrome: как получить › 1 МБ, данные › 1 Мб должен быть разделен на данные размером менее 1 Мб и отправлен столько же фрагментов. Я сделал хост-приложение Java и сделал решение для фрагментации данных. Данные разбиваются на части, и отправляется много ответов, каждый из которых содержит часть в строке json. Отправка и ответы работали нормально, сообщения объединяются во вход веб-страницы, и действие работает. Однако после выполнения этого действия любой другой вызов завершается ошибкой. Если я зайду в диспетчер задач Windows и убью собственный хост-процесс, все снова заработает. Если я выполняю действие, которое получает фрагментированный ответ, оно снова работает, но следующие вызовы молча терпят неудачу, консоль браузера Firefox ничего не дает мне. Я предполагаю, что что-то не так с моим решением. Действия работают. Когда я делаю действие, которое получает более 1 мб, действие работает, но после этого никакое другое действие снова не работает. Любая помощь приветствуется. Скажите мне, если вопрос не ясен или это большой беспорядок, я улучшу его. Я сделал все, что мог, чтобы заставить его работать, и он работает, но, как ни странно, только один раз, затем он терпит неудачу и ничего не делает. Извините, но я не могу сказать, что это за действия, я имею в виду, что я пытаюсь сделать, если это действительно необходимо знать, я попрошу моего менеджера объяснить это здесь.
Фон.js
function sendNativeMessage(message) {
port.postMessage(message);
}
function onDisconnected() {
msg = '{"message": "Failed to connect: '+browser.runtime.lastError+'"}';
browser.tabs.query({active: true, currentWindow: true}, function(tabs){
browser.tabs.sendMessage(tabs[0].id, msg, function(response) {});
});
port = null;
}
function connect() {
var hostName = "com.companyname.hostname";
port = browser.runtime.connectNative(hostName);
port.onMessage.addListener(function(msg) {
browser.tabs.query({active: true, currentWindow: true}, function(tabs){
browser.tabs.sendMessage(tabs[0].id, JSON.stringify(msg), function(response) {});
});
});
port.onDisconnect.addListener(onDisconnected);
}
browser.runtime.onMessageExternal.addListener(
function(request, sender, sendResponse) {
if (port == null) {
connect();
}
sendNativeMessage(request);
});
Inject.js
//Prevent code being injected twice(probably because of click listeners on web page)
if (document.readyState !== "complete") {
browser.runtime.onMessage.addListener(function(msg, sender, sendResponse) {
var obj = JSON.parse(msg);
if (!obj.success) {
(...)
}
if (obj.action == "doSomething") {
if (obj.last == "true") {
do something
}else {
var value = $("#input").val().trim() + obj.value.trim();
$("#input").val(value.trim());
}
}
var s = document.createElement('script');
// TODO: add "script.js" to web_accessible_resources in manifest.json
s.src = browser.runtime.getURL('script.js');
s.onload = function() {
this.remove();
};
(document.head || document.documentElement).appendChild(s);
}
script.js
class extensionName{
getValues() {
window.postMessage({ type: "FROM_PAGE", text: {action: "getValues"} }, "*");
}
//This is the function that returns more than 1 mb.
dosomething(parameter1,parameter2,parameter3,parameter4) {
window.postMessage({ type: "FROM_PAGE", text: {action: "dosomething",parameter1Key:parameter1,parameter2Key:parameter2,parameter3Key:parameter3,parameter4Key:parameter4} }, "*");
}
}
Нативное приложение на Java (aux — это экземпляр вспомогательного класса, который имеет функцию sendMessage, которая отправляет сообщения в соответствии с нативным протоколом обмена сообщениями)
switch (parameter1) {
case "getValues":
json = functions.getValues();
aux.sendMessage(json);
break;
case "doSomething":
funcoes.doSomething(...);
break;
(...)
public String doSomething(...) {
(...)
Matcher m = Pattern.compile(".{1,565048}").matcher(valueMoreThan1Mb);
String chunk = "";
while(m.find()) {
System.setOut(originalStream);//let stream output values
chunk = newSignatureBase64.substring(m.start(), m.end());
//a json is done here, with needed parameters, action, chunked value.
json = "{\"success\":\"true\",\"action\":\"sign\",\"last\":\"false\",\"value\":\""+chunk+"\"}";/Sorry for this. This code will be improved when everything is working.
aux.sendMessage(json);//auxiliar class sends message according to native messaging protocol.
System.setOut(dummyStream);//avoid 3rd party library output contents and mess native messaging port.
}
System.setOut(originalStream);//let stream output values
json = "{\"success\":\"true\",\"action\":\"sign\",\"last\":\"true\"}";//Sorry for this. This code will be improved when everything is working.
aux.sendMessage(json);
System.setOut(dummyStream);
return "";
}
Вспомогательный.java
public class Auxiliar {
public int getInt(byte[] bytes) {
return (bytes[3] << 24) & 0xff000000 | (bytes[2] << 16) & 0x00ff0000
| (bytes[1] << 8) & 0x0000ff00 | (bytes[0] << 0) & 0x000000ff;
}
public String readMessage(InputStream in) throws IOException {
byte[] b = new byte[4];
in.read(b);
int size = getInt(b);
//log(String.format("The size is %d", size));
if (size == 0) {
throw new InterruptedIOException("Blocked communication");
}
b = new byte[size];
in.read(b);
return new String(b, "UTF-8");
}
public boolean sendMessage(String message) {
try {
System.out.write(getBytes(message.length()));
System.out.write(message.getBytes("UTF-8"));
System.out.flush();
return true;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}
}
//Use this in case the other method get deprecated
public byte[] getBytes(int length) {
byte[] bytes = new byte[4];
bytes[0] = (byte) (length & 0xFF);
bytes[1] = (byte) ((length >> 8) & 0xFF);
bytes[2] = (byte) ((length >> 16) & 0xFF);
bytes[3] = (byte) ((length >> 24) & 0xFF);
return bytes;
}
}