Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* -*- Mode: c++; c-basic-offset: 2; tab-width: 20; indent-tabs-mode: nil; -*-
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 #include "nsMIMEInfoAndroid.h"
6 #include "AndroidBridge.h"
7 #include "nsAndroidHandlerApp.h"
8 #include "nsArrayUtils.h"
9 #include "nsISupportsUtils.h"
10 #include "nsStringEnumerator.h"
11 #include "nsNetUtil.h"
13 using namespace mozilla::widget::android;
15 NS_IMPL_ISUPPORTS(nsMIMEInfoAndroid, nsIMIMEInfo, nsIHandlerInfo)
17 NS_IMETHODIMP
18 nsMIMEInfoAndroid::LaunchDefaultWithFile(nsIFile* aFile)
19 {
20 return LaunchWithFile(aFile);
21 }
23 NS_IMETHODIMP
24 nsMIMEInfoAndroid::LoadUriInternal(nsIURI * aURI)
25 {
26 nsCString uriSpec;
27 aURI->GetSpec(uriSpec);
29 nsCString uriScheme;
30 aURI->GetScheme(uriScheme);
32 nsAutoString mimeType;
33 if (mType.Equals(uriScheme) || mType.Equals(uriSpec)) {
34 mimeType = EmptyString();
35 } else {
36 mimeType = NS_ConvertUTF8toUTF16(mType);
37 }
39 if (GeckoAppShell::OpenUriExternal(NS_ConvertUTF8toUTF16(uriSpec), mimeType)) {
40 return NS_OK;
41 }
42 return NS_ERROR_FAILURE;
43 }
45 bool
46 nsMIMEInfoAndroid::GetMimeInfoForMimeType(const nsACString& aMimeType,
47 nsMIMEInfoAndroid** aMimeInfo)
48 {
49 nsRefPtr<nsMIMEInfoAndroid> info = new nsMIMEInfoAndroid(aMimeType);
50 mozilla::AndroidBridge* bridge = mozilla::AndroidBridge::Bridge();
51 // we don't have access to the bridge, so just assume we can handle
52 // the mime type for now and let the system deal with it
53 if (!bridge){
54 info.forget(aMimeInfo);
55 return false;
56 }
58 nsIHandlerApp* systemDefault = nullptr;
60 if (!IsUTF8(aMimeType, true))
61 return false;
63 NS_ConvertUTF8toUTF16 mimeType(aMimeType);
65 bridge->GetHandlersForMimeType(mimeType,
66 info->mHandlerApps, &systemDefault);
68 if (systemDefault)
69 info->mPrefApp = systemDefault;
71 nsAutoCString fileExt;
72 bridge->GetExtensionFromMimeType(aMimeType, fileExt);
73 info->SetPrimaryExtension(fileExt);
75 uint32_t len;
76 info->mHandlerApps->GetLength(&len);
77 if (len == 1) {
78 info.forget(aMimeInfo);
79 return false;
80 }
82 info.forget(aMimeInfo);
83 return true;
84 }
86 bool
87 nsMIMEInfoAndroid::GetMimeInfoForFileExt(const nsACString& aFileExt,
88 nsMIMEInfoAndroid **aMimeInfo)
89 {
90 nsCString mimeType;
91 if (mozilla::AndroidBridge::Bridge())
92 mozilla::AndroidBridge::Bridge()->
93 GetMimeTypeFromExtensions(aFileExt, mimeType);
95 // "*/*" means that the bridge didn't know.
96 if (mimeType.Equals(nsDependentCString("*/*"), nsCaseInsensitiveCStringComparator()))
97 return false;
99 bool found = GetMimeInfoForMimeType(mimeType, aMimeInfo);
100 (*aMimeInfo)->SetPrimaryExtension(aFileExt);
101 return found;
102 }
104 /**
105 * Returns MIME info for the aURL, which may contain the whole URL or only a protocol
106 */
107 nsresult
108 nsMIMEInfoAndroid::GetMimeInfoForURL(const nsACString &aURL,
109 bool *found,
110 nsIHandlerInfo **info)
111 {
112 nsMIMEInfoAndroid *mimeinfo = new nsMIMEInfoAndroid(aURL);
113 NS_ADDREF(*info = mimeinfo);
114 *found = true;
116 mozilla::AndroidBridge* bridge = mozilla::AndroidBridge::Bridge();
117 if (!bridge) {
118 // we don't have access to the bridge, so just assume we can handle
119 // the protocol for now and let the system deal with it
120 return NS_OK;
121 }
123 nsIHandlerApp* systemDefault = nullptr;
124 bridge->GetHandlersForURL(NS_ConvertUTF8toUTF16(aURL),
125 mimeinfo->mHandlerApps, &systemDefault);
127 if (systemDefault)
128 mimeinfo->mPrefApp = systemDefault;
131 nsAutoCString fileExt;
132 nsAutoCString mimeType;
133 mimeinfo->GetType(mimeType);
134 bridge->GetExtensionFromMimeType(mimeType, fileExt);
135 mimeinfo->SetPrimaryExtension(fileExt);
137 uint32_t len;
138 mimeinfo->mHandlerApps->GetLength(&len);
139 if (len == 1) {
140 // Code that calls this requires an object regardless if the OS has
141 // something for us, so we return the empty object.
142 *found = false;
143 return NS_OK;
144 }
146 return NS_OK;
147 }
149 NS_IMETHODIMP
150 nsMIMEInfoAndroid::GetType(nsACString& aType)
151 {
152 aType.Assign(mType);
153 return NS_OK;
154 }
156 NS_IMETHODIMP
157 nsMIMEInfoAndroid::GetDescription(nsAString& aDesc)
158 {
159 aDesc.Assign(mDescription);
160 return NS_OK;
161 }
163 NS_IMETHODIMP
164 nsMIMEInfoAndroid::SetDescription(const nsAString& aDesc)
165 {
166 mDescription.Assign(aDesc);
167 return NS_OK;
168 }
170 NS_IMETHODIMP
171 nsMIMEInfoAndroid::GetPreferredApplicationHandler(nsIHandlerApp** aApp)
172 {
173 *aApp = mPrefApp;
174 NS_IF_ADDREF(*aApp);
175 return NS_OK;
176 }
178 NS_IMETHODIMP
179 nsMIMEInfoAndroid::SetPreferredApplicationHandler(nsIHandlerApp* aApp)
180 {
181 mPrefApp = aApp;
182 return NS_OK;
183 }
185 NS_IMETHODIMP
186 nsMIMEInfoAndroid::GetPossibleApplicationHandlers(nsIMutableArray **aHandlerApps)
187 {
188 if (!mHandlerApps)
189 mHandlerApps = do_CreateInstance(NS_ARRAY_CONTRACTID);
191 if (!mHandlerApps)
192 return NS_ERROR_OUT_OF_MEMORY;
194 *aHandlerApps = mHandlerApps;
195 NS_IF_ADDREF(*aHandlerApps);
196 return NS_OK;
197 }
199 NS_IMETHODIMP
200 nsMIMEInfoAndroid::GetHasDefaultHandler(bool* aHasDefault)
201 {
202 uint32_t len;
203 *aHasDefault = false;
204 if (!mHandlerApps)
205 return NS_OK;
207 if (NS_FAILED(mHandlerApps->GetLength(&len)))
208 return NS_OK;
210 if (len == 0)
211 return NS_OK;
213 *aHasDefault = true;
214 return NS_OK;
215 }
217 NS_IMETHODIMP
218 nsMIMEInfoAndroid::GetDefaultDescription(nsAString& aDesc)
219 {
220 aDesc.Assign(EmptyString());
221 return NS_OK;
222 }
224 NS_IMETHODIMP
225 nsMIMEInfoAndroid::LaunchWithURI(nsIURI* aURI, nsIInterfaceRequestor* req)
226 {
227 return mPrefApp->LaunchWithURI(aURI, req);
228 }
230 NS_IMETHODIMP
231 nsMIMEInfoAndroid::GetPreferredAction(nsHandlerInfoAction* aPrefAction)
232 {
233 *aPrefAction = mPrefAction;
234 return NS_OK;
235 }
237 NS_IMETHODIMP
238 nsMIMEInfoAndroid::SetPreferredAction(nsHandlerInfoAction aPrefAction)
239 {
240 mPrefAction = aPrefAction;
241 return NS_OK;
242 }
244 NS_IMETHODIMP
245 nsMIMEInfoAndroid::GetAlwaysAskBeforeHandling(bool* aAlwaysAsk)
246 {
247 *aAlwaysAsk = mAlwaysAsk;
248 return NS_OK;
249 }
251 NS_IMETHODIMP
252 nsMIMEInfoAndroid::SetAlwaysAskBeforeHandling(bool aAlwaysAsk)
253 {
254 mAlwaysAsk = aAlwaysAsk;
255 return NS_OK;
256 }
258 NS_IMETHODIMP
259 nsMIMEInfoAndroid::GetFileExtensions(nsIUTF8StringEnumerator** aResult)
260 {
261 return NS_NewUTF8StringEnumerator(aResult, &mExtensions, this);
262 }
264 NS_IMETHODIMP
265 nsMIMEInfoAndroid::SetFileExtensions(const nsACString & aExtensions)
266 {
267 mExtensions.Clear();
268 nsCString extList(aExtensions);
270 int32_t breakLocation = -1;
271 while ( (breakLocation = extList.FindChar(',')) != -1)
272 {
273 mExtensions.AppendElement(Substring(extList.get(), extList.get() + breakLocation));
274 extList.Cut(0, breakLocation + 1);
275 }
276 if (!extList.IsEmpty())
277 mExtensions.AppendElement(extList);
278 return NS_OK;
279 }
281 NS_IMETHODIMP
282 nsMIMEInfoAndroid::ExtensionExists(const nsACString & aExtension, bool *aRetVal)
283 {
284 NS_ASSERTION(!aExtension.IsEmpty(), "no extension");
286 nsCString mimeType;
287 if (mozilla::AndroidBridge::Bridge()) {
288 mozilla::AndroidBridge::Bridge()->
289 GetMimeTypeFromExtensions(aExtension, mimeType);
290 }
292 // "*/*" means the bridge didn't find anything (i.e., extension doesn't exist).
293 *aRetVal = !mimeType.Equals(nsDependentCString("*/*"), nsCaseInsensitiveCStringComparator());
294 return NS_OK;
295 }
297 NS_IMETHODIMP
298 nsMIMEInfoAndroid::AppendExtension(const nsACString & aExtension)
299 {
300 mExtensions.AppendElement(aExtension);
301 return NS_OK;
302 }
304 NS_IMETHODIMP
305 nsMIMEInfoAndroid::GetPrimaryExtension(nsACString & aPrimaryExtension)
306 {
307 if (!mExtensions.Length())
308 return NS_ERROR_NOT_INITIALIZED;
310 aPrimaryExtension = mExtensions[0];
311 return NS_OK;
312 }
314 NS_IMETHODIMP
315 nsMIMEInfoAndroid::SetPrimaryExtension(const nsACString & aExtension)
316 {
317 uint32_t extCount = mExtensions.Length();
318 uint8_t i;
319 bool found = false;
320 for (i=0; i < extCount; i++) {
321 const nsCString& ext = mExtensions[i];
322 if (ext.Equals(aExtension, nsCaseInsensitiveCStringComparator())) {
323 found = true;
324 break;
325 }
326 }
327 if (found) {
328 mExtensions.RemoveElementAt(i);
329 }
331 mExtensions.InsertElementAt(0, aExtension);
333 return NS_OK;
334 }
336 NS_IMETHODIMP
337 nsMIMEInfoAndroid::GetMIMEType(nsACString & aMIMEType)
338 {
339 aMIMEType.Assign(mType);
340 return NS_OK;
341 }
343 NS_IMETHODIMP
344 nsMIMEInfoAndroid::Equals(nsIMIMEInfo *aMIMEInfo, bool *aRetVal)
345 {
346 if (!aMIMEInfo) return NS_ERROR_NULL_POINTER;
348 nsAutoCString type;
349 nsresult rv = aMIMEInfo->GetMIMEType(type);
350 if (NS_FAILED(rv)) return rv;
352 *aRetVal = mType.Equals(type);
354 return NS_OK;
355 }
357 NS_IMETHODIMP
358 nsMIMEInfoAndroid::GetPossibleLocalHandlers(nsIArray * *aPossibleLocalHandlers)
359 {
360 return NS_ERROR_NOT_IMPLEMENTED;
361 }
363 NS_IMETHODIMP
364 nsMIMEInfoAndroid::LaunchWithFile(nsIFile *aFile)
365 {
366 nsCOMPtr<nsIURI> uri;
367 NS_NewFileURI(getter_AddRefs(uri), aFile);
368 return LoadUriInternal(uri);
369 }
371 nsMIMEInfoAndroid::nsMIMEInfoAndroid(const nsACString& aMIMEType) :
372 mType(aMIMEType), mAlwaysAsk(true),
373 mPrefAction(nsIMIMEInfo::useHelperApp)
374 {
375 mPrefApp = new nsMIMEInfoAndroid::SystemChooser(this);
376 nsresult rv;
377 mHandlerApps = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
378 mHandlerApps->AppendElement(mPrefApp, false);
379 }
381 NS_IMPL_ISUPPORTS(nsMIMEInfoAndroid::SystemChooser, nsIHandlerApp)
384 nsresult nsMIMEInfoAndroid::SystemChooser::GetName(nsAString & aName) {
385 aName.Assign(NS_LITERAL_STRING("Android chooser"));
386 return NS_OK;
387 }
389 nsresult
390 nsMIMEInfoAndroid::SystemChooser::SetName(const nsAString&) {
391 return NS_OK;
392 }
394 nsresult
395 nsMIMEInfoAndroid::SystemChooser::GetDetailedDescription(nsAString & aDesc) {
396 aDesc.Assign(NS_LITERAL_STRING("Android's default handler application chooser"));
397 return NS_OK;
398 }
400 nsresult
401 nsMIMEInfoAndroid::SystemChooser::SetDetailedDescription(const nsAString&) {
402 return NS_OK;
403 }
405 nsresult
406 nsMIMEInfoAndroid::SystemChooser::Equals(nsIHandlerApp *aHandlerApp, bool *aRetVal) {
407 nsCOMPtr<nsMIMEInfoAndroid::SystemChooser> info = do_QueryInterface(aHandlerApp);
408 if (info)
409 return mOuter->Equals(info->mOuter, aRetVal);
410 *aRetVal = false;
411 return NS_OK;
412 }
414 nsresult
415 nsMIMEInfoAndroid::SystemChooser::LaunchWithURI(nsIURI* aURI, nsIInterfaceRequestor*)
416 {
417 return mOuter->LoadUriInternal(aURI);
418 }