Ejemplo n.º 1
0
uint32_t
GetContentSize(nsIRequest* aRequest)
{
  // Use content-length as a size hint for http channels.
  nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aRequest));
  if (httpChannel) {
    nsAutoCString contentLength;
    nsresult rv = httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("content-length"),
                                                 contentLength);
    if (NS_SUCCEEDED(rv)) {
      return std::max(contentLength.ToInteger(&rv), 0);
    }
  }

  // Use the file size as a size hint for file channels.
  nsCOMPtr<nsIFileChannel> fileChannel(do_QueryInterface(aRequest));
  if (fileChannel) {
    nsCOMPtr<nsIFile> file;
    nsresult rv = fileChannel->GetFile(getter_AddRefs(file));
    if (NS_SUCCEEDED(rv)) {
      int64_t filesize;
      rv = file->GetFileSize(&filesize);
      if (NS_SUCCEEDED(rv)) {
        return std::max(SaturateToInt32(filesize), 0);
      }
    }
  }

  // Fallback - neither http nor file. We'll use dynamic allocation.
  return 0;
}
NS_IMETHODIMP
nsPluginByteRangeStreamListener::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
{
  nsresult rv;
  
  nsCOMPtr<nsIStreamListener> finalStreamListener = do_QueryReferent(mWeakPtrPluginStreamListenerPeer);
  if (!finalStreamListener)
    return NS_ERROR_FAILURE;
  
  nsPluginStreamListenerPeer *pslp =
    static_cast<nsPluginStreamListenerPeer*>(finalStreamListener.get());

  NS_ASSERTION(pslp->mRequests.IndexOfObject(GetBaseRequest(request)) != -1,
               "Untracked byte-range request?");
  
  nsCOMPtr<nsIStreamConverterService> serv = do_GetService(NS_STREAMCONVERTERSERVICE_CONTRACTID, &rv);
  if (NS_SUCCEEDED(rv)) {
    rv = serv->AsyncConvertData(MULTIPART_BYTERANGES,
                                "*/*",
                                finalStreamListener,
                                nsnull,
                                getter_AddRefs(mStreamConverter));
    if (NS_SUCCEEDED(rv)) {
      rv = mStreamConverter->OnStartRequest(request, ctxt);
      if (NS_SUCCEEDED(rv))
        return rv;
    }
  }
  mStreamConverter = 0;
  
  nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(request));
  if (!httpChannel) {
    return NS_ERROR_FAILURE;
  }
  
  PRUint32 responseCode = 0;
  rv = httpChannel->GetResponseStatus(&responseCode);
  if (NS_FAILED(rv)) {
    return NS_ERROR_FAILURE;
  }
  
  if (responseCode != 200) {
    PRBool bWantsAllNetworkStreams = PR_FALSE;
    pslp->GetPluginInstance()->
    GetValueFromPlugin(NPPVpluginWantsAllNetworkStreams,
                       (void*)&bWantsAllNetworkStreams);
    if (!bWantsAllNetworkStreams){
      return NS_ERROR_FAILURE;
    }
  }
  
  // if server cannot continue with byte range (206 status) and sending us whole object (200 status)
  // reset this seekable stream & try serve it to plugin instance as a file
  mStreamConverter = finalStreamListener;
  mRemoveMagicNumber = PR_TRUE;
  
  rv = pslp->ServeStreamAsFile(request, ctxt);
  return rv;
}
Ejemplo n.º 3
0
static nsresult
RequestSucceeded(nsIXMLHttpRequest* aRequest, PRBool* aReturn)
{
  NS_ENSURE_ARG_POINTER(aRequest);

  nsresult rv;
  nsCOMPtr<nsIChannel> channel;
  aRequest->GetChannel(getter_AddRefs(channel));
  nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel, &rv));
  NS_ENSURE_TRUE(httpChannel, rv);

  return httpChannel->GetRequestSucceeded(aReturn);
}
nsresult
txCompileObserver::startLoad(nsIURI* aUri, txStylesheetCompiler* aCompiler,
                             nsIPrincipal* aReferrerPrincipal)
{
    nsCOMPtr<nsIChannel> channel;
    nsresult rv = NS_NewChannel(getter_AddRefs(channel), aUri);
    NS_ENSURE_SUCCESS(rv, rv);

    channel->SetLoadGroup(mLoadGroup);

    channel->SetContentType(NS_LITERAL_CSTRING("text/xml"));

    nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
    if (httpChannel) {
        httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("Accept"),
                                      NS_LITERAL_CSTRING("text/xml,application/xml,application/xhtml+xml,*/*;q=0.1"),
                                      PR_FALSE);

        nsCOMPtr<nsIURI> referrerURI;
        aReferrerPrincipal->GetURI(getter_AddRefs(referrerURI));
        if (referrerURI) {
            httpChannel->SetReferrer(referrerURI);
        }
    }

    nsCOMPtr<nsIParser> parser = do_CreateInstance(kCParserCID, &rv);
    NS_ENSURE_SUCCESS(rv, rv);

    nsRefPtr<txStylesheetSink> sink = new txStylesheetSink(aCompiler, parser);
    NS_ENSURE_TRUE(sink, NS_ERROR_OUT_OF_MEMORY);

    channel->SetNotificationCallbacks(sink);

    parser->SetCommand(kLoadAsData);
    parser->SetContentSink(sink);
    parser->Parse(aUri);

    // Always install in case of redirects
    nsCOMPtr<nsIStreamListener> listener =
        new nsCrossSiteListenerProxy(sink, aReferrerPrincipal, channel,
                                     PR_FALSE, &rv);
    NS_ENSURE_TRUE(listener, NS_ERROR_OUT_OF_MEMORY);
    NS_ENSURE_SUCCESS(rv, rv);

    return channel->AsyncOpen(listener, parser);
}
Ejemplo n.º 5
0
nsresult
nsFeedSniffer::ConvertEncodedData(nsIRequest* request,
                                  const uint8_t* data,
                                  uint32_t length)
{
  nsresult rv = NS_OK;

 mDecodedData = "";
 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(request));
  if (!httpChannel)
    return NS_ERROR_NO_INTERFACE;

  nsCAutoString contentEncoding;
  httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("Content-Encoding"), 
                                 contentEncoding);
  if (!contentEncoding.IsEmpty()) {
    nsCOMPtr<nsIStreamConverterService> converterService(do_GetService(NS_STREAMCONVERTERSERVICE_CONTRACTID));
    if (converterService) {
      ToLowerCase(contentEncoding);

      nsCOMPtr<nsIStreamListener> converter;
      rv = converterService->AsyncConvertData(contentEncoding.get(), 
                                              "uncompressed", this, nullptr, 
                                              getter_AddRefs(converter));
      NS_ENSURE_SUCCESS(rv, rv);

      converter->OnStartRequest(request, nullptr);

      nsCOMPtr<nsIStringInputStream> rawStream =
        do_CreateInstance(NS_STRINGINPUTSTREAM_CONTRACTID);
      if (!rawStream)
        return NS_ERROR_FAILURE;

      rv = rawStream->SetData((const char*)data, length);
      NS_ENSURE_SUCCESS(rv, rv);

      rv = converter->OnDataAvailable(request, nullptr, rawStream, 0, length);
      NS_ENSURE_SUCCESS(rv, rv);

      converter->OnStopRequest(request, nullptr, NS_OK);
    }
  }
  return rv;
}
NS_IMETHODIMP
nsPluginStreamListenerPeer::OnStartRequest(nsIRequest *request,
                                           nsISupports* aContext)
{
  nsresult rv = NS_OK;
  PROFILER_LABEL("nsPluginStreamListenerPeer", "OnStartRequest",
    js::ProfileEntry::Category::OTHER);

  if (mRequests.IndexOfObject(GetBaseRequest(request)) == -1) {
    NS_ASSERTION(mRequests.Count() == 0,
                 "Only our initial stream should be unknown!");
    TrackRequest(request);
  }

  if (mHaveFiredOnStartRequest) {
    return NS_OK;
  }

  mHaveFiredOnStartRequest = true;

  nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
  NS_ENSURE_TRUE(channel, NS_ERROR_FAILURE);

  // deal with 404 (Not Found) HTTP response,
  // just return, this causes the request to be ignored.
  nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
  if (httpChannel) {
    uint32_t responseCode = 0;
    rv = httpChannel->GetResponseStatus(&responseCode);
    if (NS_FAILED(rv)) {
      // NPP_Notify() will be called from OnStopRequest
      // in nsNPAPIPluginStreamListener::CleanUpStream
      // return error will cancel this request
      // ...and we also need to tell the plugin that
      mRequestFailed = true;
      return NS_ERROR_FAILURE;
    }

    if (responseCode > 206) { // not normal
      uint32_t wantsAllNetworkStreams = 0;

      // We don't always have an instance here already, but if we do, check
      // to see if it wants all streams.
      if (mPluginInstance) {
        rv = mPluginInstance->GetValueFromPlugin(NPPVpluginWantsAllNetworkStreams,
                                                 &wantsAllNetworkStreams);
        // If the call returned an error code make sure we still use our default value.
        if (NS_FAILED(rv)) {
          wantsAllNetworkStreams = 0;
        }
      }

      if (!wantsAllNetworkStreams) {
        mRequestFailed = true;
        return NS_ERROR_FAILURE;
      }
    }
  }

  nsAutoCString contentType;
  rv = channel->GetContentType(contentType);
  if (NS_FAILED(rv))
    return rv;

  // Check ShouldProcess with content policy
  nsRefPtr<nsPluginInstanceOwner> owner;
  if (mPluginInstance) {
    owner = mPluginInstance->GetOwner();
  }
  nsCOMPtr<nsIDOMElement> element;
  nsCOMPtr<nsIDocument> doc;
  if (owner) {
    owner->GetDOMElement(getter_AddRefs(element));
    owner->GetDocument(getter_AddRefs(doc));
  }
  nsCOMPtr<nsIPrincipal> principal = doc ? doc->NodePrincipal() : nullptr;

  int16_t shouldLoad = nsIContentPolicy::ACCEPT;
  rv = NS_CheckContentProcessPolicy(nsIContentPolicy::TYPE_OBJECT_SUBREQUEST,
                                    mURL,
                                    principal,
                                    element,
                                    contentType,
                                    nullptr,
                                    &shouldLoad);
  if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) {
    mRequestFailed = true;
    return NS_ERROR_CONTENT_BLOCKED;
  }

  // Get the notification callbacks from the channel and save it as
  // week ref we'll use it in nsPluginStreamInfo::RequestRead() when
  // we'll create channel for byte range request.
  nsCOMPtr<nsIInterfaceRequestor> callbacks;
  channel->GetNotificationCallbacks(getter_AddRefs(callbacks));
  if (callbacks)
    mWeakPtrChannelCallbacks = do_GetWeakReference(callbacks);

  nsCOMPtr<nsILoadGroup> loadGroup;
  channel->GetLoadGroup(getter_AddRefs(loadGroup));
  if (loadGroup)
    mWeakPtrChannelLoadGroup = do_GetWeakReference(loadGroup);

  int64_t length;
  rv = channel->GetContentLength(&length);

  // it's possible for the server to not send a Content-Length.
  // we should still work in this case.
  if (NS_FAILED(rv) || length < 0 || length > UINT32_MAX) {
    // check out if this is file channel
    nsCOMPtr<nsIFileChannel> fileChannel = do_QueryInterface(channel);
    if (fileChannel) {
      // file does not exist
      mRequestFailed = true;
      return NS_ERROR_FAILURE;
    }
    mLength = 0;
  }
  else {
    mLength = uint32_t(length);
  }

  nsCOMPtr<nsIURI> aURL;
  rv = channel->GetURI(getter_AddRefs(aURL));
  if (NS_FAILED(rv))
    return rv;

  aURL->GetSpec(mURLSpec);

  if (!contentType.IsEmpty())
    mContentType = contentType;

