Example #1
0
nsresult
nsJARChannel::LookupFile(bool aAllowAsync)
{
    LOG(("nsJARChannel::LookupFile [this=%x %s]\n", this, mSpec.get()));

    if (mJarFile)
        return NS_OK;

    nsresult rv;
    nsCOMPtr<nsIURI> uri;

    rv = mJarURI->GetJARFile(getter_AddRefs(mJarBaseURI));
    if (NS_FAILED(rv))
        return rv;

    rv = mJarURI->GetJAREntry(mJarEntry);
    if (NS_FAILED(rv))
        return rv;

    // The name of the JAR entry must not contain URL-escaped characters:
    // we're moving from URL domain to a filename domain here. nsStandardURL
    // does basic escaping by default, which breaks reading zipped files which
    // have e.g. spaces in their filenames.
    NS_UnescapeURL(mJarEntry);

    // try to get a nsIFile directly from the url, which will often succeed.
    {
        nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(mJarBaseURI);
        if (fileURL)
            fileURL->GetFile(getter_AddRefs(mJarFile));
    }
    // if we're in child process and have special "remoteopenfile:://" scheme,
    // create special nsIFile that gets file handle from parent when opened.
    if (!mJarFile && !gJarHandler->IsMainProcess()) {
        nsAutoCString scheme;
        rv = mJarBaseURI->GetScheme(scheme);
        if (NS_SUCCEEDED(rv) && scheme.EqualsLiteral("remoteopenfile")) {
            RefPtr<RemoteOpenFileChild> remoteFile = new RemoteOpenFileChild();
            rv = remoteFile->Init(mJarBaseURI, mAppURI);
            NS_ENSURE_SUCCESS(rv, rv);
            mJarFile = remoteFile;

            nsIZipReaderCache *jarCache = gJarHandler->JarCache();
            if (jarCache) {
                bool cached = false;
                rv = jarCache->IsCached(mJarFile, &cached);
                if (NS_SUCCEEDED(rv) && cached) {
                    // zipcache already has file mmapped: don't open on parent,
                    // just return and proceed to cache hit in CreateJarInput().
                    // When the file descriptor is needed, get it from JAR cache
                    // if available, otherwise do the remote open to get a new
                    // one.
                    #if defined(XP_WIN) || defined(MOZ_WIDGET_COCOA)
                    // Windows/OSX desktop builds skip remoting, we don't need
                    // file descriptor here.
                    return NS_OK;
                    #else
                    PRFileDesc *fd = nullptr;
                    jarCache->GetFd(mJarFile, &fd);
                    if (fd) {
                        return SetRemoteNSPRFileDesc(fd);
                    }
                    #endif
                }
            }

            if (!aAllowAsync) {
                mJarFile = nullptr;
                return NS_OK;
            }

            mOpeningRemote = true;

            if (gJarHandler->RemoteOpenFileInProgress(remoteFile, this)) {
                // JarHandler will trigger OnRemoteFileOpen() after the first
                // request for this file completes and we'll get a JAR cache
                // hit.
                return NS_OK;
            }

            // Open file on parent: OnRemoteFileOpenComplete called when done
            nsCOMPtr<nsITabChild> tabChild;
            NS_QueryNotificationCallbacks(this, tabChild);
            nsCOMPtr<nsILoadContext> loadContext;
            NS_QueryNotificationCallbacks(this, loadContext);
            rv = remoteFile->AsyncRemoteFileOpen(PR_RDONLY, this, tabChild,
                                                 loadContext);
            NS_ENSURE_SUCCESS(rv, rv);
        }
    }
    // try to handle a nested jar
    if (!mJarFile) {
        nsCOMPtr<nsIJARURI> jarURI = do_QueryInterface(mJarBaseURI);
        if (jarURI) {
            nsCOMPtr<nsIFileURL> fileURL;
            nsCOMPtr<nsIURI> innerJarURI;
            rv = jarURI->GetJARFile(getter_AddRefs(innerJarURI));
            if (NS_SUCCEEDED(rv))
                fileURL = do_QueryInterface(innerJarURI);
            if (fileURL) {
                fileURL->GetFile(getter_AddRefs(mJarFile));
                jarURI->GetJAREntry(mInnerJarEntry);
            }
        }
    }

    return rv;
}