Плагин NPAPI, удаление ребенка с веб-страницы дает сбой Firefox4 и Chrome

У меня есть html-страница, которая открывает новое окно и загружает базовый плагин, написанный NPAPI, который я открываю в диалоговом окне Wide Save, а затем вызываю NPN_GetURL с функцией java-скрипта, чтобы закрыть окно. Каждый раз, когда Firefox вылетает и Chrome отображает, плагин терпит крах. Я не уверен, что проблема в HTML и JS или в плагине. Я не нашел много, когда искал в Google другие похожие проблемы. Ниже находится моя страница, которая загружает плагин, и плагин вызывает функцию javascript «removePlugin». По поводу firefox никаких проблем в 3.6 только в версии 4

----Начинать

<html>
 <script language="javascript">
  function removePlugin()
   {
   var plgn = document.getElementById("myplugin1");
   document.getElementById("div1").removeChild(plgn);
   setTimeout('doClose()', 2000);
   }
 function doClose()
  {
  window.close();
  }
 </script>
 <body >
  <div id="div1">
   <embed type="application/x-My-Plugin" id="myplugin1"></embed>
  </div>
 </body>
</html>

----Конец

---- Начало кода плагина

#include "npapi.h"

//Prottype
LRESULT CALLBACK    PluginWindowProc  (HWND,UINT,WPARAM,LPARAM);

//Define
#define MY_MESSAGE      WM_USER + 1000

//Global
const char*     gInstanceLookupString = "instance";
WNDPROC         fDefaultWindowProc;

//Function:    NPP_SetWindow
NPError NPP_SetWindow(NPP       instance,
                      NPWindow *window)
{
    fDefaultWindowProc = (WNDPROC)SetWindowLongPtr((HWND)window->window,
                                                   GWL_WNDPROC,
                                                   (LONG)PluginWindowProc);
    SetProp(window->window,
            gInstanceLookupString,
            (HANDLE)instance);
    SendMessage(window->window,
                MY_MESSAGE,
                0,
                0);
    return NPERR_NO_ERROR;
}

//PluginWindowProc
LRESULT CALLBACK PluginWindowProc(HWND      hWnd,
                                  UINT      Msg,
                                  WPARAM    wParam,
                                  LPARAM    lParam)
{
OPENFILENAMEW       ofn;                                                                    //Fix.3a
WCHAR               szFile[512];                                //File name that appears in the Save Dialog box //Fix.3a
NPP                 instance;

    switch(Msg)
        {
        case MY_MESSAGE:
            instance = (NPP)GetProp(hWnd,
                                    gInstanceLookupString);
            //SAVE----------------------------------------
            memset(&ofn,
                   0x00,
                   sizeof(OPENFILENAMEW));

            memset(szFile,
                   0x00,
                   sizeof(szFile));
            _snwprintf_s(szFile,                                
                        _countof(szFile),
                        _countof(szFile),
                        L"Test.Txt");
            ofn.lStructSize = sizeof(OPENFILENAME);            
            ofn.lpstrFile = szFile;
            ofn.nMaxFile = _countof(szFile);
            ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;

            GetSaveFileNameW(&ofn);


            //CLOSE---------------------------------------
            NPN_GetURL(instance,
                       "javascript:removePlugin(0);",
                       "_self");

            //--------------------------------------------
            break;
        default:
            CallWindowProc(fDefaultWindowProc,
                           hWnd,
                           Msg,
                           wParam,
                           lParam);
            break;
        }
    return 0;
    }

//Function:    NPP_Destroy
NPError NPP_Destroy(NPP instance,NPSavedData **save){return NPERR_NO_ERROR;}

//Function:    NPP_DestroyStream
NPError NPP_DestroyStream(NPP instance, NPStream *stream, NPError   reason){return NPERR_NO_ERROR;}

//Function:    NPP_HandleEvent
int16 NPP_HandleEvent(NPP instance,void* event){return 0;}

//Function:    NPP_Initialize
NPError NPP_Initialize(void){return NPERR_NO_ERROR;}

//Function:    NPP_New
NPError NPP_New(NPMIMEType pluginType,NPP instance, uint16 mode, int16 argc,char* argn[], char * argv[],NPSavedData* saved){return (NPERR_NO_ERROR);}

//Function: NPP_NewStream
NPError NPP_NewStream(NPP instance,NPMIMEType type, NPStream *stream, NPBool seekable, uint16 *stype){ return NPERR_NO_ERROR;}

//Function: NPP_Print
void NPP_Print(NPP instance, NPPrint *printInfo){}

//Function: NPP_Shutdown
void NPP_Shutdown(void){}

