>Форум Mozilla Россия http://forum.mozilla-russia.org/index.php >Разработка http://forum.mozilla-russia.org/viewforum.php?id=18 >Создание обработчика событий браузера в VC++ http://forum.mozilla-russia.org/viewtopic.php?id=43519 |
Delivron > 02-03-2010 12:35:18 |
Добрый день. Есть необходимость добавить в свое расширение, написанное на VC++, обработчик событий браузера (в частности, чтобы отлавливать переход пользователя по ссылке). В книжке "Creating XPCOM Components" описывается пример плагина (WebLock), который, по-видимому, содержит данный функционал, но к сожалению исходного кода к нему я не нашел, а того, что есть в книге, мне оказалось недостаточно. Если я правильно понял для решения моей задачи нужно: Как бы то ни было, проверить эту схему мне пока не удалось, поскольку не удается даже скомпилировать проект: во-первых, на сколько я понял, необходимо самому реализовать методы nsISupport в своем классе, или это можно сделать каким-нибудь макросом? во-вторых, компилятор ругается на абстрактные классы nsIURI и nsIRequest, которые используются в параметрах функций интерфейса nsIWebProgressListener, как быть с ними? |
Delivron > 03-03-2010 14:50:14 |
Схема, наконец-то, начала компилироваться, однако, конечно же, пока не работает! Есть пара подозрительных мест в реализации, но какие именно работают некорректно - не понятно. Может у кого будут идеи? Вот эти места: В итоге ниже приведенные код падает с Access Violation на строке вызова AddWebBrowserListener: Выделить код Код:CWebProgressListener *wpl = new CWebProgressListener(); nsCOMPtr<nsIWebBrowser> webBrowser; nsresult nsRes; webBrowser = do_GetService("@mozilla.org/embedding/browser/nsWebBrowser;1",&nsRes); if (NS_SUCCEEDED(nsRes)) { nsCOMPtr<nsIWeakReference> listener( do_GetWeakReference(static_cast<nsIWebProgressListener*>(wpl),&nsRes)); if (NS_SUCCEEDED(nsRes)) { PRBool bRes = webBrowser->AddWebBrowserListener(listener, NS_GET_IID(nsIWebProgressListener)); } } При этом под дебаггером наблюдается интересная вещь: функция do_GetWeakReference сначала взывает метод wpl.QueryInterface, потом реализованную заглушку wpl.OnStateChange (по-видимому это тестирование, о котором упоминается в исходниках мозиллы), а потом wpl.Release. Что бы это значило? Тестирование завершилось неудачей? (однако nsRes = True, иначе до AddWebBrowserListener я бы даже не дошел) |
Elexander > 03-03-2010 18:13:10 |
Объект должен реализовывать кроме nsIWebProgressListener еще nsISupportsWeakReference и nsIWeakReference, в методах которых возвращать себя же. |
myasoex > 03-03-2010 18:29:09 |
помимо WeakRefernce надо зарегистрироваться в xpcom-startup Выделить код Код:static NS_METHOD UrlCatcherFFRegistration( nsIComponentManager *aCompMgr, nsIFile *aPath, const char *registryLocation, const char *componentType, const nsModuleComponentInfo *info) { nsresult rv; nsCOMPtr<nsIServiceManager> servman = do_QueryInterface((nsISupports*)aCompMgr, &rv); if (NS_FAILED(rv)) return rv; nsCOMPtr<nsICategoryManager> catman; rv = servman->GetServiceByContractID( NS_CATEGORYMANAGER_CONTRACTID, NS_GET_IID(nsICategoryManager), getter_AddRefs(catman)); if (NS_FAILED(rv)) return rv; char* previous = nsnull; rv = catman->AddCategoryEntry( NS_XPCOM_STARTUP_CATEGORY, URLCATCHERFF_CLASSNAME, URLCATCHERFF_CONTRACTID, PR_TRUE, PR_TRUE, &previous); if (previous) nsMemory::Free(previous); return rv; } static NS_METHOD UrlCatcherFFUnregistration( nsIComponentManager *aCompMgr, nsIFile *aPath, const char *registryLocation, const nsModuleComponentInfo *info) { nsresult rv; nsCOMPtr<nsIServiceManager> servman = do_QueryInterface((nsISupports*)aCompMgr, &rv); if (NS_FAILED(rv)) return rv; nsCOMPtr<nsICategoryManager> catman; rv = servman->GetServiceByContractID( NS_CATEGORYMANAGER_CONTRACTID, NS_GET_IID(nsICategoryManager), getter_AddRefs(catman)); if (NS_FAILED(rv)) return rv; rv = catman->DeleteCategoryEntry( NS_XPCOM_STARTUP_CATEGORY, URLCATCHERFF_CLASSNAME, PR_TRUE); return rv; } static nsModuleComponentInfo components[] = { { URLCATCHERFF_CLASSNAME, URLCATCHERFF_CID, URLCATCHERFF_CONTRACTID, CUrlCatcherFFConstructor, UrlCatcherFFRegistration, UrlCatcherFFUnregistration } }; NS_IMPL_NSGETMODULE("UrlCatcherFFModule", components) |
Delivron > 04-03-2010 08:18:25 |
Elexander, интерфейсы nsISupportsWeakReference и nsIWeakReference у меня реализуются, но под дебаггером я в них еще ни разу не попадал. Может быть я не правильно их реализую: Выделить код Код:NS_METHOD CWebProgressListener::QueryReferent(const nsIID & uuid, void **result) { *result = this; return NS_OK; } NS_METHOD CWebProgressListener::GetWeakReference(nsIWeakReference **_retval) { *_retval = this; return NS_OK; } дизасемблер места падения: Выделить код Код:01117549 push offset `nsISupportsWeakReference::GetIID'::`2'::iid (11292B4h) 0111754E mov dword ptr [ebp-0Ch],eax 01117551 lea eax,[ebp-10h] 01117554 push eax 01117555 lea ecx,[ebp+8] 01117558 call nsCOMPtr_base::assign_from_qi_with_error (1117496h) 0111755D mov eax,dword ptr [ebp+8] 01117560 test eax,eax 01117562 je NS_GetWeakReference+43h (1117571h) 01117564 mov ecx,dword ptr [eax] 01117566 lea edx,[ebp-8] 01117569 push edx 0111756A push eax 0111756B call dword ptr [ecx+0Ch] 0111756E mov dword ptr [ebp-4],eax <- 01117571 lea ecx,[ebp+8] 01117574 call nsCOMPtr_base::~nsCOMPtr_base (1117431h) т.е. падает где-то в NS_GetWeakReference() myasoex, Вы уверены, что я должен создать полноценный XPCOM объект конкретно для моего обработчика и регистрировать его в стартапе? Дело в том, что я добавляю код к рабочему компоненту, который уже содержит полноценный XPCOM объект и в том числе регистрацию в стартапе. Т.е. сам компонент грузится при запуске FF. Не работает пока только часть, реализующая обработчик. Другое дело, если уже FF где-то сам захочет создать экземпляр моего объекта через ID - тогда будет проблема; но если он будет работать только с экземпляром передаваемого объекта, то необходимости регистрации я не вижу. |
Elexander > 04-03-2010 11:01:28 |
Мне сложно что-то посоветовать, потому что я подключаю перехватчик прогресса по другому. Я передаю свой nsIWebProgressListener экземпляру nsIWebProgress. Это поле webProgress в browser. А browser получаю так: Выделить код Код:browser = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor) .getInterface(Components.interfaces.nsIWebNavigation) .QueryInterface(Components.interfaces.nsIDocShellTreeItem) .rootTreeItem .QueryInterface(Components.interfaces.nsIInterfaceRequestor) .getInterface(Components.interfaces.nsIDOMWindow).getBrowser(); У меня были проблемы с получением browser в XPCOM, по этому я его получаю в JavaScript и передаю в бинарный компонент ссылку. У каждой вкладки свой browser. Нужно реагировать на открытие новой вкладки и каждый раз подключаться. При закрытии, соответственно, отключаться. У вас, я так понял, какой-то универсальный метод, но я так не пробовал. Посоветовать нечего. |
Delivron > 04-03-2010 15:02:29 |
Решил пойти по другому пути. В исходниках мозиллы нашел некий класс CWebBrowserContainer. Этот класс, похоже, используется объектом CMozillaBrowser для получения каких-то событий. По крайней мере, я нашел в нем конструкцию подключения, схожую с моей. Однако, CWebBrowserContainer не реализует интерфейсы nsISupportsWeakReference и nsIWeakReference, вместо этого он просто наследует класс nsWeakReference. Я добавил исходники nsWeakReference в свой проект, занаследовал от него свой класс и это чудо не только скомпилировалось но и... не завалилось. Но теперь я просто получаю в nsCOMPtr<nsIWeakReference> listener нуль. Вопрос: может ли это быть из-за того, что я линкую библиотеки старого XPCOM SDK? (правда Unresolved Externals не возникают, а новое SDK подключать проблематично) |
Delivron > 04-03-2010 17:25:12 |
Добился нормального получения nsCOMPtr<nsIWeakReference> listener и даже AddWebBrowserListener возвращает True. Однако уведомления о событиях все равно не приходят... Как бы проверить, что еще может быть не так? Как, например, проверить, что у меня рабочая ссылка на nsIWebBrowser (помимо возвращенного положительного результата от do_GetService)? |
Elexander > 04-03-2010 17:53:09 |
Посмотреть на nsIWebBrowser.contentDOMWindow.document.tagName, должен быть 'html'. Ну или еще по каким то свойствам пройтись. |