#ifdef PLUGIN_LOGGING
  MOZ_LOG(nsPluginLogging::gPluginLog, PLUGIN_LOG_NOISY,
         ("nsPluginStreamListenerPeer::OnStartRequest this=%p request=%p mime=%s, url=%s\n",
          this, request, contentType.get(), mURLSpec.get()));

  PR_LogFlush();
#endif

  // Set up the stream listener...
  rv = SetUpStreamListener(request, aURL);
  if (NS_FAILED(rv)) {
    return rv;
  }

  return rv;
}
nsresult
nsPluginStreamListenerPeer::RequestRead(NPByteRange* rangeList)
{
  nsAutoCString rangeString;
  int32_t numRequests;
  
  MakeByteRangeString(rangeList, rangeString, &numRequests);
  
  if (numRequests == 0)
    return NS_ERROR_FAILURE;
  
  nsresult rv = NS_OK;
  
  nsCOMPtr<nsIInterfaceRequestor> callbacks = do_QueryReferent(mWeakPtrChannelCallbacks);
  nsCOMPtr<nsILoadGroup> loadGroup = do_QueryReferent(mWeakPtrChannelLoadGroup);
  nsCOMPtr<nsIChannel> channel;
  rv = NS_NewChannel(getter_AddRefs(channel), mURL, nullptr, loadGroup, callbacks);
  if (NS_FAILED(rv))
    return rv;
  
  nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
  if (!httpChannel)
    return NS_ERROR_FAILURE;
  
  httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("Range"), rangeString, false);
  
  mAbort = true; // instruct old stream listener to cancel
  // the request on the next ODA.
  
  nsCOMPtr<nsIStreamListener> converter;
  
  if (numRequests == 1) {
    converter = this;
    // set current stream offset equal to the first offset in the range list
    // it will work for single byte range request
    // for multy range we'll reset it in ODA
    SetStreamOffset(rangeList->offset);
  } else {
    nsWeakPtr weakpeer =
    do_GetWeakReference(static_cast<nsISupportsWeakReference*>(this));
    nsPluginByteRangeStreamListener *brrListener =
    new nsPluginByteRangeStreamListener(weakpeer);
    if (brrListener)
      converter = brrListener;
    else
      return NS_ERROR_OUT_OF_MEMORY;
  }
  
  mPendingRequests += numRequests;
  
  nsCOMPtr<nsISupportsPRUint32> container = do_CreateInstance(NS_SUPPORTS_PRUINT32_CONTRACTID, &rv);
  if (NS_FAILED(rv))
    return rv;
  rv = container->SetData(MAGIC_REQUEST_CONTEXT);
  if (NS_FAILED(rv))
    return rv;
  
  rv = channel->AsyncOpen(converter, container);
  if (NS_SUCCEEDED(rv))
    TrackRequest(channel);
  return rv;
}
Ejemplo n.º 8
0
nsresult 
nsUserFontSet::StartLoad(gfxFontEntry *aFontToLoad, 
                          const gfxFontFaceSrc *aFontFaceSrc)
{
  nsresult rv;
  
  // check same-site origin
  nsIPresShell *ps = mPresContext->PresShell();
  if (!ps)
    return NS_ERROR_FAILURE;
    
  NS_ASSERTION(aFontFaceSrc && !aFontFaceSrc->mIsLocal, 
               "bad font face url passed to fontloader");
  NS_ASSERTION(aFontFaceSrc->mURI, "null font uri");
  if (!aFontFaceSrc->mURI)
    return NS_ERROR_FAILURE;

  // use document principal, original principal if flag set
  // this enables user stylesheets to load font files via
  // @font-face rules
  nsCOMPtr<nsIPrincipal> principal = ps->GetDocument()->NodePrincipal();

  NS_ASSERTION(aFontFaceSrc->mOriginPrincipal, 
               "null origin principal in @font-face rule");
  if (aFontFaceSrc->mUseOriginPrincipal) {
    principal = do_QueryInterface(aFontFaceSrc->mOriginPrincipal);
  }
  
  rv = nsFontFaceLoader::CheckLoadAllowed(principal, aFontFaceSrc->mURI, 
                                          ps->GetDocument());
  if (NS_FAILED(rv)) {
#ifdef PR_LOGGING
    if (LOG_ENABLED()) {
      nsCAutoString fontURI, referrerURI;
      aFontFaceSrc->mURI->GetSpec(fontURI);
      if (aFontFaceSrc->mReferrer)
        aFontFaceSrc->mReferrer->GetSpec(referrerURI);
      LOG(("fontdownloader download blocked - font uri: (%s) "
           "referrer uri: (%s) err: %8.8x\n", 
          fontURI.get(), referrerURI.get(), rv));
    }
#endif    
    return rv;
  }

  nsCOMPtr<nsIStreamLoader> streamLoader;
  nsCOMPtr<nsILoadGroup> loadGroup(ps->GetDocument()->GetDocumentLoadGroup());

  nsCOMPtr<nsIChannel> channel;
  // get Content Security Policy from principal to pass into channel
  nsCOMPtr<nsIChannelPolicy> channelPolicy;
  nsCOMPtr<nsIContentSecurityPolicy> csp;
  rv = principal->GetCsp(getter_AddRefs(csp));
  NS_ENSURE_SUCCESS(rv, rv);
  if (csp) {
    channelPolicy = do_CreateInstance("@mozilla.org/nschannelpolicy;1");
    channelPolicy->SetContentSecurityPolicy(csp);
    channelPolicy->SetLoadType(nsIContentPolicy::TYPE_FONT);
  }
  rv = NS_NewChannel(getter_AddRefs(channel),
                     aFontFaceSrc->mURI,
                     nsnull,
                     loadGroup,
                     nsnull,
                     nsIRequest::LOAD_NORMAL,
                     channelPolicy);

  NS_ENSURE_SUCCESS(rv, rv);

  nsRefPtr<nsFontFaceLoader> fontLoader =
    new nsFontFaceLoader(aFontToLoad, aFontFaceSrc->mURI, this, channel);

  if (!fontLoader)
    return NS_ERROR_OUT_OF_MEMORY;

#ifdef PR_LOGGING
  if (LOG_ENABLED()) {
    nsCAutoString fontURI, referrerURI;
    aFontFaceSrc->mURI->GetSpec(fontURI);
    if (aFontFaceSrc->mReferrer)
      aFontFaceSrc->mReferrer->GetSpec(referrerURI);
    LOG(("fontdownloader (%p) download start - font uri: (%s) "
         "referrer uri: (%s)\n", 
         fontLoader.get(), fontURI.get(), referrerURI.get()));
  }
#endif  

  nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
  if (httpChannel)
    httpChannel->SetReferrer(aFontFaceSrc->mReferrer);
  rv = NS_NewStreamLoader(getter_AddRefs(streamLoader), fontLoader);
  NS_ENSURE_SUCCESS(rv, rv);
  
  PRBool inherits = PR_FALSE;
  rv = NS_URIChainHasFlags(aFontFaceSrc->mURI,
                           nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
                           &inherits);
  if (NS_SUCCEEDED(rv) && inherits) {
    // allow data, javascript, etc URI's
    rv = channel->AsyncOpen(streamLoader, nsnull);
  } else {
    nsCOMPtr<nsIStreamListener> listener =
      new nsCrossSiteListenerProxy(streamLoader, principal, channel, 
                                   PR_FALSE, &rv);
    if (NS_FAILED(rv)) {
      fontLoader->DropChannel();  // explicitly need to break ref cycle
    }
    NS_ENSURE_TRUE(listener, NS_ERROR_OUT_OF_MEMORY);
    NS_ENSURE_SUCCESS(rv, rv);

    rv = channel->AsyncOpen(listener, nsnull);
  }

  if (NS_SUCCEEDED(rv)) {
    mLoaders.PutEntry(fontLoader);
  }

  return rv;
}
Ejemplo n.º 9
0
nsresult
nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
{
    // We need a document to evaluate scripts.
    NS_ENSURE_TRUE(mDocument, NS_ERROR_FAILURE);

    // Check to see if scripts has been turned off.
    if (!mEnabled || !mDocument->IsScriptEnabled()) {
        return NS_ERROR_NOT_AVAILABLE;
    }

    NS_ASSERTION(!aElement->IsMalformed(), "Executing malformed script");

    // Check that the script is not an eventhandler
    if (IsScriptEventHandler(aElement)) {
        return NS_CONTENT_SCRIPT_IS_EVENTHANDLER;
    }

    // Script evaluation can also be disabled in the current script
    // context even though it's enabled in the document.
    // XXX - still hard-coded for JS here, even though another language
    // may be specified.  Should this check be made *after* we examine
    // the attributes to locate the script-type?
    // For now though, if JS is disabled we assume every language is
    // disabled.
    // XXX is this different from the mDocument->IsScriptEnabled() call?
    nsIScriptGlobalObject *globalObject = mDocument->GetScriptGlobalObject();
    if (!globalObject) {
        return NS_ERROR_NOT_AVAILABLE;
    }

    nsIScriptContext *context = globalObject->GetScriptContext(
                                    nsIProgrammingLanguage::JAVASCRIPT);

    // If scripts aren't enabled in the current context, there's no
    // point in going on.
    if (!context || !context->GetScriptsEnabled()) {
        return NS_ERROR_NOT_AVAILABLE;
    }

    // Default script language is whatever the root content specifies
    // (which may come from a header or http-meta tag), or if there
    // is no root content, from the script global object.
    nsCOMPtr<nsIContent> rootContent = mDocument->GetRootContent();
    PRUint32 typeID = rootContent ? rootContent->GetScriptTypeID() :
                      context->GetScriptTypeID();
    PRUint32 version = 0;
    nsAutoString language, type, src;
    nsresult rv = NS_OK;

    // Check the type attribute to determine language and version.
    // If type exists, it trumps the deprecated 'language='
    aElement->GetScriptType(type);
    if (!type.IsEmpty()) {
        nsCOMPtr<nsIMIMEHeaderParam> mimeHdrParser =
            do_GetService("@mozilla.org/network/mime-hdrparam;1");
        NS_ENSURE_TRUE(mimeHdrParser, NS_ERROR_FAILURE);

        NS_ConvertUTF16toUTF8 typeAndParams(type);

        nsAutoString mimeType;
        rv = mimeHdrParser->GetParameter(typeAndParams, nsnull,
                                         EmptyCString(), PR_FALSE, nsnull,
                                         mimeType);
        NS_ENSURE_SUCCESS(rv, rv);

        // Javascript keeps the fast path, optimized for most-likely type
        // Table ordered from most to least likely JS MIME types.
        // See bug 62485, feel free to add <script type="..."> survey data to it,
        // or to a new bug once 62485 is closed.
        static const char *jsTypes[] = {
            "text/javascript",
            "text/ecmascript",
            "application/javascript",
            "application/ecmascript",
            "application/x-javascript",
            nsnull
        };

        PRBool isJavaScript = PR_FALSE;
        for (PRInt32 i = 0; jsTypes[i]; i++) {
            if (mimeType.LowerCaseEqualsASCII(jsTypes[i])) {
                isJavaScript = PR_TRUE;
                break;
            }
        }
        if (isJavaScript)
            typeID = nsIProgrammingLanguage::JAVASCRIPT;
        else {
            // Use the object factory to locate a matching language.
            nsCOMPtr<nsIScriptRuntime> runtime;
            rv = NS_GetScriptRuntime(mimeType, getter_AddRefs(runtime));
            if (NS_FAILED(rv) || runtime == nsnull) {
                // Failed to get the explicitly specified language
                NS_WARNING("Failed to find a scripting language");
                typeID = nsIProgrammingLanguage::UNKNOWN;
            } else
                typeID = runtime->GetScriptTypeID();
        }
        if (typeID != nsIProgrammingLanguage::UNKNOWN) {
            // Get the version string, and ensure the language supports it.
            nsAutoString versionName;
            rv = mimeHdrParser->GetParameter(typeAndParams, "version",
                                             EmptyCString(), PR_FALSE, nsnull,
                                             versionName);
            if (NS_FAILED(rv)) {
                // no version attribute - version remains 0.
                if (rv != NS_ERROR_INVALID_ARG)
                    return rv;
            } else {
                nsCOMPtr<nsIScriptRuntime> runtime;
                rv = NS_GetScriptRuntimeByID(typeID, getter_AddRefs(runtime));
                if (NS_FAILED(rv)) {
                    NS_ERROR("Failed to locate the language with this ID");
                    return rv;
                }
                rv = runtime->ParseVersion(versionName, &version);
                if (NS_FAILED(rv)) {
                    NS_WARNING("This script language version is not supported - ignored");
                    typeID = nsIProgrammingLanguage::UNKNOWN;
                }
            }
        }

        // Some js specifics yet to be abstracted.
        if (typeID == nsIProgrammingLanguage::JAVASCRIPT) {
            nsAutoString value;

            rv = mimeHdrParser->GetParameter(typeAndParams, "e4x",
                                             EmptyCString(), PR_FALSE, nsnull,
                                             value);
            if (NS_FAILED(rv)) {
                if (rv != NS_ERROR_INVALID_ARG)
                    return rv;
            } else {
                if (value.Length() == 1 && value[0] == '1')
                    // This means that we need to set JSOPTION_XML in the JS options.
                    // We re-use our knowledge of the implementation to reuse
                    // JSVERSION_HAS_XML as a safe version flag.
                    // If version has JSVERSION_UNKNOWN (-1), then this is still OK.
                    version |= JSVERSION_HAS_XML;
            }
        }
    } else {
        // no 'type=' element
        // "language" is a deprecated attribute of HTML, so we check it only for
        // HTML script elements.
        nsCOMPtr<nsIDOMHTMLScriptElement> htmlScriptElement =
            do_QueryInterface(aElement);
        if (htmlScriptElement) {
            htmlScriptElement->GetAttribute(NS_LITERAL_STRING("language"), language);
            if (!language.IsEmpty()) {
                if (nsParserUtils::IsJavaScriptLanguage(language, &version))
                    typeID = nsIProgrammingLanguage::JAVASCRIPT;
                else
                    typeID = nsIProgrammingLanguage::UNKNOWN;
                // IE, Opera, etc. do not respect language version, so neither should
                // we at this late date in the browser wars saga.  Note that this change
                // affects HTML but not XUL or SVG (but note also that XUL has its own
                // code to check nsParserUtils::IsJavaScriptLanguage -- that's probably
                // a separate bug, one we may not be able to fix short of XUL2).  See
                // bug 255895 (https://bugzilla.mozilla.org/show_bug.cgi?id=255895).
                NS_ASSERTION(JSVERSION_DEFAULT == 0,
                             "We rely on all languages having 0 as a version default");
                version = 0;
            }
        }
    }

    // If we don't know the language, we don't know how to evaluate
    if (typeID == nsIProgrammingLanguage::UNKNOWN) {
        return NS_ERROR_NOT_AVAILABLE;
    }
    // If not from a chrome document (which is always trusted), we need some way
    // of checking the language is "safe".  Currently the only other language
    // impl is Python, and that is *not* safe in untrusted code - so fixing
    // this isn't a priority.!
    // See also similar code in nsXULContentSink.cpp
    if (typeID != nsIProgrammingLanguage::JAVASCRIPT &&
            !nsContentUtils::IsChromeDoc(mDocument)) {
        NS_WARNING("Untrusted language called from non-chrome - ignored");
        return NS_ERROR_NOT_AVAILABLE;
    }

    nsCOMPtr<nsIContent> eltContent(do_QueryInterface(aElement));
    eltContent->SetScriptTypeID(typeID);

    // Create a request object for this script
    nsRefPtr<nsScriptLoadRequest> request = new nsScriptLoadRequest(aElement, version);
    NS_ENSURE_TRUE(request, NS_ERROR_OUT_OF_MEMORY);

    // First check to see if this is an external script
    nsCOMPtr<nsIURI> scriptURI = aElement->GetScriptURI();
    if (scriptURI) {
        // Check that the containing page is allowed to load this URI.
        rv = nsContentUtils::GetSecurityManager()->
             CheckLoadURIWithPrincipal(mDocument->NodePrincipal(), scriptURI,
                                       nsIScriptSecurityManager::ALLOW_CHROME);

        NS_ENSURE_SUCCESS(rv, rv);

        // After the security manager, the content-policy stuff gets a veto
        PRInt16 shouldLoad = nsIContentPolicy::ACCEPT;
        rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_SCRIPT,
                                       scriptURI,
                                       mDocument->NodePrincipal(),
                                       aElement,
                                       NS_LossyConvertUTF16toASCII(type),
                                       nsnull,    //extra
                                       &shouldLoad,
                                       nsContentUtils::GetContentPolicy(),
                                       nsContentUtils::GetSecurityManager());
        if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) {
            if (NS_FAILED(rv) || shouldLoad != nsIContentPolicy::REJECT_TYPE) {
                return NS_ERROR_CONTENT_BLOCKED;
            }
            return NS_ERROR_CONTENT_BLOCKED_SHOW_ALT;
        }

        request->mURI = scriptURI;
        request->mIsInline = PR_FALSE;
        request->mLoading = PR_TRUE;

        nsCOMPtr<nsILoadGroup> loadGroup = mDocument->GetDocumentLoadGroup();
        nsCOMPtr<nsIStreamLoader> loader;

        nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(globalObject));
        nsIDocShell *docshell = window->GetDocShell();

        nsCOMPtr<nsIInterfaceRequestor> prompter(do_QueryInterface(docshell));

        nsCOMPtr<nsIChannel> channel;
        rv = NS_NewChannel(getter_AddRefs(channel),
                           scriptURI, nsnull, loadGroup,
                           prompter, nsIRequest::LOAD_NORMAL);
        NS_ENSURE_SUCCESS(rv, rv);

        nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
        if (httpChannel) {
            // HTTP content negotation has little value in this context.
            httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("Accept"),
                                          NS_LITERAL_CSTRING("*/*"),
                                          PR_FALSE);
            httpChannel->SetReferrer(mDocument->GetDocumentURI());
        }

        rv = NS_NewStreamLoader(getter_AddRefs(loader), this);
        NS_ENSURE_SUCCESS(rv, rv);

        rv = channel->AsyncOpen(loader, request);
        NS_ENSURE_SUCCESS(rv, rv);
    } else {
        request->mLoading = PR_FALSE;
        request->mIsInline = PR_TRUE;
        request->mURI = mDocument->GetDocumentURI();

        request->mLineNo = aElement->GetScriptLineNumber();

        // If we've got existing pending requests, add ourselves
        // to this list.
        if (mPendingRequests.Count() == 0 && ReadyToExecuteScripts() &&
                nsContentUtils::IsSafeToRunScript()) {
            return ProcessRequest(request);
        }
    }

    // Add the request to our pending requests list
    NS_ENSURE_TRUE(mPendingRequests.AppendObject(request),
                   NS_ERROR_OUT_OF_MEMORY);

    // If there weren't any pending requests before, and this one is
    // ready to execute, do that as soon as it's safe.
    if (mPendingRequests.Count() == 1 && !request->mLoading &&
            ReadyToExecuteScripts()) {
        nsContentUtils::AddScriptRunner(new nsRunnableMethod<nsScriptLoader>(this,
                                        &nsScriptLoader::ProcessPendingRequests));
    }

    // Added as pending request, now we can send blocking back
    return NS_ERROR_HTMLPARSER_BLOCK;
}
Ejemplo n.º 10
0
/* void onStartRequest (in nsIRequest request, in nsISupports ctxt); */
NS_IMETHODIMP imgRequest::OnStartRequest(nsIRequest *aRequest, nsISupports *ctxt)
{
  nsresult rv;

  LOG_SCOPE(gImgLog, "imgRequest::OnStartRequest");

  NS_ASSERTION(!mDecoder, "imgRequest::OnStartRequest -- we already have a decoder");

  nsCOMPtr<nsIMultiPartChannel> mpchan(do_QueryInterface(aRequest));
  if (mpchan)
      mIsMultiPartChannel = PR_TRUE;

  /*
   * If mRequest is null here, then we need to set it so that we'll be able to
   * cancel it if our Cancel() method is called.  Note that this can only
   * happen for multipart channels.  We could simply not null out mRequest for
   * non-last parts, if GetIsLastPart() were reliable, but it's not.  See
   * https://bugzilla.mozilla.org/show_bug.cgi?id=339610
   */
  if (!mRequest) {
    NS_ASSERTION(mpchan,
                 "We should have an mRequest here unless we're multipart");
    nsCOMPtr<nsIChannel> chan;
    mpchan->GetBaseChannel(getter_AddRefs(chan));
    mRequest = chan;
  }

  /* set our state variables to their initial values, but advance mState
     to onStartRequest. */
  if (mIsMultiPartChannel) {
    // Don't blow away our status altogether
    mImageStatus &= ~imgIRequest::STATUS_LOAD_PARTIAL;
    mImageStatus &= ~imgIRequest::STATUS_LOAD_COMPLETE;
    mImageStatus &= ~imgIRequest::STATUS_FRAME_COMPLETE;
  } else {
    mImageStatus = imgIRequest::STATUS_NONE;
  }
  mState = onStartRequest;

  nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
  if (channel)
    channel->GetSecurityInfo(getter_AddRefs(mSecurityInfo));

  /* set our loading flag to true */
  mLoading = PR_TRUE;

  /* notify our kids */
  nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mObservers);
  while (iter.HasMore()) {
    iter.GetNext()->OnStartRequest(aRequest, ctxt);
  }

  /* Get our principal */
  nsCOMPtr<nsIChannel> chan(do_QueryInterface(aRequest));
  if (chan) {
    nsCOMPtr<nsIScriptSecurityManager> secMan =
      do_GetService("@mozilla.org/scriptsecuritymanager;1");
    if (secMan) {
      nsresult rv = secMan->GetChannelPrincipal(chan,
                                                getter_AddRefs(mPrincipal));
      if (NS_FAILED(rv)) {
        return rv;
      }
    }
  }

  /* get the expires info */
  if (mCacheEntry) {
    nsCOMPtr<nsICachingChannel> cacheChannel(do_QueryInterface(aRequest));
    if (cacheChannel) {
      nsCOMPtr<nsISupports> cacheToken;
      cacheChannel->GetCacheToken(getter_AddRefs(cacheToken));
      if (cacheToken) {
        nsCOMPtr<nsICacheEntryInfo> entryDesc(do_QueryInterface(cacheToken));
        if (entryDesc) {
          PRUint32 expiration;
          /* get the expiration time from the caching channel's token */
          entryDesc->GetExpirationTime(&expiration);

          /* set the expiration time on our entry */
          mCacheEntry->SetExpiryTime(expiration);
        }
      }
    }
    //
    // Determine whether the cache entry must be revalidated when it expires.
    // If so, then the cache entry must *not* be used during HISTORY loads if
    // it has expired.
    //
    // Currently, only HTTP specifies this information...
    //
    nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aRequest));
    if (httpChannel) {
      PRBool bMustRevalidate = PR_FALSE;

      rv = httpChannel->IsNoStoreResponse(&bMustRevalidate);

      if (!bMustRevalidate) {
        rv = httpChannel->IsNoCacheResponse(&bMustRevalidate);
      }

      if (!bMustRevalidate) {
        nsCAutoString cacheHeader;

        rv = httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("Cache-Control"),
                                            cacheHeader);
        if (PL_strcasestr(cacheHeader.get(), "must-revalidate")) {
          bMustRevalidate = PR_TRUE;
        }
      }

      mCacheEntry->SetMustValidateIfExpired(bMustRevalidate);
    }
  }


  // Shouldn't we be dead already if this gets hit?  Probably multipart/x-mixed-replace...
  if (mObservers.IsEmpty()) {
    this->Cancel(NS_IMAGELIB_ERROR_FAILURE);
  }

  return NS_OK;
}
nsresult
NS_StartCORSPreflight(nsIChannel* aRequestChannel,
                      nsIStreamListener* aListener,
                      nsIPrincipal* aPrincipal,
                      PRBool aWithCredentials,
                      nsTArray<nsCString>& aUnsafeHeaders,
                      nsIChannel** aPreflightChannel)
{
  *aPreflightChannel = nsnull;

  nsCAutoString method;
  nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aRequestChannel));
  NS_ENSURE_TRUE(httpChannel, NS_ERROR_UNEXPECTED);
  httpChannel->GetRequestMethod(method);

  nsCOMPtr<nsIURI> uri;
  nsresult rv = NS_GetFinalChannelURI(aRequestChannel, getter_AddRefs(uri));
  NS_ENSURE_SUCCESS(rv, rv);

  nsPreflightCache::CacheEntry* entry =
    sPreflightCache ?
    sPreflightCache->GetEntry(uri, aPrincipal, aWithCredentials, PR_FALSE) :
    nsnull;

  if (entry && entry->CheckRequest(method, aUnsafeHeaders)) {
    // We have a cached preflight result, just start the original channel
    return aRequestChannel->AsyncOpen(aListener, nsnull);
  }

  // Either it wasn't cached or the cached result has expired. Build a
  // channel for the OPTIONS request.

  nsCOMPtr<nsILoadGroup> loadGroup;
  rv = aRequestChannel->GetLoadGroup(getter_AddRefs(loadGroup));
  NS_ENSURE_SUCCESS(rv, rv);

  nsLoadFlags loadFlags;
  rv = aRequestChannel->GetLoadFlags(&loadFlags);
  NS_ENSURE_SUCCESS(rv, rv);

  nsCOMPtr<nsIChannel> preflightChannel;
  rv = NS_NewChannel(getter_AddRefs(preflightChannel), uri, nsnull,
                     loadGroup, nsnull, loadFlags);
  NS_ENSURE_SUCCESS(rv, rv);

  nsCOMPtr<nsIHttpChannel> preHttp = do_QueryInterface(preflightChannel);
  NS_ASSERTION(preHttp, "Failed to QI to nsIHttpChannel!");

  rv = preHttp->SetRequestMethod(NS_LITERAL_CSTRING("OPTIONS"));
  NS_ENSURE_SUCCESS(rv, rv);
  
  // Set up listener which will start the original channel
  nsCOMPtr<nsIStreamListener> preflightListener =
    new nsCORSPreflightListener(aRequestChannel, aListener, nsnull, aPrincipal,
                                method, aWithCredentials);
  NS_ENSURE_TRUE(preflightListener, NS_ERROR_OUT_OF_MEMORY);

  preflightListener =
    new nsCORSListenerProxy(preflightListener, aPrincipal,
                            preflightChannel, aWithCredentials,
                            method, aUnsafeHeaders, &rv);
  NS_ENSURE_TRUE(preflightListener, NS_ERROR_OUT_OF_MEMORY);
  NS_ENSURE_SUCCESS(rv, rv);

  // Start preflight
  rv = preflightChannel->AsyncOpen(preflightListener, nsnull);
  NS_ENSURE_SUCCESS(rv, rv);
  
  // Return newly created preflight channel
  preflightChannel.forget(aPreflightChannel);

  return NS_OK;
}
Ejemplo n.º 12
0
NS_IMETHODIMP 
HeaderSniffer::OnStopRequest (nsIRequest *aRequest, 
			      nsISupports *aContext, nsresult aStatusCode)
{  
	nsresult rv;
	LOG ("HeaderSniffer::OnStopRequest");

	if (aStatusCode != NS_BINDING_SUCCEEDED)
	{
		GtkWidget *parent, *dialog;

		parent = galeon_embed_persist_get_fc_parent (mEmbedPersist);

		dialog = hig_alert_new (parent ? GTK_WINDOW (parent) : NULL,
					GTK_DIALOG_DESTROY_WITH_PARENT,
					HIG_ALERT_ERROR,
					_("Unable to save link."),
					_("The web page might have been removed "
					  "or had its name changed."),
					GTK_STOCK_OK,
					GTK_RESPONSE_OK,
					NULL);
		g_signal_connect (dialog, "response",
				  (GCallback)gtk_widget_destroy, NULL);

		gtk_widget_show (dialog);
		return NS_OK;
	}

	nsCOMPtr<nsIURIChecker> checker = do_QueryInterface (aRequest);
	NS_ENSURE_TRUE (checker, NS_ERROR_FAILURE);

	nsCOMPtr<nsIChannel> channel;
	checker->GetBaseChannel (getter_AddRefs(channel));
	NS_ENSURE_TRUE (channel, NS_ERROR_FAILURE);

	/* Get the final URL of the request */
	channel->GetURI (getter_AddRefs(mFinalURL));

	/* Get the Content-Disposition header, it might give us a 
	 * hint on the filename */
	nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));

	GulCString contentDisposition;
	if (httpChannel)
	{
		httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("content-disposition"),
					       contentDisposition);
	}

	/* Get the document encoding */
	nsCOMPtr<nsIEncodedChannel> encodedChannel(do_QueryInterface(channel));
	GulCString contentEncoding;
	if (encodedChannel)
	{
		nsCOMPtr<nsIUTF8StringEnumerator> enumerator;
		encodedChannel->GetContentEncodings (getter_AddRefs (enumerator));

		if (enumerator)
		{
			PRBool more = PR_FALSE;
			enumerator->HasMore (&more);
			
			if (more)
			{
				enumerator->GetNext (contentEncoding);
			}
		}
	}

    	/* Get the Content-Type header */
	GulCString contentType;
	channel->GetContentType(contentType);
	
	if (contentType.Equals ("application/x-unknown-content-type"))
	{
		contentType = "";
	}

	/* If no Content-Type, try and get it from the document */
	if (contentType.IsEmpty() && mDocument)
	{
		nsCOMPtr<nsIDOMNSDocument> doc = do_QueryInterface(mDocument);
		if (doc)
		{
			GulString type;
			doc->GetContentType (type);
			contentType = type;
		}
	}

	/* Failing that, guess from the url */
	if (contentType.IsEmpty())
	{
		nsCOMPtr<nsIMIMEService> mimeService (do_GetService(NS_MIMESERVICE_CONTRACTID));

		mimeService->GetTypeFromURI (mFinalURL, contentType);
	}

	/* Calculate whether we whould decode */
	mShouldDecode = PR_FALSE;

	if (contentEncoding.Length ())
	{
		nsCOMPtr<nsIExternalHelperAppService> helperService =
			do_GetService (NS_EXTERNALHELPERAPPSERVICE_CONTRACTID);

		nsCOMPtr<nsIURL> resultURL = do_QueryInterface (mFinalURL);
		if (resultURL)
		{
			GulCString extension;
			resultURL->GetFileExtension (extension);

			rv = helperService->ApplyDecodingForExtension (extension,
								       contentEncoding,
								       &mShouldDecode);

			if (NS_FAILED (rv))
			{
				mShouldDecode = PR_FALSE;
			}
		}
	}

	if (!mDocument && !mShouldDecode && contentEncoding.Length())
	{
		// The data is encoded, we are not going to decode it,
		// and this is not a document save so just set our
		// content type to correspond to the outermost
		// encoding so we get extensions and the like right.
		contentType = contentEncoding;
	}


	GulCString filename;
	rv = GetFilename (contentDisposition, contentType, filename);
	NS_ENSURE_TRUE (NS_SUCCEEDED (rv), NS_ERROR_FAILURE);

	PerformSave (filename);
	return NS_OK;
}
NS_IMETHODIMP
nsPluginStreamListenerPeer::OnStartRequest(nsIRequest *request,
                                           nsISupports* aContext)
{
  nsresult rv = NS_OK;

  if (mRequests.IndexOfObject(GetBaseRequest(request)) == -1) {
    NS_ASSERTION(mRequests.Count() == 0,
                 "Only our initial stream should be unknown!");
    TrackRequest(request);
  }
  
  if (mHaveFiredOnStartRequest) {
    return NS_OK;
  }
  
  mHaveFiredOnStartRequest = true;
  
  nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
  NS_ENSURE_TRUE(channel, NS_ERROR_FAILURE);
  
  // deal with 404 (Not Found) HTTP response,
  // just return, this causes the request to be ignored.
  nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
  if (httpChannel) {
    PRUint32 responseCode = 0;
    rv = httpChannel->GetResponseStatus(&responseCode);
    if (NS_FAILED(rv)) {
      // NPP_Notify() will be called from OnStopRequest
      // in nsNPAPIPluginStreamListener::CleanUpStream
      // return error will cancel this request
      // ...and we also need to tell the plugin that
      mRequestFailed = true;
      return NS_ERROR_FAILURE;
    }
    
    if (responseCode > 206) { // not normal
      bool bWantsAllNetworkStreams = false;

      // We don't always have an instance here already, but if we do, check
      // to see if it wants all streams.
      if (mPluginInstance) {
        rv = mPluginInstance->GetValueFromPlugin(NPPVpluginWantsAllNetworkStreams,
                                                 &bWantsAllNetworkStreams);
        // If the call returned an error code make sure we still use our default value.
        if (NS_FAILED(rv)) {
          bWantsAllNetworkStreams = false;
        }
      }

      if (!bWantsAllNetworkStreams) {
        mRequestFailed = true;
        return NS_ERROR_FAILURE;
      }
    }
  }
  
  // do a little sanity check to make sure our frame isn't gone
  // by getting the tag type and checking for an error, we can determine if
  // the frame is gone
  if (mOwner) {
    nsCOMPtr<nsIPluginTagInfo> pti = do_QueryInterface(mOwner);
    NS_ENSURE_TRUE(pti, NS_ERROR_FAILURE);
    nsPluginTagType tagType;
    if (NS_FAILED(pti->GetTagType(&tagType)))
      return NS_ERROR_FAILURE;  // something happened to our object frame, so bail!
  }
  
  // Get the notification callbacks from the channel and save it as
  // week ref we'll use it in nsPluginStreamInfo::RequestRead() when
  // we'll create channel for byte range request.
  nsCOMPtr<nsIInterfaceRequestor> callbacks;
  channel->GetNotificationCallbacks(getter_AddRefs(callbacks));
  if (callbacks)
    mWeakPtrChannelCallbacks = do_GetWeakReference(callbacks);
  
  nsCOMPtr<nsILoadGroup> loadGroup;
  channel->GetLoadGroup(getter_AddRefs(loadGroup));
  if (loadGroup)
    mWeakPtrChannelLoadGroup = do_GetWeakReference(loadGroup);
  
  PRInt32 length;
  rv = channel->GetContentLength(&length);
  
  // it's possible for the server to not send a Content-Length.
  // we should still work in this case.
  if (NS_FAILED(rv) || length == -1) {
    // check out if this is file channel
    nsCOMPtr<nsIFileChannel> fileChannel = do_QueryInterface(channel);
    if (fileChannel) {
      // file does not exist
      mRequestFailed = true;
      return NS_ERROR_FAILURE;
    }
    mLength = 0;
  }
  else {
    mLength = length;
  }
  
  nsCAutoString aContentType; // XXX but we already got the type above!
  rv = channel->GetContentType(aContentType);
  if (NS_FAILED(rv))
    return rv;
  
  nsCOMPtr<nsIURI> aURL;
  rv = channel->GetURI(getter_AddRefs(aURL));
  if (NS_FAILED(rv))
    return rv;
  
  aURL->GetSpec(mURLSpec);
  
  if (!aContentType.IsEmpty())
    mContentType = aContentType;
  
#ifdef PLUGIN_LOGGING
  PR_LOG(nsPluginLogging::gPluginLog, PLUGIN_LOG_NOISY,
         ("nsPluginStreamListenerPeer::OnStartRequest this=%p request=%p mime=%s, url=%s\n",
          this, request, aContentType.get(), mURLSpec.get()));
  
  PR_LogFlush();
#endif
  
  NPWindow* window = nsnull;
  
  // if we don't have an nsNPAPIPluginInstance (mPluginInstance), it means
  // we weren't able to load a plugin previously because we
  // didn't have the mimetype.  Now that we do (aContentType),
  // we'll try again with SetUpPluginInstance()
  // which is called by InstantiateEmbeddedPlugin()
  // NOTE: we don't want to try again if we didn't get the MIME type this time
  
  if (!mPluginInstance && mOwner && !aContentType.IsEmpty()) {
    nsRefPtr<nsNPAPIPluginInstance> pluginInstRefPtr;
    mOwner->GetInstance(getter_AddRefs(pluginInstRefPtr));
    mPluginInstance = pluginInstRefPtr.get();

    mOwner->GetWindow(window);
    if (!mPluginInstance && window) {
      nsRefPtr<nsPluginHost> pluginHost = dont_AddRef(nsPluginHost::GetInst());
      rv = pluginHost->SetUpPluginInstance(aContentType.get(), aURL, mOwner);
      if (NS_SUCCEEDED(rv)) {
        mOwner->GetInstance(getter_AddRefs(pluginInstRefPtr));
        mPluginInstance = pluginInstRefPtr.get();
        if (mPluginInstance) {
          mOwner->CreateWidget();
          // If we've got a native window, the let the plugin know about it.
          mOwner->SetWindow();
        }
      }
    }
  }
  
  // Set up the stream listener...
  rv = SetUpStreamListener(request, aURL);
  if (NS_FAILED(rv)) return rv;
  
  return rv;
}
Ejemplo n.º 14
0
// This method is largely cribbed from
// nsExternalResourceMap::PendingLoad::SetupViewer.
nsresult
SVGDocumentWrapper::SetupViewer(nsIRequest* aRequest,
                                nsIContentViewer** aViewer,
                                nsILoadGroup** aLoadGroup)
{
  nsCOMPtr<nsIChannel> chan(do_QueryInterface(aRequest));
  NS_ENSURE_TRUE(chan, NS_ERROR_UNEXPECTED);

  // Check for HTTP error page
  nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aRequest));
  if (httpChannel) {
    bool requestSucceeded;
    if (NS_FAILED(httpChannel->GetRequestSucceeded(&requestSucceeded)) ||
        !requestSucceeded) {
      return NS_ERROR_FAILURE;
    }
  }

  // Give this document its own loadgroup
  nsCOMPtr<nsILoadGroup> loadGroup;
  chan->GetLoadGroup(getter_AddRefs(loadGroup));

  nsCOMPtr<nsILoadGroup> newLoadGroup =
        do_CreateInstance(NS_LOADGROUP_CONTRACTID);
  NS_ENSURE_TRUE(newLoadGroup, NS_ERROR_OUT_OF_MEMORY);
  newLoadGroup->SetLoadGroup(loadGroup);

  nsCOMPtr<nsICategoryManager> catMan =
    do_GetService(NS_CATEGORYMANAGER_CONTRACTID);
  NS_ENSURE_TRUE(catMan, NS_ERROR_NOT_AVAILABLE);
  nsXPIDLCString contractId;
  nsresult rv = catMan->GetCategoryEntry("Gecko-Content-Viewers", IMAGE_SVG_XML,
                                         getter_Copies(contractId));
  NS_ENSURE_SUCCESS(rv, rv);
  nsCOMPtr<nsIDocumentLoaderFactory> docLoaderFactory =
    do_GetService(contractId);
  NS_ENSURE_TRUE(docLoaderFactory, NS_ERROR_NOT_AVAILABLE);

  nsCOMPtr<nsIContentViewer> viewer;
  nsCOMPtr<nsIStreamListener> listener;
  rv = docLoaderFactory->CreateInstance("external-resource", chan,
                                        newLoadGroup,
                                        NS_LITERAL_CSTRING(IMAGE_SVG_XML),
                                        nullptr, nullptr,
                                        getter_AddRefs(listener),
                                        getter_AddRefs(viewer));
  NS_ENSURE_SUCCESS(rv, rv);

  NS_ENSURE_TRUE(viewer, NS_ERROR_UNEXPECTED);

  nsCOMPtr<nsIParser> parser = do_QueryInterface(listener);
  NS_ENSURE_TRUE(parser, NS_ERROR_UNEXPECTED);

  // XML-only, because this is for SVG content
  nsIContentSink* sink = parser->GetContentSink();
  nsCOMPtr<nsIXMLContentSink> xmlSink = do_QueryInterface(sink);
  NS_ENSURE_TRUE(sink, NS_ERROR_UNEXPECTED);

  listener.swap(mListener);
  viewer.forget(aViewer);
  newLoadGroup.forget(aLoadGroup);

  RegisterForXPCOMShutdown();
  return NS_OK;
}
Ejemplo n.º 15
0
/* void onDataAvailable (in nsIRequest request, in nsISupports ctxt, in nsIInputStream inStr, in unsigned long sourceOffset, in unsigned long count); */
NS_IMETHODIMP imgRequest::OnDataAvailable(nsIRequest *aRequest, nsISupports *ctxt, nsIInputStream *inStr, PRUint32 sourceOffset, PRUint32 count)
{
  LOG_SCOPE_WITH_PARAM(gImgLog, "imgRequest::OnDataAvailable", "count", count);

  NS_ASSERTION(aRequest, "imgRequest::OnDataAvailable -- no request!");

  mGotData = PR_TRUE;

  if (!mProcessing) {
    LOG_SCOPE(gImgLog, "imgRequest::OnDataAvailable |First time through... finding mimetype|");

    /* set our processing flag to true if this is the first OnDataAvailable() */
    mProcessing = PR_TRUE;

    /* look at the first few bytes and see if we can tell what the data is from that
     * since servers tend to lie. :(
     */
    PRUint32 out;
    inStr->ReadSegments(sniff_mimetype_callback, this, count, &out);

#ifdef NS_DEBUG
    /* NS_WARNING if the content type from the channel isn't the same if the sniffing */
#endif

    if (mContentType.IsEmpty()) {
      LOG_SCOPE(gImgLog, "imgRequest::OnDataAvailable |sniffing of mimetype failed|");

      nsCOMPtr<nsIChannel> chan(do_QueryInterface(aRequest));

      nsresult rv = NS_ERROR_FAILURE;
      if (chan) {
        rv = chan->GetContentType(mContentType);
      }

      if (NS_FAILED(rv)) {
        PR_LOG(gImgLog, PR_LOG_ERROR,
               ("[this=%p] imgRequest::OnDataAvailable -- Content type unavailable from the channel\n",
                this));

        this->Cancel(NS_IMAGELIB_ERROR_FAILURE);

        return NS_BINDING_ABORTED;
      }

      LOG_MSG(gImgLog, "imgRequest::OnDataAvailable", "Got content type from the channel");
    }

    /* set our mimetype as a property */
    nsCOMPtr<nsISupportsCString> contentType(do_CreateInstance("@mozilla.org/supports-cstring;1"));
    if (contentType) {
      contentType->SetData(mContentType);
      mProperties->Set("type", contentType);
    }

    /* set our content disposition as a property */
    nsCAutoString disposition;
    nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aRequest));
    if (httpChannel) {
      httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("content-disposition"), disposition);
    } else {
      nsCOMPtr<nsIMultiPartChannel> multiPartChannel(do_QueryInterface(aRequest));
      if (multiPartChannel) {
        multiPartChannel->GetContentDisposition(disposition);
      }
    }
    if (!disposition.IsEmpty()) {
      nsCOMPtr<nsISupportsCString> contentDisposition(do_CreateInstance("@mozilla.org/supports-cstring;1"));
      if (contentDisposition) {
        contentDisposition->SetData(disposition);
        mProperties->Set("content-disposition", contentDisposition);
      }
    }

    LOG_MSG_WITH_PARAM(gImgLog, "imgRequest::OnDataAvailable", "content type", mContentType.get());

    nsCAutoString conid(NS_LITERAL_CSTRING("@mozilla.org/image/decoder;2?type=") + mContentType);

    mDecoder = do_CreateInstance(conid.get());

    if (!mDecoder) {
      PR_LOG(gImgLog, PR_LOG_WARNING,
             ("[this=%p] imgRequest::OnDataAvailable -- Decoder not available\n", this));

      // no image decoder for this mimetype :(
      this->Cancel(NS_IMAGELIB_ERROR_NO_DECODER);

      return NS_IMAGELIB_ERROR_NO_DECODER;
    }

    nsresult rv = mDecoder->Init(static_cast<imgILoad*>(this));
    if (NS_FAILED(rv)) {
      PR_LOG(gImgLog, PR_LOG_WARNING,
             ("[this=%p] imgRequest::OnDataAvailable -- mDecoder->Init failed\n", this));

      this->Cancel(NS_IMAGELIB_ERROR_FAILURE);

      return NS_BINDING_ABORTED;
    }
  }

  if (!mDecoder) {
    PR_LOG(gImgLog, PR_LOG_WARNING,
           ("[this=%p] imgRequest::OnDataAvailable -- no decoder\n", this));

    this->Cancel(NS_IMAGELIB_ERROR_NO_DECODER);

    return NS_BINDING_ABORTED;
  }

  // The decoder will start decoding into the current frame (if we have one).
  // When it needs to add another frame, we will unlock this frame and lock the
  // new frame.
  // Our invariant is that, while in the decoder, the last frame is always
  // locked, and all others are unlocked.
  imgContainer *image = reinterpret_cast<imgContainer*>(mImage.get());
  if (image->mFrames.Length() > 0) {
    imgFrame *curframe = image->mFrames.ElementAt(image->mFrames.Length() - 1);
    curframe->LockImageData();
  }

  PRUint32 wrote;
  nsresult rv = mDecoder->WriteFrom(inStr, count, &wrote);

  // We unlock the current frame, even if that frame is different from the
  // frame we entered the decoder with. (See above.)
  if (image->mFrames.Length() > 0) {
    imgFrame *curframe = image->mFrames.ElementAt(image->mFrames.Length() - 1);
    curframe->UnlockImageData();
  }

  if (NS_FAILED(rv)) {
    PR_LOG(gImgLog, PR_LOG_WARNING,
           ("[this=%p] imgRequest::OnDataAvailable -- mDecoder->WriteFrom failed\n", this));

    this->Cancel(NS_IMAGELIB_ERROR_FAILURE);

    return NS_BINDING_ABORTED;
  }

  return NS_OK;
}
Ejemplo n.º 16
0
nsresult
nsPluginStreamListenerPeer::RequestRead(NPByteRange* rangeList)
{
  nsAutoCString rangeString;
  int32_t numRequests;

  MakeByteRangeString(rangeList, rangeString, &numRequests);

  if (numRequests == 0)
    return NS_ERROR_FAILURE;

  nsresult rv = NS_OK;

  nsRefPtr<nsPluginInstanceOwner> owner = mPluginInstance->GetOwner();
  nsCOMPtr<nsIDOMElement> element;
  nsCOMPtr<nsIDocument> doc;
  if (owner) {
    rv = owner->GetDOMElement(getter_AddRefs(element));
    NS_ENSURE_SUCCESS(rv, rv);
    rv = owner->GetDocument(getter_AddRefs(doc));
    NS_ENSURE_SUCCESS(rv, rv);
  }

  nsCOMPtr<nsIInterfaceRequestor> callbacks = do_QueryReferent(mWeakPtrChannelCallbacks);
  nsCOMPtr<nsILoadGroup> loadGroup = do_QueryReferent(mWeakPtrChannelLoadGroup);

  nsCOMPtr<nsIChannel> channel;
  nsCOMPtr<nsINode> requestingNode(do_QueryInterface(element));
  if (requestingNode) {
    rv = NS_NewChannel(getter_AddRefs(channel),
                       mURL,
                       requestingNode,
                       nsILoadInfo::SEC_NORMAL,
                       nsIContentPolicy::TYPE_OTHER,
                       loadGroup,
                       callbacks);
  }
  else {
    // in this else branch we really don't know where the load is coming
    // from and in fact should use something better than just using
    // a nullPrincipal as the loadingPrincipal.
    nsCOMPtr<nsIPrincipal> principal = nsNullPrincipal::Create();
    NS_ENSURE_TRUE(principal, NS_ERROR_FAILURE);
    rv = NS_NewChannel(getter_AddRefs(channel),
                       mURL,
                       principal,
                       nsILoadInfo::SEC_NORMAL,
                       nsIContentPolicy::TYPE_OTHER,
                       loadGroup,
                       callbacks);
  }

  if (NS_FAILED(rv))
    return rv;

  nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
  if (!httpChannel)
    return NS_ERROR_FAILURE;

  httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("Range"), rangeString, false);

  mAbort = true; // instruct old stream listener to cancel
  // the request on the next ODA.

  nsCOMPtr<nsIStreamListener> converter;

  if (numRequests == 1) {
    converter = this;
    // set current stream offset equal to the first offset in the range list
    // it will work for single byte range request
    // for multy range we'll reset it in ODA
    SetStreamOffset(rangeList->offset);
  } else {
    nsWeakPtr weakpeer =
    do_GetWeakReference(static_cast<nsISupportsWeakReference*>(this));
    nsPluginByteRangeStreamListener *brrListener =
    new nsPluginByteRangeStreamListener(weakpeer);
    if (brrListener)
      converter = brrListener;
    else
      return NS_ERROR_OUT_OF_MEMORY;
  }

  mPendingRequests += numRequests;

  nsCOMPtr<nsISupportsPRUint32> container = do_CreateInstance(NS_SUPPORTS_PRUINT32_CONTRACTID, &rv);
  if (NS_FAILED(rv))
    return rv;
  rv = container->SetData(MAGIC_REQUEST_CONTEXT);
  if (NS_FAILED(rv))
    return rv;

  rv = channel->AsyncOpen(converter, container);
  if (NS_SUCCEEDED(rv))
    TrackRequest(channel);
  return rv;
}
Ejemplo n.º 17
0
NS_IMETHODIMP
nsJARChannel::OnDownloadComplete(nsIDownloader *downloader,
                                 nsIRequest    *request,
                                 nsISupports   *context,
                                 nsresult       status,
                                 nsIFile       *file)
{
    nsresult rv;

    nsCOMPtr<nsIChannel> channel(do_QueryInterface(request));
    if (channel) {
        PRUint32 loadFlags;
        channel->GetLoadFlags(&loadFlags);
        if (loadFlags & LOAD_REPLACE) {
            mLoadFlags |= LOAD_REPLACE;

            if (!mOriginalURI) {
                SetOriginalURI(mJarURI);
            }

            nsCOMPtr<nsIURI> innerURI;
            rv = channel->GetURI(getter_AddRefs(innerURI));
            if (NS_SUCCEEDED(rv)) {
                nsCOMPtr<nsIJARURI> newURI;
                rv = mJarURI->CloneWithJARFile(innerURI,
                                               getter_AddRefs(newURI));
                if (NS_SUCCEEDED(rv)) {
                    mJarURI = newURI;
                }
            }
            if (NS_SUCCEEDED(status)) {
                status = rv;
            }
        }
    }

    if (NS_SUCCEEDED(status) && channel) {
        // Grab the security info from our base channel
        channel->GetSecurityInfo(getter_AddRefs(mSecurityInfo));

        nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
        if (httpChannel) {
            // We only want to run scripts if the server really intended to
            // send us a JAR file.  Check the server-supplied content type for
            // a JAR type.
            nsCAutoString header;
            httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("Content-Type"),
                                           header);
            nsCAutoString contentType;
            nsCAutoString charset;
            NS_ParseContentType(header, contentType, charset);
            nsCAutoString channelContentType;
            channel->GetContentType(channelContentType);
            mIsUnsafe = !(contentType.Equals(channelContentType) &&
                          (contentType.EqualsLiteral("application/java-archive") ||
                           contentType.EqualsLiteral("application/x-jar")));
        } else {
            nsCOMPtr<nsIJARChannel> innerJARChannel(do_QueryInterface(channel));
            if (innerJARChannel) {
                PRBool unsafe;
                innerJARChannel->GetIsUnsafe(&unsafe);
                mIsUnsafe = unsafe;
            }
        }

        channel->GetContentDisposition(mContentDisposition);
    }

    if (NS_SUCCEEDED(status) && mIsUnsafe) {
        PRBool allowUnpack = PR_FALSE;

        nsCOMPtr<nsIPrefBranch> prefs =
            do_GetService(NS_PREFSERVICE_CONTRACTID);
        if (prefs) {
            prefs->GetBoolPref("network.jar.open-unsafe-types", &allowUnpack);
        }

        if (!allowUnpack) {
            status = NS_ERROR_UNSAFE_CONTENT_TYPE;
        }
    }

    if (NS_SUCCEEDED(status)) {
        // Refuse to unpack view-source: jars even if open-unsafe-types is set.
        nsCOMPtr<nsIViewSourceChannel> viewSource = do_QueryInterface(channel);
        if (viewSource) {
            status = NS_ERROR_UNSAFE_CONTENT_TYPE;
        }
    }

    if (NS_SUCCEEDED(status)) {
        mJarFile = file;
    
        rv = CreateJarInput(nsnull);
        if (NS_SUCCEEDED(rv)) {
            // create input stream pump
            rv = NS_NewInputStreamPump(getter_AddRefs(mPump), mJarInput);
            if (NS_SUCCEEDED(rv))
                rv = mPump->AsyncRead(this, nsnull);
        }
        status = rv;
    }

    if (NS_FAILED(status)) {
        mStatus = status;
        OnStartRequest(nsnull, nsnull);
        OnStopRequest(nsnull, nsnull, status);
    }

    return NS_OK;
}
Ejemplo n.º 18
0
nsresult
nsDOMWorkerScriptLoader::OnStreamCompleteInternal(nsIStreamLoader* aLoader,
                                                  nsISupports* aContext,
                                                  nsresult aStatus,
                                                  PRUint32 aStringLen,
                                                  const PRUint8* aString)
{
  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");

  nsCOMPtr<nsISupportsPRUint32> indexSupports(do_QueryInterface(aContext));
  NS_ENSURE_TRUE(indexSupports, NS_ERROR_NO_INTERFACE);

  PRUint32 index = PR_UINT32_MAX;
  indexSupports->GetData(&index);

  if (index >= mScriptCount) {
    NS_NOTREACHED("This really can't fail or we'll hang!");
    return NS_ERROR_FAILURE;
  }

  ScriptLoadInfo& loadInfo = mLoadInfos[index];

  NS_ASSERTION(!loadInfo.done, "Got complete on the same load twice!");
  loadInfo.done = PR_TRUE;

#ifdef DEBUG
  // Make sure we're seeing the channel that we expect.
  nsCOMPtr<nsIRequest> requestDebug;
  nsresult rvDebug = aLoader->GetRequest(getter_AddRefs(requestDebug));

  // When we cancel sometimes we get null here. That should be ok, but only if
  // we're canceled.
  NS_ASSERTION(NS_SUCCEEDED(rvDebug) || mCanceled, "GetRequest failed!");

  if (NS_SUCCEEDED(rvDebug)) {
    nsCOMPtr<nsIChannel> channel(do_QueryInterface(requestDebug));
    NS_ASSERTION(channel, "QI failed!");

    nsCOMPtr<nsISupports> thisChannel(do_QueryInterface(channel));
    NS_ASSERTION(thisChannel, "QI failed!");

    nsCOMPtr<nsISupports> ourChannel(do_QueryInterface(loadInfo.channel));
    NS_ASSERTION(ourChannel, "QI failed!");

    NS_ASSERTION(thisChannel == ourChannel, "Wrong channel!");
  }
#endif

  // Use an alias to keep rv and loadInfo.result in sync.
  nsresult& rv = loadInfo.result = aStatus;

  if (NS_FAILED(rv)) {
    return rv;
  }

  if (!(aStringLen && aString)) {
    return rv = NS_ERROR_UNEXPECTED;
  }

  // Make sure we're not seeing the result of a 404 or something by checking the
  // 'requestSucceeded' attribute on the http channel.
  nsCOMPtr<nsIRequest> request;
  rv = aLoader->GetRequest(getter_AddRefs(request));
  NS_ENSURE_SUCCESS(rv, rv);

  nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(request));
  if (httpChannel) {
    PRBool requestSucceeded;
    rv = httpChannel->GetRequestSucceeded(&requestSucceeded);
    NS_ENSURE_SUCCESS(rv, rv);

    if (!requestSucceeded) {
      return rv = NS_ERROR_NOT_AVAILABLE;
    }
  }

  nsIDocument* parentDoc = mWorker->Pool()->ParentDocument();
  if (!parentDoc) {
    NS_ASSERTION(mWorker->IsCanceled(),
                 "Null parent document when we're not canceled?!");
    return rv = NS_ERROR_FAILURE;
  }

  // Use the regular nsScriptLoader for this grunt work! Should be just fine
  // because we're running on the main thread.
  rv = nsScriptLoader::ConvertToUTF16(loadInfo.channel, aString, aStringLen,
                                      EmptyString(), parentDoc,
                                      loadInfo.scriptText);
  if (NS_FAILED(rv)) {
    return rv;
  }

  if (loadInfo.scriptText.IsEmpty()) {
    return rv = NS_ERROR_FAILURE;
  }

  nsCString filename;
  loadInfo.finalURI->GetSpec(filename);

  if (filename.IsEmpty()) {
    filename.Assign(NS_LossyConvertUTF16toASCII(loadInfo.url));
  }
  else {
    // This will help callers figure out what their script url resolved to in
    // case of errors.
    loadInfo.url.Assign(NS_ConvertUTF8toUTF16(filename));
  }

  nsRefPtr<ScriptCompiler> compiler =
    new ScriptCompiler(this, loadInfo.scriptText, filename, loadInfo.scriptObj);
  NS_ASSERTION(compiler, "Out of memory!");
  if (!compiler) {
    return rv = NS_ERROR_OUT_OF_MEMORY;
  }

  rv = mTarget->Dispatch(compiler, NS_DISPATCH_NORMAL);
  NS_ENSURE_SUCCESS(rv, rv);

  return rv;
}
nsresult
CVE_2013_1709_thunderbird6_0_2_nsDocShell::AddToSessionHistory(nsIURI * aURI, nsIChannel * aChannel,
                                nsISupports* aOwner, PRBool aCloneChildren,
                                nsISHEntry ** aNewEntry)
{
    NS_PRECONDITION(aURI, "uri is null");
    NS_PRECONDITION(!aChannel || !aOwner, "Shouldn't have both set");

#if defined(PR_LOGGING) && defined(DEBUG)
    if (PR_LOG_TEST(gDocShellLog, PR_LOG_DEBUG)) {
        nsCAutoString spec;
        aURI->GetSpec(spec);

        nsCAutoString chanName;
        if (aChannel)
            aChannel->GetName(chanName);
        else
            chanName.AssignLiteral("<no channel>");

        PR_LOG(gDocShellLog, PR_LOG_DEBUG,
               ("nsDocShell[%p]::AddToSessionHistory(\"%s\", [%s])\n", this, spec.get(),
                chanName.get()));
    }
#endif

    nsresult rv = NS_OK;
    nsCOMPtr<nsISHEntry> entry;
    PRBool shouldPersist;

    shouldPersist = ShouldAddToSessionHistory(aURI);

    // Get a handle to the root docshell 
    nsCOMPtr<nsIDocShellTreeItem> root;
    GetSameTypeRootTreeItem(getter_AddRefs(root));     
    /*
     * If this is a LOAD_FLAGS_REPLACE_HISTORY in a subframe, we use
     * the existing SH entry in the page and replace the url and
     * other vitalities.
     */
    if (LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY) &&
        root != static_cast<nsIDocShellTreeItem *>(this)) {
        // This is a subframe 
        entry = mOSHE;
        nsCOMPtr<nsISHContainer> shContainer(do_QueryInterface(entry));
        if (shContainer) {
            PRInt32 childCount = 0;
            shContainer->GetChildCount(&childCount);
            // Remove all children of this entry 
            for (PRInt32 i = childCount - 1; i >= 0; i--) {
                nsCOMPtr<nsISHEntry> child;
                shContainer->GetChildAt(i, getter_AddRefs(child));
                shContainer->RemoveChild(child);
            }  // for
        }  // shContainer
    }

    // Create a new entry if necessary.
    if (!entry) {
        entry = do_CreateInstance(NS_SHENTRY_CONTRACTID);

        if (!entry) {
            return NS_ERROR_OUT_OF_MEMORY;
        }
    }

    // Get the post data & referrer
    nsCOMPtr<nsIInputStream> inputStream;
    nsCOMPtr<nsIURI> referrerURI;
    nsCOMPtr<nsISupports> cacheKey;
    nsCOMPtr<nsISupports> owner = aOwner;
    PRBool expired = PR_FALSE;
    PRBool discardLayoutState = PR_FALSE;
    nsCOMPtr<nsICachingChannel> cacheChannel;
    if (aChannel) {
        cacheChannel = do_QueryInterface(aChannel);

        /* If there is a caching channel, get the Cache Key and store it
         * in SH.
         */
        if (cacheChannel) {
            cacheChannel->GetCacheKey(getter_AddRefs(cacheKey));
        }
        nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
        
        // Check if the httpChannel is hiding under a multipartChannel
        if (!httpChannel) {
            GetHttpChannel(aChannel, getter_AddRefs(httpChannel));
        }
        if (httpChannel) {
            nsCOMPtr<nsIUploadChannel> uploadChannel(do_QueryInterface(httpChannel));
            if (uploadChannel) {
                uploadChannel->GetUploadStream(getter_AddRefs(inputStream));
            }
            httpChannel->GetReferrer(getter_AddRefs(referrerURI));

            discardLayoutState = ShouldDiscardLayoutState(httpChannel);
        }
        aChannel->GetOwner(getter_AddRefs(owner));
    }

    //Title is set in nsDocShell::SetTitle()
    entry->Create(aURI,              // uri
                  EmptyString(),     // Title
                  inputStream,       // Post data stream
                  nsnull,            // LayoutHistory state
                  cacheKey,          // CacheKey
                  mContentTypeHint,  // Content-type
                  owner,             // Channel or provided owner
                  mHistoryID,
                  mDynamicallyCreated);
    entry->SetReferrerURI(referrerURI);
    /* If cache got a 'no-store', ask SH not to store
     * HistoryLayoutState. By default, SH will set this
     * flag to PR_TRUE and save HistoryLayoutState.
     */    
    if (discardLayoutState) {
        entry->SetSaveLayoutStateFlag(PR_FALSE);
    }
    if (cacheChannel) {
        // Check if the page has expired from cache
        PRUint32 expTime = 0;
        cacheChannel->GetCacheTokenExpirationTime(&expTime);
        PRUint32 now = PRTimeToSeconds(PR_Now());
        if (expTime <=  now)
            expired = PR_TRUE;
    }
    if (expired)
        entry->SetExpirationStatus(PR_TRUE);


    if (root == static_cast<nsIDocShellTreeItem *>(this) && mSessionHistory) {
        // If we need to clone our children onto the new session
        // history entry, do so now.
        if (aCloneChildren && mOSHE) {
            PRUint32 cloneID;
            mOSHE->GetID(&cloneID);
            nsCOMPtr<nsISHEntry> newEntry;
            CloneAndReplace(mOSHE, this, cloneID, entry, PR_TRUE, getter_AddRefs(newEntry));
            NS_ASSERTION(entry == newEntry, "The new session history should be in the new entry");
        }

        // This is the root docshell
        if (LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY)) {            
            // Replace current entry in session history.
            PRInt32  index = 0;   
            mSessionHistory->GetIndex(&index);
            nsCOMPtr<nsISHistoryInternal>   shPrivate(do_QueryInterface(mSessionHistory));
            // Replace the current entry with the new entry
            if (shPrivate)
                rv = shPrivate->ReplaceEntry(index, entry);          
        }
        else {
            // Add to session history
            nsCOMPtr<nsISHistoryInternal>
                shPrivate(do_QueryInterface(mSessionHistory));
            NS_ENSURE_TRUE(shPrivate, NS_ERROR_FAILURE);
            mSessionHistory->GetIndex(&mPreviousTransIndex);
            rv = shPrivate->AddEntry(entry, shouldPersist);
            mSessionHistory->GetIndex(&mLoadedTransIndex);
#ifdef DEBUG_PAGE_CACHE
            printf("Previous index: %d, Loaded index: %d\n\n",
                   mPreviousTransIndex, mLoadedTransIndex);
#endif
        }
    }
    else {  
        // This is a subframe.
        if (!mOSHE || !LOAD_TYPE_HAS_FLAGS(mLoadType,
                                           LOAD_FLAGS_REPLACE_HISTORY))
            rv = DoAddChildSHEntry(entry, mChildOffset, aCloneChildren);
    }

    // Return the new SH entry...
    if (aNewEntry) {
        *aNewEntry = nsnull;
        if (NS_SUCCEEDED(rv)) {
            *aNewEntry = entry;
            NS_ADDREF(*aNewEntry);
        }
    }

    return rv;
}
NS_IMETHODIMP
nsPluginStreamListenerPeer::OnStartRequest(nsIRequest *request,
        nsISupports* aContext)
{
    nsresult rv = NS_OK;
    SAMPLE_LABEL("nsPluginStreamListenerPeer", "OnStartRequest");

    if (mRequests.IndexOfObject(GetBaseRequest(request)) == -1) {
        NS_ASSERTION(mRequests.Count() == 0,
                     "Only our initial stream should be unknown!");
        TrackRequest(request);
    }

    if (mHaveFiredOnStartRequest) {
        return NS_OK;
    }

    mHaveFiredOnStartRequest = true;

    nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
    NS_ENSURE_TRUE(channel, NS_ERROR_FAILURE);

    // deal with 404 (Not Found) HTTP response,
    // just return, this causes the request to be ignored.
    nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
    if (httpChannel) {
        uint32_t responseCode = 0;
        rv = httpChannel->GetResponseStatus(&responseCode);
        if (NS_FAILED(rv)) {
            // NPP_Notify() will be called from OnStopRequest
            // in nsNPAPIPluginStreamListener::CleanUpStream
            // return error will cancel this request
            // ...and we also need to tell the plugin that
            mRequestFailed = true;
            return NS_ERROR_FAILURE;
        }

        if (responseCode > 206) { // not normal
            uint32_t wantsAllNetworkStreams = 0;

            // We don't always have an instance here already, but if we do, check
            // to see if it wants all streams.
            if (mPluginInstance) {
                rv = mPluginInstance->GetValueFromPlugin(NPPVpluginWantsAllNetworkStreams,
                        &wantsAllNetworkStreams);
                // If the call returned an error code make sure we still use our default value.
                if (NS_FAILED(rv)) {
                    wantsAllNetworkStreams = 0;
                }
            }

            if (!wantsAllNetworkStreams) {
                mRequestFailed = true;
                return NS_ERROR_FAILURE;
            }
        }
    }

    // Get the notification callbacks from the channel and save it as
    // week ref we'll use it in nsPluginStreamInfo::RequestRead() when
    // we'll create channel for byte range request.
    nsCOMPtr<nsIInterfaceRequestor> callbacks;
    channel->GetNotificationCallbacks(getter_AddRefs(callbacks));
    if (callbacks)
        mWeakPtrChannelCallbacks = do_GetWeakReference(callbacks);

    nsCOMPtr<nsILoadGroup> loadGroup;
    channel->GetLoadGroup(getter_AddRefs(loadGroup));
    if (loadGroup)
        mWeakPtrChannelLoadGroup = do_GetWeakReference(loadGroup);

    int64_t length;
    rv = channel->GetContentLength(&length);

    // it's possible for the server to not send a Content-Length.
    // we should still work in this case.
    if (NS_FAILED(rv) || length == -1) {
        // check out if this is file channel
        nsCOMPtr<nsIFileChannel> fileChannel = do_QueryInterface(channel);
        if (fileChannel) {
            // file does not exist
            mRequestFailed = true;
            return NS_ERROR_FAILURE;
        }
        mLength = 0;
    }
    else {
        mLength = length;
    }

    nsAutoCString aContentType; // XXX but we already got the type above!
    rv = channel->GetContentType(aContentType);
    if (NS_FAILED(rv))
        return rv;

    nsCOMPtr<nsIURI> aURL;
    rv = channel->GetURI(getter_AddRefs(aURL));
    if (NS_FAILED(rv))
        return rv;

    aURL->GetSpec(mURLSpec);

    if (!aContentType.IsEmpty())
        mContentType = aContentType;

#ifdef PLUGIN_LOGGING
    PR_LOG(nsPluginLogging::gPluginLog, PLUGIN_LOG_NOISY,
           ("nsPluginStreamListenerPeer::OnStartRequest this=%p request=%p mime=%s, url=%s\n",
            this, request, aContentType.get(), mURLSpec.get()));

    PR_LogFlush();
#endif

    // Set up the stream listener...
    rv = SetUpStreamListener(request, aURL);
    if (NS_FAILED(rv)) return rv;

    return rv;
}