modules/libjar/nsJARProtocolHandler.cpp
author Andreea Pavel <apavel@mozilla.com>
Tue, 21 Aug 2018 20:20:24 +0300
changeset 490366 d8a7212c51a48253bfa9551ecc9318a9536c62d4
parent 465193 60b94194d25cef664bf63bb8a7cc514d3835a1a7
child 508163 6f3709b3878117466168c40affa7bca0b60cf75b
permissions -rw-r--r--
Backed out 6 changesets (bug 1396821) for linux tier2 build bustages on a CLOSED TREE Backed out changeset 2fa2975f97e3 (bug 1396821) Backed out changeset c5895db52483 (bug 1396821) Backed out changeset 5c0ddd45f926 (bug 1396821) Backed out changeset 7c97853a85b9 (bug 1396821) Backed out changeset b61ce753f01e (bug 1396821) Backed out changeset 7ef3912feb2c (bug 1396821)

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "mozilla/ClearOnShutdown.h"
#include "nsAutoPtr.h"
#include "nsJARProtocolHandler.h"
#include "nsIIOService.h"
#include "nsCRT.h"
#include "nsIComponentManager.h"
#include "nsIServiceManager.h"
#include "nsJARURI.h"
#include "nsIURL.h"
#include "nsJARChannel.h"
#include "nsString.h"
#include "nsNetCID.h"
#include "nsIMIMEService.h"
#include "nsMimeTypes.h"
#include "nsThreadUtils.h"

static NS_DEFINE_CID(kZipReaderCacheCID, NS_ZIPREADERCACHE_CID);

#define NS_JAR_CACHE_SIZE 32

//-----------------------------------------------------------------------------

StaticRefPtr<nsJARProtocolHandler> gJarHandler;

nsJARProtocolHandler::nsJARProtocolHandler()
{
    MOZ_ASSERT(NS_IsMainThread());
}

nsJARProtocolHandler::~nsJARProtocolHandler()
{}

nsresult
nsJARProtocolHandler::Init()
{
    nsresult rv;

    mJARCache = do_CreateInstance(kZipReaderCacheCID, &rv);
    if (NS_FAILED(rv)) return rv;

    rv = mJARCache->Init(NS_JAR_CACHE_SIZE);
    return rv;
}

nsIMIMEService *
nsJARProtocolHandler::MimeService()
{
    if (!mMimeService)
        mMimeService = do_GetService("@mozilla.org/mime;1");

    return mMimeService.get();
}

NS_IMPL_ISUPPORTS(nsJARProtocolHandler,
                  nsIJARProtocolHandler,
                  nsIProtocolHandler,
                  nsISupportsWeakReference)

already_AddRefed<nsJARProtocolHandler>
nsJARProtocolHandler::GetSingleton()
{
    if (!gJarHandler) {
        gJarHandler = new nsJARProtocolHandler();
        if (NS_SUCCEEDED(gJarHandler->Init())) {
            ClearOnShutdown(&gJarHandler);
        } else {
            gJarHandler = nullptr;
        }
    }
    return do_AddRef(gJarHandler);
}

NS_IMETHODIMP
nsJARProtocolHandler::GetJARCache(nsIZipReaderCache* *result)
{
    *result = mJARCache;
    NS_ADDREF(*result);
    return NS_OK;
}

////////////////////////////////////////////////////////////////////////////////
// nsIProtocolHandler methods:

NS_IMETHODIMP
nsJARProtocolHandler::GetScheme(nsACString &result)
{
    result.AssignLiteral("jar");
    return NS_OK;
}

NS_IMETHODIMP
nsJARProtocolHandler::GetDefaultPort(int32_t *result)
{
    *result = -1;        // no port for JAR: URLs
    return NS_OK;
}

NS_IMETHODIMP
nsJARProtocolHandler::GetProtocolFlags(uint32_t *result)
{
    // URI_LOADABLE_BY_ANYONE, since it's our inner URI that will matter
    // anyway.
    *result = URI_NORELATIVE | URI_NOAUTH | URI_LOADABLE_BY_ANYONE;
    /* Although jar uris have their own concept of relative urls
       it is very different from the standard behaviour, so we
       have to say norelative here! */
    return NS_OK;
}

NS_IMETHODIMP
nsJARProtocolHandler::NewURI(const nsACString &aSpec,
                             const char *aCharset,
                             nsIURI *aBaseURI,
                             nsIURI **result)
{
    nsCOMPtr<nsIURI> base(aBaseURI);
    return NS_MutateURI(new nsJARURI::Mutator())
             .Apply(NS_MutatorMethod(&nsIJARURIMutator::SetSpecBaseCharset,
                                     nsCString(aSpec), base, aCharset))
             .Finalize(result);
}

NS_IMETHODIMP
nsJARProtocolHandler::NewChannel2(nsIURI* uri,
                                  nsILoadInfo* aLoadInfo,
                                  nsIChannel** result)
{
    nsJARChannel *chan = new nsJARChannel();
    if (!chan)
        return NS_ERROR_OUT_OF_MEMORY;
    NS_ADDREF(chan);

    nsresult rv = chan->Init(uri);
    if (NS_FAILED(rv)) {
        NS_RELEASE(chan);
        return rv;
    }

    // set the loadInfo on the new channel
    rv = chan->SetLoadInfo(aLoadInfo);
    if (NS_FAILED(rv)) {
        NS_RELEASE(chan);
        return rv;
    }

    *result = chan;
    return NS_OK;
}

NS_IMETHODIMP
nsJARProtocolHandler::NewChannel(nsIURI *uri, nsIChannel **result)
{
    return NewChannel2(uri, nullptr, result);
}


NS_IMETHODIMP
nsJARProtocolHandler::AllowPort(int32_t port, const char *scheme, bool *_retval)
{
    // don't override anything.
    *_retval = false;
    return NS_OK;
}

////////////////////////////////////////////////////////////////////////////////