2009-06-25 3 views
2

델파이에서 nsIProtocolHandler 구현을 구축 중입니다. (more here) 그리고 이미 작동 중입니다. 모듈이 빌드 한 데이터는 nsIInputStream을 통해 스트리밍됩니다. 모든 nsIRequest, nsIChannel 및 nsIHttpChannel 메서드와 속성이 작동합니다.nsIProtocolHandler : html 페이지의 이미지로드 문제가 있습니다.

테스트를 시작했는데 이상한 점이 있습니다. 파이어 폭스에서 작업

<img src="a.png">

모두 "중, Xxm : : : //test/a.html"와 "//test/a.png 중, Xxm"나는이 간단한 HTML로 페이지 "a.html"이 , HTML 또는 PNG 이미지 데이터 위에 제공하십시오. 문제는 HTML 페이지를 표시하면 이미지가로드되지 않습니다. 내가 디버깅 할 때, 내가 볼 : (파이어 폭스 a.html에 OnDataAvailable 통지를 처리 ​​할 때)

  • NewChannel는
  • NotificationCallbacks이 설정되고, a.png 위해 호출됩니다 (I에만 참조를 유지해야 맞죠?)에 RequestHeader는 "Accept는"

는 requ에 다른보고)에 의한 제로 참조 횟수에 대부분의 아마 ("image/png,image/*;q=0.8,*/*;q=0.5"

  • 하지만 그때는, 채널 객체가 해제로 설정되어
  • 내가 LoadFlags 또는 OriginalURI) 및 AsyncOpen 같은 얻을 수있는 다른 속성을 설정할 것이라고 예상되는 요청을 가져 오는 시작할 수 있습니다.

    아무도 이것을 인식하지 못합니까? 내가 뭔가 잘못하고 있는거야? 아마도 LoadFlags 또는 LoadGroup과 함께? LoadGroup에서 AddRequest 및 RemoveRequest를 호출 할 때 확실하지 않고 nsHttpChannelnsBaseChannel에서 엿보는 경우 RemoveRequest를 일찍 또는 늦게 (OnStartRequest 또는 OnStopRequest 이전 또는 이후) 호출하는 것이 더 낫지 않습니까?

    업데이트 : <img src="xxm://test/a.png" />에 "//test/a1.html 파일을" 더 문제를 분리하려고하기 위해, 나는 시도 :는 여전히 같은

    업데이트가 갓 새로운 파이어 폭스 3.5에 대한 검사 그리고 여전히 일어나고있는 일련의 사건들 위에서 만 얻을 수 있습니다. AsyncOpen이 호출되도록로드 그룹에이 secundary 요청을 추가해야한다면 어디서 참조해야하는지 잘 모릅니다.

    추가 정보 : 요청 헤더에 추가되는 "Accept"문자열 중 one instance 만 찾았습니다. 새 채널을 만든 직후에 nsIHttpChannelInternal을 쿼리하지만이 QueryInterface 호출을받지 못했습니다. (내가 게시 한 here)

  • 답변

    0

    나는 그것을 발견했다고 생각한다. this page을 자세히 살펴 본다. UUID가 버전에 비해 변경되었음을 강조하지 않는 이유는 분명하지 않지만 nsIHttpChannelInternal에서 QueryInterface를 호출 할 때 (또는 바로 전에) 실패하는 이유를 설명합니다.

    새로운 (어) UUID로 더 나은 결과를 얻고 있습니다. 질문에 대한 업데이트에서 언급했듯이 bugzilla.mozilla.org에이 글을 올렸습니다. 궁금한 점이 있다면 응답 해 드리겠습니다.

    0

    다시.

    나는 nsIChannel::asyncOpen()에서 같은 물건을 인용하기 위하여려고하고있다 :

    asyncOpen하면 반환 성공적으로 채널이 aListeneronStopRequest 전화 또는 onChannelRedirect라고 할 때까지 자신이 살아 을 유지하는 책임이있다.

    다시 nsViewSourceChannel.cpp에 갈 경우, loadGroup->AddRequest를 호출 한 곳과 loadGroup->RemoveRequest가 호출되는 두 곳이있다.

    nsViewSourceChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports *ctxt) 
    { 
        NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE); 
    
        mListener = aListener; 
    
        /* 
        * We want to add ourselves to the loadgroup before opening 
        * mChannel, since we want to make sure we're in the loadgroup 
        * when mChannel finishes and fires OnStopRequest() 
        */ 
    
        nsCOMPtr<nsILoadGroup> loadGroup; 
        mChannel->GetLoadGroup(getter_AddRefs(loadGroup)); 
        if (loadGroup) 
         loadGroup->AddRequest(NS_STATIC_CAST(nsIViewSourceChannel*, 
                  this), nsnull); 
    
        nsresult rv = mChannel->AsyncOpen(this, ctxt); 
    
        if (NS_FAILED(rv) && loadGroup) 
         loadGroup->RemoveRequest(NS_STATIC_CAST(nsIViewSourceChannel*, 
                   this), 
               nsnull, rv); 
    
        if (NS_SUCCEEDED(rv)) { 
         mOpened = PR_TRUE; 
        } 
    
        return rv; 
    } 
    

    nsViewSourceChannel::OnStopRequest(nsIRequest *aRequest, nsISupports* aContext, 
               nsresult aStatus) 
    { 
        NS_ENSURE_TRUE(mListener, NS_ERROR_FAILURE); 
        if (mChannel) 
        { 
         nsCOMPtr<nsILoadGroup> loadGroup; 
         mChannel->GetLoadGroup(getter_AddRefs(loadGroup)); 
         if (loadGroup) 
         { 
          loadGroup->RemoveRequest(NS_STATIC_CAST(nsIViewSourceChannel*, 
                    this), 
                nsnull, aStatus); 
         } 
        } 
        return mListener->OnStopRequest(NS_STATIC_CAST(nsIViewSourceChannel*, 
                    this), 
                aContext, aStatus); 
    } 
    

    편집 : 나는 모질라의 작동 방식에 대한 단서가 없다, 그래서 몇 가지 코드를 읽고 생각해야으로

    . 채널의 관점에서 볼 때 원본 파일이로드되면 작업이 완료됩니다. 이미지처럼 파일에 링크 된 보조 항목을로드하려면 해당 항목을 수신기에 구현해야합니다. TestPageLoad.cpp을 참조하십시오. 그것은 원유 파서를 구현하고는 OnDataAvailable에 하위 항목을 검색합니다

    NS_IMETHODIMP 
    MyListener::OnDataAvailable(nsIRequest *req, nsISupports *ctxt, 
              nsIInputStream *stream, 
              PRUint32 offset, PRUint32 count) 
    { 
        //printf(">>> OnDataAvailable [count=%u]\n", count); 
        nsresult rv = NS_ERROR_FAILURE; 
        PRUint32 bytesRead=0; 
        char buf[1024]; 
    
        if(ctxt == nsnull) { 
         bytesRead=0; 
         rv = stream->ReadSegments(streamParse, &offset, count, &bytesRead); 
        } else { 
         while (count) { 
         PRUint32 amount = PR_MIN(count, sizeof(buf)); 
         rv = stream->Read(buf, amount, &bytesRead); 
         count -= bytesRead; 
         } 
        } 
    
        if (NS_FAILED(rv)) { 
         printf(">>> stream->Read failed with rv=%x\n", rv); 
         return rv; 
        } 
    
        return NS_OK; 
    } 
    

    중요한 것은 그것이 새로운 새로운 채널을 생성하는 imgscript 요소의 src 속성에 보이는, streamParse()을 호출하고 auxLoad()를 호출하는 것입니다 청취자이며 전화는 AsyncOpen()입니다. 또한 러시아 인형 상황처럼 광고 인해서 이상의 하위 항목을로드 할 수 있습니다

    uriList->AppendElement(uri); 
    rv = NS_NewChannel(getter_AddRefs(chan), uri, nsnull, nsnull, callbacks); 
    RETURN_IF_FAILED(rv, "NS_NewChannel"); 
    
    gKeepRunning++; 
    rv = chan->AsyncOpen(listener, myBool); 
    RETURN_IF_FAILED(rv, "AsyncOpen"); 
    

    거기에 MyListener 개체의 다른 인스턴스를 전달 이후로.

    +0

    이것은 매우 혼란 스럽습니다. 필자는 필자의 AddRequest/RemoveRequest 호출을 매우 비슷한 위치에두고 있지만 SetLoadGroup이나 AsyncOpen도 PNG의 채널에서 호출되지 않습니다. ViewSourceChannel은 nsIStreamListener.OnStartRequest 호출에서 설정된 "mChannel"을 사용하지만 내 채널에 nsIStreamListener를 추가하면 해당 메서드가 호출되지 않습니다. –

    +0

    질문에 second update도 참조하십시오. –

    +0

    @ Stijn Sanders, 답변을 업데이트했습니다. –