Полезная информация

Пользователи не любят читать документацию. Станьте оригинальным, будьте не как все. Ознакомьтесь с нашей базой знаний.
  • Форумы
  •  » Разработка
  •  » Firefox 4: платформенно-зависимые бинарные компоненты в расширениях

№109-02-2011 15:32:33

hydrolizer
Участник
 
Группа: Extensions
Зарегистрирован: 22-07-2009
Сообщений: 1945
UA: Firefox 4.0

Firefox 4: платформенно-зависимые бинарные компоненты в расширениях

.. а точнее, проблема доступа к ним. Ситуация: имеется самописная сишная 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, инсталлирую (попутно смотрю в консоль: всё в порядке, ошибок и варнингов нет). Пытаюсь вызвать код - он рвется на строке

Выделить код

Код:

var foolib=ctypes.open("foolib.dll");

с сообщением "can't open library". Вставляю в код

Выделить код

Код:

var foolibname=ctypes.libraryName("foolib")

- возвращает "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). Ну, и вообще хотелось бы в итоге сделать "как положено", а не опять же своими кустарными способами.

Отсутствует

 

№226-02-2011 22:57:30

hydrolizer
Участник
 
Группа: Extensions
Зарегистрирован: 22-07-2009
Сообщений: 1945
UA: Firefox 4.0

Re: Firefox 4: платформенно-зависимые бинарные компоненты в расширениях

Возвращаясь к теме: в 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...

Отсутствует

 

№314-03-2011 17:14:22

hydrolizer
Участник
 
Группа: Extensions
Зарегистрирован: 22-07-2009
Сообщений: 1945
UA: Firefox 4.0

Re: Firefox 4: платформенно-зависимые бинарные компоненты в расширениях

Кажется, относительно прописывания бинарных компонентов в 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
binary-component platform/WINNT_x86-msvc/foolib.dll ABI=WINNT_x86-msvc

(имена .xpt и .dll не обязательно должны совпадать).

Теперь вопрос следующий. Он находится немного в стороне от данной темы, но связан с ней. Бинарный компонент при старте FF вешает хук на главное окно FF, метод коллбэка хука - в той же dll, которая объявлена для компонента в манифесте. Разумеется, после навешивания хука на dll вешается блокировка файловой системы. Сама логика работы расширения не предполагает снятия хука (хотя метод для этого на всякий случай предусмотрен). Но: при удалении расширения хук необходимо снять, иначе расширение не удалится ввиду наличия блокировки на dll. Напрашивается решение в виде некоего uninstall-скрипта, который будет подчищать перед удалением всё, что нельзя удалить штатными средствами. Только лично я расширений с функционалом в виде uninstall не видел - поэтому если кому-то такие известны - сообщите, пожалуйста.

Отсутствует

 

№414-03-2011 21:18:44

Infocatcher
Not found
 
Группа: Extensions
Зарегистрирован: 24-05-2007
Сообщений: 4339
UA: Firefox 4.0

Re: Firefox 4: платформенно-зависимые бинарные компоненты в расширениях

hydrolizer пишет

расширений с функционалом в виде uninstall

https://developer.mozilla.org/en/Addons … ener%28%29
https://developer.mozilla.org/en/Observ … on_Manager
Я пробовал примерно так:

Выделить код

Код:

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 и чего-то еще – забыл, давно дело было :))
Правда, проверялось все это когда новый AddonManager еще только появился. Пока работает, вроде бы.


Прошлое – это локомотив, который тянет за собой будущее. Бывает, что это прошлое вдобавок чужое. Ты едешь спиной вперед и видишь только то, что уже исчезло. А чтобы сойти с поезда, нужен билет. Ты держишь его в руках. Но кому ты его предъявишь?
Виктор Пелевин. Желтая стрела

Отсутствует

 

№514-03-2011 21:23:21

hydrolizer
Участник
 
Группа: Extensions
Зарегистрирован: 22-07-2009
Сообщений: 1945
UA: Firefox 4.0

Re: Firefox 4: платформенно-зависимые бинарные компоненты в расширениях

Infocatcher
Спасибо, буду пробовать.

Отсутствует

 

№618-03-2011 01:58:12

hydrolizer
Участник
 
Группа: Extensions
Зарегистрирован: 22-07-2009
Сообщений: 1945
UA: Firefox 4.0

Re: Firefox 4: платформенно-зависимые бинарные компоненты в расширениях

Infocatcher
Всё, сделал свой uninstaller - всё практически как в приведенном вами коде. Единственное, с чем пришлось немного повозиться - вот с этим моментом:

Выделить код

Код:

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 именно так и сделано. А в остальном всё работает вполне нормально. Спасибо.

Отсутствует

 

№704-06-2011 04:32:15

hydrolizer
Участник
 
Группа: Extensions
Зарегистрирован: 22-07-2009
Сообщений: 1945
UA: Firefox 5.0

Re: Firefox 4: платформенно-зависимые бинарные компоненты в расширениях

Подниму тему, т.к. ниже речь пойдет о проблеме, связанной именно с бинарным компонентом в расширении (вот в этом). Итак, пользователь сообщает, что у него расширение не работает. У меня, и еще у энного количества пользователей оно работает нормально (проверялось для 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_

x86

-msvc


, и несмотря на то, что, как в этом топике было выше приведено, путь к 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 определяет и платформу в т.ч.) - сообщите, пожалуйста.

Отредактировано hydrolizer (11-09-2012 03:42:54)

Отсутствует

 

№810-06-2011 18:41:56

Unghost
Призрак-админ
 
Группа: Administrators
Откуда: Moscow, Russia
Зарегистрирован: 08-10-2004
Сообщений: 11771
UA: Nightly 7.0

Re: Firefox 4: платформенно-зависимые бинарные компоненты в расширениях

Но это потом, сейчас просто хотелось бы выдавать сообщение о невозможности работы на 64-х разрядной платформе - а для этого надо как-то определить фактическую разрядность платформы.

Разве нельзя ли из расширения определить текущий user agent браузера?
Присутствие там WOW64 сразу говорит о том что это 32-битный браузер запущенный на 64-битной ОС.


Do not meddle in the affairs of Wizards, for they are subtle and quick to anger.

Отсутствует

 

№911-06-2011 00:32:04

hydrolizer
Участник
 
Группа: Extensions
Зарегистрирован: 22-07-2009
Сообщений: 1945
UA: Firefox 5.0

Re: Firefox 4: платформенно-зависимые бинарные компоненты в расширениях

Unghost
Да, user agent вполне можно определить. Мне как раз не хватало подсказки в этом направлении. Спасибо.

Отсутствует

 
  • Форумы
  •  » Разработка
  •  » Firefox 4: платформенно-зависимые бинарные компоненты в расширениях

Board footer

Powered by PunBB
Modified by Mozilla Russia
Copyright © 2004–2020 Mozilla Russia GitHub mark
Язык отображения форума: [Русский] [English]