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