Line data Source code
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 "nsAutoPtr.h"
7 : #include "nsJARProtocolHandler.h"
8 : #include "nsIIOService.h"
9 : #include "nsCRT.h"
10 : #include "nsIComponentManager.h"
11 : #include "nsIServiceManager.h"
12 : #include "nsJARURI.h"
13 : #include "nsIURL.h"
14 : #include "nsJARChannel.h"
15 : #include "nsXPIDLString.h"
16 : #include "nsString.h"
17 : #include "nsNetCID.h"
18 : #include "nsIMIMEService.h"
19 : #include "nsMimeTypes.h"
20 : #include "nsThreadUtils.h"
21 :
22 : static NS_DEFINE_CID(kZipReaderCacheCID, NS_ZIPREADERCACHE_CID);
23 :
24 : #define NS_JAR_CACHE_SIZE 32
25 :
26 : //-----------------------------------------------------------------------------
27 :
28 : nsJARProtocolHandler *gJarHandler = nullptr;
29 :
30 1 : nsJARProtocolHandler::nsJARProtocolHandler()
31 : {
32 1 : MOZ_ASSERT(NS_IsMainThread());
33 1 : }
34 :
35 0 : nsJARProtocolHandler::~nsJARProtocolHandler()
36 : {
37 0 : MOZ_ASSERT(gJarHandler == this);
38 0 : gJarHandler = nullptr;
39 0 : }
40 :
41 : nsresult
42 1 : nsJARProtocolHandler::Init()
43 : {
44 : nsresult rv;
45 :
46 1 : mJARCache = do_CreateInstance(kZipReaderCacheCID, &rv);
47 1 : if (NS_FAILED(rv)) return rv;
48 :
49 1 : rv = mJARCache->Init(NS_JAR_CACHE_SIZE);
50 1 : return rv;
51 : }
52 :
53 : nsIMIMEService *
54 0 : nsJARProtocolHandler::MimeService()
55 : {
56 0 : if (!mMimeService)
57 0 : mMimeService = do_GetService("@mozilla.org/mime;1");
58 :
59 0 : return mMimeService.get();
60 : }
61 :
62 16 : NS_IMPL_ISUPPORTS(nsJARProtocolHandler,
63 : nsIJARProtocolHandler,
64 : nsIProtocolHandler,
65 : nsISupportsWeakReference)
66 :
67 : nsJARProtocolHandler*
68 1 : nsJARProtocolHandler::GetSingleton()
69 : {
70 1 : if (!gJarHandler) {
71 1 : gJarHandler = new nsJARProtocolHandler();
72 1 : if (!gJarHandler)
73 0 : return nullptr;
74 :
75 1 : NS_ADDREF(gJarHandler);
76 1 : nsresult rv = gJarHandler->Init();
77 1 : if (NS_FAILED(rv)) {
78 0 : NS_RELEASE(gJarHandler);
79 0 : return nullptr;
80 : }
81 : }
82 1 : NS_ADDREF(gJarHandler);
83 1 : return gJarHandler;
84 : }
85 :
86 : NS_IMETHODIMP
87 0 : nsJARProtocolHandler::GetJARCache(nsIZipReaderCache* *result)
88 : {
89 0 : *result = mJARCache;
90 0 : NS_ADDREF(*result);
91 0 : return NS_OK;
92 : }
93 :
94 : ////////////////////////////////////////////////////////////////////////////////
95 : // nsIProtocolHandler methods:
96 :
97 : NS_IMETHODIMP
98 0 : nsJARProtocolHandler::GetScheme(nsACString &result)
99 : {
100 0 : result.AssignLiteral("jar");
101 0 : return NS_OK;
102 : }
103 :
104 : NS_IMETHODIMP
105 0 : nsJARProtocolHandler::GetDefaultPort(int32_t *result)
106 : {
107 0 : *result = -1; // no port for JAR: URLs
108 0 : return NS_OK;
109 : }
110 :
111 : NS_IMETHODIMP
112 0 : nsJARProtocolHandler::GetProtocolFlags(uint32_t *result)
113 : {
114 : // URI_LOADABLE_BY_ANYONE, since it's our inner URI that will matter
115 : // anyway.
116 0 : *result = URI_NORELATIVE | URI_NOAUTH | URI_LOADABLE_BY_ANYONE;
117 : /* Although jar uris have their own concept of relative urls
118 : it is very different from the standard behaviour, so we
119 : have to say norelative here! */
120 0 : return NS_OK;
121 : }
122 :
123 : NS_IMETHODIMP
124 0 : nsJARProtocolHandler::NewURI(const nsACString &aSpec,
125 : const char *aCharset,
126 : nsIURI *aBaseURI,
127 : nsIURI **result)
128 : {
129 0 : nsresult rv = NS_OK;
130 :
131 0 : RefPtr<nsJARURI> jarURI = new nsJARURI();
132 0 : if (!jarURI)
133 0 : return NS_ERROR_OUT_OF_MEMORY;
134 :
135 0 : rv = jarURI->Init(aCharset);
136 0 : NS_ENSURE_SUCCESS(rv, rv);
137 :
138 0 : rv = jarURI->SetSpecWithBase(aSpec, aBaseURI);
139 0 : if (NS_FAILED(rv))
140 0 : return rv;
141 :
142 0 : NS_ADDREF(*result = jarURI);
143 0 : return rv;
144 : }
145 :
146 : NS_IMETHODIMP
147 0 : nsJARProtocolHandler::NewChannel2(nsIURI* uri,
148 : nsILoadInfo* aLoadInfo,
149 : nsIChannel** result)
150 : {
151 0 : nsJARChannel *chan = new nsJARChannel();
152 0 : if (!chan)
153 0 : return NS_ERROR_OUT_OF_MEMORY;
154 0 : NS_ADDREF(chan);
155 :
156 0 : nsresult rv = chan->Init(uri);
157 0 : if (NS_FAILED(rv)) {
158 0 : NS_RELEASE(chan);
159 0 : return rv;
160 : }
161 :
162 : // set the loadInfo on the new channel
163 0 : rv = chan->SetLoadInfo(aLoadInfo);
164 0 : if (NS_FAILED(rv)) {
165 0 : NS_RELEASE(chan);
166 0 : return rv;
167 : }
168 :
169 0 : *result = chan;
170 0 : return NS_OK;
171 : }
172 :
173 : NS_IMETHODIMP
174 0 : nsJARProtocolHandler::NewChannel(nsIURI *uri, nsIChannel **result)
175 : {
176 0 : return NewChannel2(uri, nullptr, result);
177 : }
178 :
179 :
180 : NS_IMETHODIMP
181 0 : nsJARProtocolHandler::AllowPort(int32_t port, const char *scheme, bool *_retval)
182 : {
183 : // don't override anything.
184 0 : *_retval = false;
185 0 : return NS_OK;
186 : }
187 :
188 : ////////////////////////////////////////////////////////////////////////////////
|