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

Юристы зарабатывают огромные деньги и славу, оперируя хорошим знанием законов. Правила форума — простой путь к успешному общению.

№102-03-2010 12:35:18

Delivron
Участник
 
Группа: Members
Зарегистрирован: 01-04-2009
Сообщений: 24
UA: Firefox 3.6

Создание обработчика событий браузера в VC++

Добрый день. Есть необходимость добавить в свое расширение, написанное на VC++, обработчик событий браузера (в частности, чтобы отлавливать переход пользователя по ссылке). В книжке "Creating XPCOM Components" описывается пример плагина (WebLock), который, по-видимому, содержит данный функционал, но к сожалению исходного кода к нему я не нашел, а того, что есть в книге, мне оказалось недостаточно.

Если я правильно понял для решения моей задачи нужно:
1) создать собственный класс, реализующий интерфейс nsIWebProgressListener и реализовать в нем метод onLocationChange
2) запросить интерфейс nsIWebBrowser и передать в его методе addWebBrowserListener экземпляр собственного класса и IDD nsIWebProgressListener
так?

Как бы то ни было, проверить эту схему мне пока не удалось, поскольку не удается даже скомпилировать проект: во-первых, на сколько я понял, необходимо самому реализовать методы nsISupport в своем классе,  или это можно сделать каким-нибудь макросом? во-вторых, компилятор ругается на абстрактные классы nsIURI и nsIRequest, которые используются в параметрах функций интерфейса nsIWebProgressListener, как быть с ними?

Отсутствует

 

№203-03-2010 14:50:14

Delivron
Участник
 
Группа: Members
Зарегистрирован: 01-04-2009
Сообщений: 24
UA: Firefox 3.6

Re: Создание обработчика событий браузера в VC++

Схема, наконец-то, начала компилироваться, однако, конечно же, пока не работает! :)

Есть пара подозрительных мест в реализации, но какие именно работают некорректно - не понятно. Может у кого будут идеи? Вот эти места:
1) класс-обработчик, который я создаю не является полноценным XPCOM объектом (т.е. у него нету ID, и методы nsISupport реализуются вручную)
2) недостаточно полная реализация всех методов, требующихся для регистрации подписки

В итоге ниже приведенные код падает с 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 я бы даже не дошел)

Отсутствует

 

№303-03-2010 18:13:10

Elexander
Участник
 
Группа: Members
Зарегистрирован: 06-10-2008
Сообщений: 54
UA: Opera 10.1

Re: Создание обработчика событий браузера в VC++

Объект должен реализовывать кроме nsIWebProgressListener еще nsISupportsWeakReference и nsIWeakReference, в методах которых возвращать себя же.

Отсутствует

 

№403-03-2010 18:29:09

myasoex
Участник
 
Группа: Members
Зарегистрирован: 01-03-2010
Сообщений: 5
UA: Chrome 4.0

Re: Создание обработчика событий браузера в VC++

помимо 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)

Отсутствует

 

№504-03-2010 08:18:25

Delivron
Участник
 
Группа: Members
Зарегистрирован: 01-04-2009
Сообщений: 24
UA: Firefox 3.6

Re: Создание обработчика событий браузера в VC++

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 - тогда будет проблема; но если он будет работать только с экземпляром передаваемого объекта, то необходимости регистрации я не вижу.

Отредактировано Delivron (04-03-2010 11:04:49)

Отсутствует

 

№604-03-2010 11:01:28

Elexander
Участник
 
Группа: Members
Зарегистрирован: 06-10-2008
Сообщений: 54
UA: Opera 10.1

Re: Создание обработчика событий браузера в VC++

Мне сложно что-то посоветовать, потому что я подключаю перехватчик прогресса по другому. Я передаю свой 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. Нужно реагировать на открытие новой вкладки и каждый раз подключаться. При закрытии, соответственно, отключаться. У вас, я так понял, какой-то универсальный метод, но я так не пробовал. Посоветовать нечего.

Отсутствует

 

№704-03-2010 15:02:29

Delivron
Участник
 
Группа: Members
Зарегистрирован: 01-04-2009
Сообщений: 24
UA: Firefox 3.6

Re: Создание обработчика событий браузера в VC++

Решил пойти по другому пути. В исходниках мозиллы нашел некий класс CWebBrowserContainer. Этот класс, похоже, используется объектом CMozillaBrowser для получения каких-то событий. По крайней мере, я нашел в нем конструкцию подключения, схожую с моей. Однако, CWebBrowserContainer не реализует интерфейсы nsISupportsWeakReference и nsIWeakReference, вместо этого он просто наследует класс nsWeakReference. Я добавил исходники nsWeakReference в свой проект, занаследовал от него свой класс и это чудо не только скомпилировалось но и... не завалилось. Но теперь я просто получаю в nsCOMPtr<nsIWeakReference> listener нуль. Вопрос: может ли это быть из-за того, что я линкую библиотеки старого XPCOM SDK? (правда Unresolved Externals не возникают, а новое SDK подключать проблематично)

Отсутствует

 

№804-03-2010 17:25:12

Delivron
Участник
 
Группа: Members
Зарегистрирован: 01-04-2009
Сообщений: 24
UA: Firefox 3.6

Re: Создание обработчика событий браузера в VC++

Добился нормального получения nsCOMPtr<nsIWeakReference> listener и даже AddWebBrowserListener возвращает True. Однако уведомления о событиях все равно не приходят... Как бы проверить, что еще может быть не так? Как, например, проверить, что у меня рабочая ссылка на nsIWebBrowser (помимо возвращенного положительного результата от do_GetService)?

Отсутствует

 

№904-03-2010 17:53:09

Elexander
Участник
 
Группа: Members
Зарегистрирован: 06-10-2008
Сообщений: 54
UA: Opera 10.1

Re: Создание обработчика событий браузера в VC++

Посмотреть на nsIWebBrowser.contentDOMWindow.document.tagName, должен  быть 'html'. Ну или еще по каким то свойствам пройтись.

Отсутствует

 

Board footer

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