>Форум Mozilla Россия http://forum.mozilla-russia.org/index.php >Разработка http://forum.mozilla-russia.org/viewforum.php?id=18 >Firefox 4: платформенно-зависимые бинарные компоненты в расширениях http://forum.mozilla-russia.org/viewtopic.php?id=48129 |
hydrolizer > 09-02-2011 15:32:33 |
.. а точнее, проблема доступа к ним. Ситуация: имеется самописная сишная dll, платформа - WINNTx86/MSVC. Пытаюсь сделать простейший вызов с использованием ctypes.jsm - нативный метод без входных параметров просто возвращает версию dll. Для начала кладу dll в %SystemRoot%\system32. Вызов отрабатывает нормально, всё в порядке. Далее, в соответствии с изложенными здесь рекомендациями, пытаюсь поместить библиотеку в папку components расширения. В манифесте указываю: binary-component components/foolib.dll ABI=WINNT_x86-msvc , в install.rdf указываю em:unpack=true. Делаю .xpi, инсталлирую (попутно смотрю в консоль: всё в порядке, ошибок и варнингов нет). Пытаюсь вызвать код - он рвется на строке с сообщением "can't open library". Вставляю в код - возвращает "foolib.dll", пытаюсь результат от ctypes.libraryName("foolib") вставить в ctypes.open - та же ошибка. Всяческие манипуляции с путем, именем, и т.п. результата не дали. В результате я поступил так: положил dll в modules, рядом с jsm, который эту библиотеку использует, путь к dll получаю так: Выделить код Код:AddonManager.getAddonByID(extID, function(addon) { var lib = addon.getResourceURI("modules/foolib.dll").QueryInterface(Ci.nsIFileURL).file; libpath=lib.exists() ? lib.path : null; }); - этот код работает вполне нормально. Но всё же остается открытым вопрос, как использовать библиотеку в случае, если она входит в состав xpi - а такой случай предусмотрен, и вполне может считаться штатным. Ведь вышеприведенное объявление в манифесте, например, позволяет контролировать целевую платформу - иначе придется делать это своими кустарными методами (через nsIXULRuntime/nsIXULAppInfo). Ну, и вообще хотелось бы в итоге сделать "как положено", а не опять же своими кустарными способами. |
hydrolizer > 26-02-2011 22:57:30 |
Возвращаясь к теме: в Nightly Tester Tools недавно случайно наткнулся, как вопрос с бинарным компонентом решают они. Выглядит это так: в chrome.manifest прописывается binary-component platform/WINNT_x86-msvc/foolib.dll ABI=WINNT_x86-msvc и далее в jsm-обёртке Выделить код Код:var dir = __LOCATION__.parent.parent; var file = dir.clone(); file.append("platform"); let xr = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime); file.append(xr.OS + "_" + xr.XPCOMABI); file.append(ctypes.libraryName("foolib")); var libpath=file.path; т.е. всё же получается, что каких-то встроенных функций, базирующихся на информации из chrome.manifest для бинарного компонента, нет, и путь к компоненту конструируется фактически вручную - я его мог бы положить в папку с любым именем, а дальше, отталкиваясь от __LOCATION__, сконструировать путь. Но лучше всё же уж так, чем определять путь в коллбэке AddonManager.getAddonByID... |
hydrolizer > 14-03-2011 17:14:22 |
Кажется, относительно прописывания бинарных компонентов в chrome.manifest всё прояснилось. Строка вида binary-component platform/WINNT_x86-msvc/foolib.dll ABI=WINNT_x86-msvc нужна, и именно в приведенном виде, в случае, если у нас бинарный компонент является scriptable не посредством ctypes, а как обычный XPCOM-компонент, и состоит из двух частей: интерфейсной в виде .xpt, и реализации в виде .dll - запись вида "binary-component..." нужна, чтобы FF правильно подгрузил бинарную реализацию для интерфейсной части. Полностью запись в манифесте выглядит так: interfaces components/fooClass.xpt (имена .xpt и .dll не обязательно должны совпадать). Теперь вопрос следующий. Он находится немного в стороне от данной темы, но связан с ней. Бинарный компонент при старте FF вешает хук на главное окно FF, метод коллбэка хука - в той же dll, которая объявлена для компонента в манифесте. Разумеется, после навешивания хука на dll вешается блокировка файловой системы. Сама логика работы расширения не предполагает снятия хука (хотя метод для этого на всякий случай предусмотрен). Но: при удалении расширения хук необходимо снять, иначе расширение не удалится ввиду наличия блокировки на dll. Напрашивается решение в виде некоего uninstall-скрипта, который будет подчищать перед удалением всё, что нельзя удалить штатными средствами. Только лично я расширений с функционалом в виде uninstall не видел - поэтому если кому-то такие известны - сообщите, пожалуйста. |
Infocatcher > 14-03-2011 21:18:44 |
hydrolizer пишет
https://developer.mozilla.org/en/Addons … ener%28%29 Выделить код Код:extensionUninstaller = { guid: "some@guid", isUninstall: false, uninstallConfirmed: false, get oSvc() { delete this.oSvc; return this.oSvc = Components.classes["@mozilla.org/observer-service;1"] .getService(Components.interfaces.nsIObserverService); }, get newAddonManager() { delete this.newAddonManager; return this.newAddonManager = !("@mozilla.org/extensions/manager;1" in Components.classes); }, initUninstallObserver: function() { this.oSvc.addObserver(this, "quit-application-granted", false); if(this.newAddonManager) { try { // In Gecko 2 XPCOM can starts after "final-ui-startup" this.addAddonListener(); } catch(e) { // Wait for AddonManager startup this.oSvc.addObserver(this, "final-ui-startup", false); } } else this.oSvc.addObserver(this, "em-action-requested", false); }, destroyUninstallObserver: function() { this.oSvc.removeObserver(this, "quit-application-granted"); if(this.newAddonManager) AddonManager.removeAddonListener(this); else this.oSvc.removeObserver(this, "em-action-requested"); }, observe: function(subject, topic, data) { if(topic == "final-ui-startup") { this.oSvc.removeObserver(this, "final-ui-startup"); this.addAddonListener(); } else if(topic == "quit-application-granted") { this.destroyUninstallObserver(); if(this.isUninstall && this.uninstallConfirmed) this.uninstall(); } else if( topic == "em-action-requested" && subject instanceof Components.interfaces.nsIUpdateItem && subject.id == this.guid ) { if(data == "item-uninstalled") this.handleUninstalling(); else if(data == "item-cancel-action") this.isUninstall = false; } }, addAddonListener: function() { // Firefox 3.7a5pre+: // In Firefox 1.5 we can't use "import" keyword (we get syntax error) Components.utils["import"]("resource://gre/modules/AddonManager.jsm"); //AddonManagerPrivate.startup(); AddonManager.addAddonListener(this); }, onUninstalling: function(ext, requiresRestart) { if(ext.id == this.guid) this.handleUninstalling(); }, onOperationCancelled: function(ext) { if( ext.id == this.guid && !(ext.pendingOperations & AddonManager.PENDING_UNINSTALL) ) this.isUninstall = false; }, handleUninstalling: function() { this.isUninstall = true; this.uninstallConfirm(); }, uninstallConfirm: function() { this.uninstallConfirmed = true; // Or ask user... }, uninstall: function() { // Do something } }; extensionUninstaller.initUninstallObserver(); (Основано на коде Mouse Gestures и чего-то еще – забыл, давно дело было ) |
hydrolizer > 14-03-2011 21:23:21 |
Infocatcher |
hydrolizer > 18-03-2011 01:58:12 |
Infocatcher Выделить код Код:try { // In Gecko 2 XPCOM can starts after "final-ui-startup" this.addAddonListener(); } catch(e) { // Wait for AddonManager startup this.oSvc.addObserver(this, "final-ui-startup", false); } - хотя у меня, сколько раз я ни пробовал, XPCOM стартовал всегда до final-ui-startup, я решил просто смоделировать ситуацию - топик не ловился. Выяснилось, что для того, чтобы поймать final-ui-startup, нужен обсервер, зарегистрированный через Category Manager на profile-after-change, тогда все прочие подписчики смогут поймать в т.ч. и final-ui-startup - в Mouse Gestures именно так и сделано. А в остальном всё работает вполне нормально. Спасибо. |
hydrolizer > 04-06-2011 04:32:15 |
Подниму тему, т.к. ниже речь пойдет о проблеме, связанной именно с бинарным компонентом в расширении (вот в этом). Итак, пользователь сообщает, что у него расширение не работает. У меня, и еще у энного количества пользователей оно работает нормально (проверялось для WinXP/Vista/Win7). Начинаю разбираться - выясняется, что первое же обращение через ctypes к методу в dll возвращает ошибку с кодом 998 - это то, что возвращает WinAPI-функция GetLastError. 998 - это ERROR_NOACCESS, возвращаемый LoadLibrary. Далее, выясняется, что у пользователя Win7 x64 (а официальных сборок x64 для FF4.x в природе не существует; есть только ночные англоязычные). Следовательно, с очень большой вероятностью FF, несмотря на х64-ОС, 32-х битный. Бинарный компонент компилировался под x86 target platform (со статической линковкой). И несмотря на то, что в chrome.manifest абсолютно однозначно указано, что binary-component platform/WINNT_x86-msvc/skl.dll ABI=WINNT_ , и несмотря на то, что, как в этом топике было выше приведено, путь к dll конструируется из данных, получаемых от nsIXULRuntime, в которые входит nsIXULRuntime.XPCOMABI, который, в свою очередь, содержит разрядность платформы - тем не менее, dll подгрузилась (ERROR_NOACCESS возвращается методом-враппером над функцией WinAPI; если бы не загрузилась моя dll - то и кода ошибки бы не было). Исходя из этого, было бы логично предположить, что nsIXULRuntime возвращает не фактические данные об ОС, а данные той платформы, под которую делалась сборка FF. Поэтому на всякий случай у меня просьба - если у кого-то есть в наличии конфигурация windows x64 (неважно, какого семейства) + FFx86 - проверьте, пожалуйста, как отработает вот этот код: Выделить код Код:alert(Components.classes["@mozilla.org/xre/app-info;1"] .getService(Components.interfaces.nsIXULRuntime).XPCOMABI); (если что - под спойлером код для кастомной кнопки) скрытый текст Выделить код Код:custombutton://%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%3F%3E%0D%0A%3Ccustombutton%20xmlns%3Acb%3D%22http%3A//xsms.nm.ru/custombuttons/%22%3E%0A%20%20%3Cname%3ECheckOSABI%3C/name%3E%0A%20%20%3Cimage%3E%3C%21%5BCDATA%5Bcustombuttons-stdicon-1%5D%5D%3E%3C/image%3E%0A%20%20%3Cmode%3E0%3C/mode%3E%0A%20%20%3Cinitcode%3E%3C%21%5BCDATA%5B/*Initialization%20Code*/%5D%5D%3E%3C/initcode%3E%0A%20%20%3Ccode%3E%3C%21%5BCDATA%5Balert%28Components.classes%5B%22@mozilla.org/xre/app-info%3B1%22%5D%0A%20%20%20%20.getService%28Components.interfaces.nsIXULRuntime%29.XPCOMABI%29%3B%0A%5D%5D%3E%3C/code%3E%0A%20%20%3Caccelkey%3E%3C%21%5BCDATA%5B%5D%5D%3E%3C/accelkey%3E%0A%20%20%3Chelp%3E%3C%21%5BCDATA%5B%5D%5D%3E%3C/help%3E%0A%20%20%3Cattributes/%3E%0A%3C/custombutton%3E Ну и, в общем, понятно, что для поддержки х64-платформы в составе расширения должна быть еще одна dll c x64 target platform. Но это потом, сейчас просто хотелось бы выдавать сообщение о невозможности работы на 64-х разрядной платформе - а для этого надо как-то определить фактическую разрядность платформы. Если есть какие-то способы (а они наверняка должны быть - тот же движок форума при определении UA определяет и платформу в т.ч.) - сообщите, пожалуйста. |
Unghost > 10-06-2011 18:41:56 |
Разве нельзя ли из расширения определить текущий user agent браузера? |
hydrolizer > 11-06-2011 00:32:04 |
Unghost |