//Function: NPP_StreamAsFile
void NPP_StreamAsFile(NPP instance, NPStream *stream, const char *fname){}

//Function: NPP_URLNotify
void NPP_URLNotify(NPP instance, const char *url, NPReason reason, void *notifyData){}

//Function: NPP_Write
int32 NPP_Write(NPP instance, NPStream *stream, int32 offset, int32 len, void *buffer)        {return 0;}

//Function: NPP_WriteReady
int32 NPP_WriteReady(NPP instance, NPStream *stream){return 0;}

---- Конец кода плагина


person hapyfishrmn    schedule 13.06.2011    source источник
comment
Вы должны предоставить источник плагина, который дает сбой.   -  person jmtd    schedule 13.06.2011
comment
трассировка стека или журнал сбоев также (или альтернативно) были бы очень полезны. То, что вы нам дали, не очень-то полезно; Могу сказать вам, что я сделал то же самое без труда, но поскольку мой плагин, несомненно, отличается от вашего, это вам не поможет. Прикрепили ли вы отладчик, чтобы узнать, в вашем коде или в firefox, сбой?   -  person taxilian    schedule 13.06.2011
comment
Как получить трассировку стека или журнал? Я подключился к firefox с помощью Firebug, и кажется, что проблема с removeChild, но я думаю, что это больше связано с плагином.   -  person hapyfishrmn    schedule 14.06.2011
comment
вы получаете трассировку стека с помощью отладчика C ++, а не отладчика javascript. Кроме того, вы можете сделать about: crashes, чтобы просмотреть последние отчеты о сбоях.   -  person taxilian    schedule 03.07.2011
comment
Я обратился к about: crashes, и вот отчет о сбое: crash-stats.mozilla.com/report/index/ кто-нибудь знает, как это интерпретировать?   -  person hapyfishrmn    schedule 07.07.2011


Ответы (1)


Действительно сложно сказать наверняка, что происходит, но я могу сказать вам, что у вашего подхода есть несколько других проблем. Прежде всего, вы никогда не должны блокировать основной поток браузера, что происходит, когда вы открываете диалоговое окно в основном браузере. Теперь я понимаю, что с вами может быть все в порядке (а некоторые могут даже заблуждаться, что другие будут в порядке) с блокировкой диалогового окна (нет, не просто предотвращением ввода, а фактически блокировкой) браузера, пока ваш диалог открыт, но в случаях, когда все текущие браузеры запускают плагин вне процесса и не полностью блокируются, пока диалоговое окно открыто, браузер должен, по крайней мере, спросить пользователя, хотят ли они убить плагин, если не убить его сразу, как Safari 5.1.

Что вам действительно нужно сделать, если вы собираетесь использовать диалог, так это запустить другой поток и поместить в него вызов диалога, а затем позвонить обратно в браузер (в основном потоке! Используйте NPN_PluginThreadAsyncCall), когда закончите.

Что касается журнала сбоев, из того, что он говорит, вы каким-то образом связали дескриптор браузера с плагином, потому что он дает сбой, когда пытается вызвать SetWindow в вашем плагине. Возможно, вам стоит подумать о том, чтобы отбросить эту простую попытку в NPAPI и использовать что-то вроде FireBreath, где хитрые биты NPAPI уже были решено за вас.

person taxilian    schedule 03.09.2011
comment
Ничего себе, я думал, что никогда не получу никаких комментариев по этому поводу. Этот код здесь является урезанной версией, чтобы попытаться найти, где происходит сбой плагина. Я понимаю вашу точку зрения, не позволяя блокировать основной поток плагинов, чтобы его можно было завершить в случае, если что-то пойдет не так. Но дело здесь в том, что общая версия диалога сохранения не работает ИЛИ удаление плагина с веб-страницы вызывает проблемы в FF 4, но не в предыдущих версиях. - person hapyfishrmn; 13.09.2011
comment
нет, вы не понимаете мою точку зрения о том, что основной поток не блокируется. Дело не в том, чтобы его можно было завершить - он будет завершен, если вы заблокируете поток. Вы не должны никогда блокировать основной поток, иначе некоторые браузеры прекратят работу вашего плагина. Другие спросят пользователя, хотят ли они прекратить работу вашего плагина. - person taxilian; 13.09.2011
comment
Следующий пункт - перечитать последний абзац своего ответа; Я понимаю, что это происходит только в FF4, но теперь у FF4 есть внепроцессные плагины, которые меняют ситуацию. Что-то, что вы делаете, портит для вас дескриптор браузера - это может быть или не быть вызвано диалоговым окном сохранения, но что бы это ни было, вы делаете что-то странное, потому что у меня нет проблем с другими плагины, которые я использую. - person taxilian; 13.09.2011