Xpoint
   [напомнить пароль]

Как определить сетевую ошибку для nsIHttpChannel ?

Метки: [без меток]
2007-01-28 03:54:54 [обр] Cube(2/2)[досье]

Обработчик http-on-modify-request помещает channel запроса в массив, с помощью которого устанавливается соответствие 'запрос-ответ' в обработчике http-on-examine-response.
А как быть, если на сетевой запрос браузер загружает about:neterror - как определить для какого channel это произошло - и произошло ли вообще ?
Пробовал подцеплять observer к channel, но он получает управление, только если запрос обрабатывается нормально.

Подкиньте идею, пожалуйста.

спустя 2 дня 18 часов [обр] Владимир Палант(434/4445)[досье]
nsIStreamListener может быть только один, то есть непосредственно получать уведомления сможет только тот, кто инициировал запрос. Вы же IMHO можете только по таймауту проверять channel.isPending(). Если запрос завершился, то эта функция вернет false, а в channel.status вы найдете код ошибки (если ошибка была).
спустя 18 часов [обр] Cube(2/2)[досье]
получать уведомления сможет только тот, кто инициировал запрос

То есть ? listener ведь работает, если запрос не натыкается на сетевую ошибку.

по таймауту проверять channel.isPending()

Видимо, придётся. Я думал о тайм-ауте, но до isPending как-то не додумался. Спасибо.

p.s. может, всё же есть какой-нибудь способ выцепить безответный channel ? где-то ведь он существует.

спустя 9 минут [обр] Владимир Палант(434/4445)[досье]
Какой listener? Как вы его прикручиваете?
спустя 20 минут [обр] Cube(2/2)[досье]
   ...

    observe: function (subject, topic, data)
    {
        switch (topic)
        {
            case "http-on-modify-request":
            case "http-on-examine-response":
            {
             subject. QueryInterface (nsIHttpChannel);
             ...
            subject. QueryInterface (nsIRequest);
            ...
             if (topic == "http-on-modify-request")
             {
                ...
                var listener = new mylistener (subject);
               subject. QueryInterface (nsIChannel);
               subject. notificationCallbacks = listener;
               ...
            }
            else
            {
               ...
            }
            break;
         }
         ...
         default:;
      }
   },
   
   ...

function mylistener (channel)
{
   this. mChannel = channel;
   LOG ("listener: create")
}

mylistener. prototype =
{
   mChannel : null,

   QueryInterface: function (iid)
   {
      LOG ("listener: QueryInterface: " + iid)
      if (!iid. equals(Components. interfaces. nsISupports) &&
         !iid. equals(Components. interfaces. nsIInterfaceRequestor) &&
         !iid. equals(Components. interfaces. nsIRequestObserver) &&
         !iid. equals(Components. interfaces. nsIChannelEventSink) &&
         !iid. equals(Components. interfaces. nsIProgressEventSink) && // see below
         !iid. equals(Components. interfaces. nsIStreamListener) &&
         !iid. equals(Components. interfaces. nsIHttpEventSink))
      {
         throw Components. results. NS_ERROR_NO_INTERFACE;
      }
      return this;
   },

   // nsIInterfaceRequestor
   getInterface: function (iid)
   {
      LOG ("listener: getInterface: " + iid)
      try
      {
         return this. QueryInterface (iid);
      } catch (e)
      {
         throw Components. results. NS_NOINTERFACE;
      }
   },

   // nsIRequestObserver
   onStartRequest: function (aRequest, aContext)
   {
      LOG ("listener: onStartRequest")
   },

   onStopRequest: function (aRequest, aContext, aStatusCode)
   {
      LOG ("listener: onStopRequest")
      this. mChannel = null;
   },

   // nsIStreamObserver
   onDataAvailable: function (aRequest, aContext, aInputStream, aOffset, aCount)
   {
      LOG ("listener: onDataAvailable")
   },

   // nsIChannelEventSink
   onChannelRedirect: function (aOldChannel, aNewChannel, aFlags)
   {
      LOG ("listener: onChannelRedirect")
      this. mChannel = aNewChannel;
   },

   // nsIProgressEventSink: the only reason we support
   // nsIProgressEventSink is to shut up a whole slew of xpconnect
   // warnings in debug builds.  (see bug #253127)
   onProgress : function (aRequest, aContext, aProgress, aProgressMax)
   {
      LOG ("listener: onProgress")
   },

   onStatus: function (aRequest, aContext, aStatus, aStatusArg)
   {
      LOG ("listener: onStatus: " + aStatus)
   },

   // nsIHttpEventSink
   onRedirect: function (httpChannel, newChannel)
   {
      LOG ("listener: onRedirect: ")
   }
}
скелет listener стянут из bookmarks.js, только дополнен nsIHttpEventSink интерфейсом
спустя 1 день 3 часа [обр] Владимир Палант(434/4445)[досье]
Да, я боялся, что вы что-то в таком роде сделали. Вам не показалось странным, что notificationCallbacks у nsIChannel существуют в единственном экземпляре? Эта возможность предусмотрена для использования тем, кто этот канал создал. Вы его заменяете, тем самым создатель nsIChannel уведомления больше не получает. Вывод: не надо так делать.
спустя 17 часов [обр] Cube(2/2)[досье]
Да, я боялся, что вы что-то в таком роде сделали.
Я тоже подозревал, что это будет сказано : )
listener был добавлен в код в поисках хоть какого-то, унифицированного в рамках modify-request/examine-response способа определения сетевой ошибки. А то, что он не отрабатывает при сетевой ошибке, не есть ли свидетельство того, что channel уже не существует ? - надо проверить.
спустя 3 часа 3 минуты [обр] Cube(2/2)[досье]
поэкспериментировал, результаты такие: channel существует, isPending()==false, status=2152398878. А в каком интерфейсе искать статусные коды ? Те, что в nsIRequest слишком мелковаты.
спустя 15 минут [обр] Владимир Палант(434/4445)[досье]
Это 0x804B001E. При этом 0x804B0000 — это NS_ERROR_MODULE_NETWORK, база для всех сетевых ошибок. Сам же код ошибки — 1E, то есть 30. Смотрим http://lxr.mozilla.org/mozilla/source/netwerk/base/public/nsNetError.h, оказывается это NS_ERROR_UNKNOWN_HOST.
спустя 15 часов [обр] Cube(2/2)[досье]
Спасибо, то, что нужно. Не знаю, сколько бы я ещё искал самостоятельно.
Powered by POEM™ Engine Copyright © 2002-2005