michael@0: /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "Omnijar.h" michael@0: michael@0: #include "nsDirectoryService.h" michael@0: #include "nsDirectoryServiceDefs.h" michael@0: #include "nsIFile.h" michael@0: #include "nsZipArchive.h" michael@0: #include "nsNetUtil.h" michael@0: michael@0: namespace mozilla { michael@0: michael@0: nsIFile *Omnijar::sPath[2] = { nullptr, nullptr }; michael@0: nsZipArchive *Omnijar::sReader[2] = { nullptr, nullptr }; michael@0: bool Omnijar::sInitialized = false; michael@0: static bool sIsUnified = false; michael@0: static bool sIsNested[2] = { false, false }; michael@0: michael@0: static const char *sProp[2] = michael@0: { NS_GRE_DIR, NS_XPCOM_CURRENT_PROCESS_DIR }; michael@0: michael@0: #define SPROP(Type) ((Type == mozilla::Omnijar::GRE) ? sProp[GRE] : sProp[APP]) michael@0: michael@0: void michael@0: Omnijar::CleanUpOne(Type aType) michael@0: { michael@0: if (sReader[aType]) { michael@0: sReader[aType]->CloseArchive(); michael@0: NS_IF_RELEASE(sReader[aType]); michael@0: } michael@0: sReader[aType] = nullptr; michael@0: NS_IF_RELEASE(sPath[aType]); michael@0: } michael@0: michael@0: void michael@0: Omnijar::InitOne(nsIFile *aPath, Type aType) michael@0: { michael@0: nsCOMPtr file; michael@0: if (aPath) { michael@0: file = aPath; michael@0: } else { michael@0: nsCOMPtr dir; michael@0: nsDirectoryService::gService->Get(SPROP(aType), NS_GET_IID(nsIFile), getter_AddRefs(dir)); michael@0: NS_NAMED_LITERAL_CSTRING (kOmnijarName, NS_STRINGIFY(OMNIJAR_NAME)); michael@0: if (NS_FAILED(dir->Clone(getter_AddRefs(file))) || michael@0: NS_FAILED(file->AppendNative(kOmnijarName))) michael@0: return; michael@0: } michael@0: bool isFile; michael@0: if (NS_FAILED(file->IsFile(&isFile)) || !isFile) { michael@0: // If we're not using an omni.jar for GRE, and we don't have an michael@0: // omni.jar for APP, check if both directories are the same. michael@0: if ((aType == APP) && (!sPath[GRE])) { michael@0: nsCOMPtr greDir, appDir; michael@0: bool equals; michael@0: nsDirectoryService::gService->Get(SPROP(GRE), NS_GET_IID(nsIFile), getter_AddRefs(greDir)); michael@0: nsDirectoryService::gService->Get(SPROP(APP), NS_GET_IID(nsIFile), getter_AddRefs(appDir)); michael@0: if (NS_SUCCEEDED(greDir->Equals(appDir, &equals)) && equals) michael@0: sIsUnified = true; michael@0: } michael@0: return; michael@0: } michael@0: michael@0: bool equals; michael@0: if ((aType == APP) && (sPath[GRE]) && michael@0: NS_SUCCEEDED(sPath[GRE]->Equals(file, &equals)) && equals) { michael@0: // If we're using omni.jar on both GRE and APP and their path michael@0: // is the same, we're in the unified case. michael@0: sIsUnified = true; michael@0: return; michael@0: } michael@0: michael@0: nsRefPtr zipReader = new nsZipArchive(); michael@0: if (NS_FAILED(zipReader->OpenArchive(file))) { michael@0: return; michael@0: } michael@0: michael@0: nsRefPtr handle; michael@0: if (NS_SUCCEEDED(nsZipHandle::Init(zipReader, NS_STRINGIFY(OMNIJAR_NAME), getter_AddRefs(handle)))) { michael@0: zipReader = new nsZipArchive(); michael@0: if (NS_FAILED(zipReader->OpenArchive(handle))) michael@0: return; michael@0: sIsNested[aType] = true; michael@0: } michael@0: michael@0: CleanUpOne(aType); michael@0: sReader[aType] = zipReader; michael@0: NS_IF_ADDREF(sReader[aType]); michael@0: sPath[aType] = file; michael@0: NS_IF_ADDREF(sPath[aType]); michael@0: } michael@0: michael@0: void michael@0: Omnijar::Init(nsIFile *aGrePath, nsIFile *aAppPath) michael@0: { michael@0: InitOne(aGrePath, GRE); michael@0: InitOne(aAppPath, APP); michael@0: sInitialized = true; michael@0: } michael@0: michael@0: void michael@0: Omnijar::CleanUp() michael@0: { michael@0: CleanUpOne(GRE); michael@0: CleanUpOne(APP); michael@0: sInitialized = false; michael@0: } michael@0: michael@0: already_AddRefed michael@0: Omnijar::GetReader(nsIFile *aPath) michael@0: { michael@0: NS_ABORT_IF_FALSE(IsInitialized(), "Omnijar not initialized"); michael@0: michael@0: bool equals; michael@0: nsresult rv; michael@0: michael@0: if (sPath[GRE] && !sIsNested[GRE]) { michael@0: rv = sPath[GRE]->Equals(aPath, &equals); michael@0: if (NS_SUCCEEDED(rv) && equals) michael@0: return GetReader(GRE); michael@0: } michael@0: if (sPath[APP] && !sIsNested[APP]) { michael@0: rv = sPath[APP]->Equals(aPath, &equals); michael@0: if (NS_SUCCEEDED(rv) && equals) michael@0: return GetReader(APP); michael@0: } michael@0: return nullptr; michael@0: } michael@0: michael@0: nsresult michael@0: Omnijar::GetURIString(Type aType, nsACString &result) michael@0: { michael@0: NS_ABORT_IF_FALSE(IsInitialized(), "Omnijar not initialized"); michael@0: michael@0: result.Truncate(); michael@0: michael@0: // Return an empty string for APP in the unified case. michael@0: if ((aType == APP) && sIsUnified) { michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsAutoCString omniJarSpec; michael@0: if (sPath[aType]) { michael@0: nsresult rv = NS_GetURLSpecFromActualFile(sPath[aType], omniJarSpec); michael@0: if (NS_WARN_IF(NS_FAILED(rv))) michael@0: return rv; michael@0: michael@0: result = "jar:"; michael@0: if (sIsNested[aType]) michael@0: result += "jar:"; michael@0: result += omniJarSpec; michael@0: result += "!"; michael@0: if (sIsNested[aType]) michael@0: result += "/" NS_STRINGIFY(OMNIJAR_NAME) "!"; michael@0: } else { michael@0: nsCOMPtr dir; michael@0: nsDirectoryService::gService->Get(SPROP(aType), NS_GET_IID(nsIFile), getter_AddRefs(dir)); michael@0: nsresult rv = NS_GetURLSpecFromActualFile(dir, result); michael@0: if (NS_WARN_IF(NS_FAILED(rv))) michael@0: return rv; michael@0: } michael@0: result += "/"; michael@0: return NS_OK; michael@0: } michael@0: michael@0: } /* namespace mozilla */