Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #include "Omnijar.h"
8 :
9 : #include "nsDirectoryService.h"
10 : #include "nsDirectoryServiceDefs.h"
11 : #include "nsIFile.h"
12 : #include "nsZipArchive.h"
13 : #include "nsNetUtil.h"
14 :
15 : namespace mozilla {
16 :
17 3 : StaticRefPtr<nsIFile> Omnijar::sPath[2];
18 3 : StaticRefPtr<nsZipArchive> Omnijar::sReader[2];
19 3 : StaticRefPtr<nsZipArchive> Omnijar::sOuterReader[2];
20 : bool Omnijar::sInitialized = false;
21 : bool Omnijar::sIsUnified = false;
22 :
23 : static const char* sProp[2] = {
24 : NS_GRE_DIR, NS_XPCOM_CURRENT_PROCESS_DIR
25 : };
26 :
27 : #define SPROP(Type) ((Type == mozilla::Omnijar::GRE) ? sProp[GRE] : sProp[APP])
28 :
29 : void
30 0 : Omnijar::CleanUpOne(Type aType)
31 : {
32 0 : if (sReader[aType]) {
33 0 : sReader[aType]->CloseArchive();
34 0 : sReader[aType] = nullptr;
35 : }
36 0 : if (sOuterReader[aType]) {
37 0 : sOuterReader[aType]->CloseArchive();
38 0 : sOuterReader[aType] = nullptr;
39 : }
40 0 : sPath[aType] = nullptr;
41 0 : }
42 :
43 : void
44 6 : Omnijar::InitOne(nsIFile* aPath, Type aType)
45 : {
46 6 : nsCOMPtr<nsIFile> file;
47 6 : if (aPath) {
48 0 : file = aPath;
49 : } else {
50 12 : nsCOMPtr<nsIFile> dir;
51 6 : nsDirectoryService::gService->Get(SPROP(aType), NS_GET_IID(nsIFile),
52 12 : getter_AddRefs(dir));
53 6 : NS_NAMED_LITERAL_CSTRING(kOmnijarName, NS_STRINGIFY(OMNIJAR_NAME));
54 12 : if (NS_FAILED(dir->Clone(getter_AddRefs(file))) ||
55 6 : NS_FAILED(file->AppendNative(kOmnijarName))) {
56 0 : return;
57 : }
58 : }
59 : bool isFile;
60 6 : if (NS_FAILED(file->IsFile(&isFile)) || !isFile) {
61 : // If we're not using an omni.jar for GRE, and we don't have an
62 : // omni.jar for APP, check if both directories are the same.
63 6 : if ((aType == APP) && (!sPath[GRE])) {
64 6 : nsCOMPtr<nsIFile> greDir, appDir;
65 : bool equals;
66 3 : nsDirectoryService::gService->Get(sProp[GRE], NS_GET_IID(nsIFile),
67 6 : getter_AddRefs(greDir));
68 3 : nsDirectoryService::gService->Get(sProp[APP], NS_GET_IID(nsIFile),
69 6 : getter_AddRefs(appDir));
70 3 : if (NS_SUCCEEDED(greDir->Equals(appDir, &equals)) && equals) {
71 0 : sIsUnified = true;
72 : }
73 : }
74 6 : return;
75 : }
76 :
77 : bool equals;
78 0 : if ((aType == APP) && (sPath[GRE]) &&
79 0 : NS_SUCCEEDED(sPath[GRE]->Equals(file, &equals)) && equals) {
80 : // If we're using omni.jar on both GRE and APP and their path
81 : // is the same, we're in the unified case.
82 0 : sIsUnified = true;
83 0 : return;
84 : }
85 :
86 0 : RefPtr<nsZipArchive> zipReader = new nsZipArchive();
87 0 : if (NS_FAILED(zipReader->OpenArchive(file))) {
88 0 : return;
89 : }
90 :
91 0 : RefPtr<nsZipArchive> outerReader;
92 0 : RefPtr<nsZipHandle> handle;
93 0 : if (NS_SUCCEEDED(nsZipHandle::Init(zipReader, NS_STRINGIFY(OMNIJAR_NAME),
94 : getter_AddRefs(handle)))) {
95 0 : outerReader = zipReader;
96 0 : zipReader = new nsZipArchive();
97 0 : if (NS_FAILED(zipReader->OpenArchive(handle))) {
98 0 : return;
99 : }
100 : }
101 :
102 0 : CleanUpOne(aType);
103 0 : sReader[aType] = zipReader;
104 0 : sOuterReader[aType] = outerReader;
105 0 : sPath[aType] = file;
106 : }
107 :
108 : void
109 3 : Omnijar::Init(nsIFile* aGrePath, nsIFile* aAppPath)
110 : {
111 3 : InitOne(aGrePath, GRE);
112 3 : InitOne(aAppPath, APP);
113 3 : sInitialized = true;
114 3 : }
115 :
116 : void
117 0 : Omnijar::CleanUp()
118 : {
119 0 : CleanUpOne(GRE);
120 0 : CleanUpOne(APP);
121 0 : sInitialized = false;
122 0 : }
123 :
124 : already_AddRefed<nsZipArchive>
125 0 : Omnijar::GetReader(nsIFile* aPath)
126 : {
127 0 : MOZ_ASSERT(IsInitialized(), "Omnijar not initialized");
128 :
129 : bool equals;
130 : nsresult rv;
131 :
132 0 : if (sPath[GRE]) {
133 0 : rv = sPath[GRE]->Equals(aPath, &equals);
134 0 : if (NS_SUCCEEDED(rv) && equals) {
135 0 : return IsNested(GRE) ? GetOuterReader(GRE) : GetReader(GRE);
136 : }
137 : }
138 0 : if (sPath[APP]) {
139 0 : rv = sPath[APP]->Equals(aPath, &equals);
140 0 : if (NS_SUCCEEDED(rv) && equals) {
141 0 : return IsNested(APP) ? GetOuterReader(APP) : GetReader(APP);
142 : }
143 : }
144 0 : return nullptr;
145 : }
146 :
147 : nsresult
148 790 : Omnijar::GetURIString(Type aType, nsACString& aResult)
149 : {
150 790 : MOZ_ASSERT(IsInitialized(), "Omnijar not initialized");
151 :
152 790 : aResult.Truncate();
153 :
154 : // Return an empty string for APP in the unified case.
155 790 : if ((aType == APP) && sIsUnified) {
156 0 : return NS_OK;
157 : }
158 :
159 1580 : nsAutoCString omniJarSpec;
160 790 : if (sPath[aType]) {
161 0 : nsresult rv = NS_GetURLSpecFromActualFile(sPath[aType], omniJarSpec);
162 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
163 0 : return rv;
164 : }
165 :
166 0 : aResult = "jar:";
167 0 : if (IsNested(aType)) {
168 0 : aResult += "jar:";
169 : }
170 0 : aResult += omniJarSpec;
171 0 : aResult += "!";
172 0 : if (IsNested(aType)) {
173 0 : aResult += "/" NS_STRINGIFY(OMNIJAR_NAME) "!";
174 : }
175 : } else {
176 1580 : nsCOMPtr<nsIFile> dir;
177 790 : nsDirectoryService::gService->Get(SPROP(aType), NS_GET_IID(nsIFile),
178 1580 : getter_AddRefs(dir));
179 790 : nsresult rv = NS_GetURLSpecFromActualFile(dir, aResult);
180 790 : if (NS_WARN_IF(NS_FAILED(rv))) {
181 0 : return rv;
182 : }
183 : }
184 790 : aResult += "/";
185 790 : return NS_OK;
186 : }
187 :
188 : } /* namespace mozilla */
|