Маленький фон
Я работаю пару дней на расширении Chrome, которое делает снимок экрана с заданных веб-страниц несколько раз в день. Я использовал этот в качестве руководства, и все работает так, как ожидалось.
Однако одно небольшое расширение требований не может встретиться. Пользователь должен иметь доступ к папке, в которой сохранены изображения (скриншоты), но Расширения Chrome не имеют доступа к файловой системе. С другой стороны, Chrome Apps. Таким образом, после многого оглядываясь, я пришел к выводу, что должен создать как расширение Chrome, так и приложение Chrome. Идея состоит в том, что расширение создало бы blob скриншота, а затем отправило бы этот blob в приложение, которое затем сохранит его как изображение в указанном пользователем месте. И это именно то, что я делаю - я создаю blob screentshot на стороне расширения, а затем отправляю его в приложение, где пользователю предлагается выбрать, где сохранить изображение.
Проблема
До части сохранения все работает так, как ожидалось. Блаб создается на добавочном номере, отправляется в приложение, полученном приложением, пользователь спрашивает, где сохранить, и изображение сохраняется. Это то, где вещи разваливаются. Результирующее изображение непригодно. Когда я пытаюсь открыть его, я получаю сообщение с надписью "Невозможно определить тип". Ниже приведен код, который я использую:
-
Сначала на стороне расширения, я создаю blob и отправляю его, например:
chrome.runtime.sendMessage( APP_ID, /* I got this from the app */ {myMessage: blob}, /* Blob created previously; it correct */ function(response) { appendLog("response: "+JSON.stringify(response)); } );
-
Затем, на стороне APP, я получаю blob и пытаюсь сохранить его следующим образом:
// listen for external messages chrome.runtime.onMessageExternal.addListener( function(request, sender, sendResponse) { if (sender.id in blacklistedIds) { sendResponse({"result":"sorry, could not process your message"}); return; // don't allow this extension access } else if (request.incomingBlob) { appendLog("from "+sender.id+": " + request.incomingBlob); // attempt to save blob to choosen location if (_folderEntry == null) { // get a directory to save in if not yet chosen openDirectory(); } saveBlobToFile(request.incomingBlob, "screenshot.png"); /* // inspect object to try to see what wrong var keys = Object.keys(request.incomingBlob); var keyString = ""; for (var key in keys) { keyString += " " + key; } appendLog("Blob object keys:" + keyString); */ sendResponse({"result":"Ok, got your message"}); } else { sendResponse({"result":"Ops, I don't understand this message"}); } } );
Здесь функция ON APP, которая выполняет фактическое сохранение:
function saveBlobToFile(blob, fileName) { appendLog('entering saveBlobToFile function...'); chrome.fileSystem.getWritableEntry(_folderEntry, function(entry) { entry.getFile(fileName, {create: true}, function(entry) { entry.createWriter(function(writer) { //writer.onwrite = function() { // writer.onwrite = null; // writer.truncate(writer.position); //}; appendLog('calling writer.write...'); writer.write(blob); // Also tried writer.write(new Blob([blob], {type: 'image/png'})); }); }); }); }
Ошибок нет. Никаких икота. Код работает, но изображение бесполезно. Что именно мне не хватает? Где я иду не так? Может быть, мы можем передавать строки между расширениями/приложениями? Является ли blob поврежденным в пути? У моего приложения нет доступа к блобу, потому что он был создан на расширении? Может ли кто-нибудь пролить некоторый свет?
ОБНОВЛЕНИЕ (9/23/14) Извините за последнее обновление, но мне был назначен другой проект, и я не мог вернуться к нему до 2 дней назад.
Итак, после многого оглядываясь, я решил пойти с предложением @Danniel Herr, которое предлагает использовать SharedWorker и страницу, встроенную в фрейм в приложении. Идея заключается в том, что Extension будет поставлять blob в SharedWorker, который пересылает blob на страницу в расширении, встроенном в фрейм в приложении. Эта страница, а затем переводит blob в приложение, используя parent.postMessage(...). Это немного громоздко, но, похоже, это единственный вариант, который у меня есть.
Позвольте мне опубликовать некоторый код, чтобы он стал более понятным:
Расширение:
var worker = new SharedWorker(chrome.runtime.getURL('shared-worker.js'));
worker.port.start();
worker.postMessage('hello from extension'); // Can send blob here too
worker.port.addEventListener("message", function(event) {
$('h1Title').innerHTML = event.data;
});
proxy.js
var worker = new SharedWorker(chrome.runtime.getURL('shared-worker.js'));
worker.port.start();
worker.port.addEventListener("message",
function(event) {
parent.postMessage(event.data, 'chrome-extension://[extension id]');
}
);
proxy.html
<script src='proxy.js'></script>
разделяемых-worker.js
var ports = [];
var count = 0;
onconnect = function(event) {
count++;
var port = event.ports[0];
ports.push(port);
port.start();
/*
On both the extension and the app, I get count = 1 and ports.length = 1
I'm running them side by side. This is so maddening!!!
What am I missing?
*/
var msg = 'Hi, you are connection #' + count + ". ";
msg += " There are " + ports.length + " ports open so far."
port.postMessage(msg);
port.addEventListener("message",
function(event) {
for (var i = 0; i < ports.length; ++i) {
//if (ports[i] != port) {
ports[i].postMessage(event.data);
//}
}
});
};
В приложении
context.addEventListener("message",
function(event) {
appendLog("message from proxy: " + event.data);
}
);
Итак, это поток выполнения... На расширении я создаю общего рабочего и отправлю ему сообщение. Общий рабочий должен иметь возможность получать blob, но для целей тестирования я просто отправляю простую строку.
Затем общий рабочий получает сообщение и пересылает его всем, кто подключился. Прокси .html/js, который находится внутри фрейма в приложении, действительно подключился к этому моменту и должен получить что-либо, переданное общим рабочим.
Затем proxy.js [должен] получает сообщение от общего рабочего и отправляет его в приложение, используя parent.postMessage(...). Приложение прослушивает через window.addEventListener( "сообщение",...).
Чтобы протестировать этот поток, я сначала открываю приложение, затем нажимаю кнопку расширения. Я не получаю сообщения в приложении. У меня тоже нет ошибок.
Расширение может поддерживать связь с совместно используемым рабочим. Приложение может прекрасно общаться с общим рабочим. Однако сообщение, отправленное из приложения extension- > proxy- > , не доходит до приложения. Что мне не хватает?
Извините за длинные ребята, но я надеюсь, что кто-то прольет свет, так как это сводит меня с ума.
Спасибо