blob: 35483c988ea9276ea91c9c5a1ac5c5f52d34d695 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.webkit;
18
Elliott Hughes0f1169612010-08-02 13:37:48 -070019import android.text.TextUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020import java.util.HashMap;
21import java.util.regex.Pattern;
Elliott Hughes0f1169612010-08-02 13:37:48 -070022import libcore.net.MimeUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080023
24/**
25 * Two-way map that maps MIME-types to file extensions and vice versa.
Elliott Hughes0f1169612010-08-02 13:37:48 -070026 *
27 * <p>See also {@link java.net.URLConnection#guessContentTypeFromName}
28 * and {@link java.net.URLConnection#guessContentTypeFromStream}. This
29 * class and {@code URLConnection} share the same MIME-type database.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030 */
Patrick Scott9f617322009-07-21 13:39:45 -040031public class MimeTypeMap {
Elliott Hughes0f1169612010-08-02 13:37:48 -070032 private static final MimeTypeMap sMimeTypeMap = new MimeTypeMap();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080033
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080034 private MimeTypeMap() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035 }
36
37 /**
38 * Returns the file extension or an empty string iff there is no
Patrick Scott9f617322009-07-21 13:39:45 -040039 * extension. This method is a convenience method for obtaining the
40 * extension of a url and has undefined results for other Strings.
41 * @param url
42 * @return The file extension of the given url.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080043 */
44 public static String getFileExtensionFromUrl(String url) {
Elliott Hughes0f1169612010-08-02 13:37:48 -070045 if (!TextUtils.isEmpty(url)) {
Ben Murdoch18700152010-12-14 16:36:03 +000046 int fragment = url.lastIndexOf('#');
47 if (fragment > 0) {
48 url = url.substring(0, fragment);
49 }
50
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080051 int query = url.lastIndexOf('?');
52 if (query > 0) {
53 url = url.substring(0, query);
54 }
Ben Murdoch18700152010-12-14 16:36:03 +000055
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080056 int filenamePos = url.lastIndexOf('/');
57 String filename =
58 0 <= filenamePos ? url.substring(filenamePos + 1) : url;
59
60 // if the filename contains special characters, we don't
61 // consider it valid for our matching purposes:
Elliott Hughes0f1169612010-08-02 13:37:48 -070062 if (!filename.isEmpty() &&
Melanie Clementsf19670a2010-05-01 22:48:20 -040063 Pattern.matches("[a-zA-Z_0-9\\.\\-\\(\\)\\%]+", filename)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080064 int dotPos = filename.lastIndexOf('.');
65 if (0 <= dotPos) {
66 return filename.substring(dotPos + 1);
67 }
68 }
69 }
70
71 return "";
72 }
73
74 /**
Patrick Scott9f617322009-07-21 13:39:45 -040075 * Return true if the given MIME type has an entry in the map.
76 * @param mimeType A MIME type (i.e. text/plain)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080077 * @return True iff there is a mimeType entry in the map.
78 */
79 public boolean hasMimeType(String mimeType) {
Elliott Hughes0f1169612010-08-02 13:37:48 -070080 return MimeUtils.hasMimeType(mimeType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080081 }
82
83 /**
Patrick Scott9f617322009-07-21 13:39:45 -040084 * Return the MIME type for the given extension.
85 * @param extension A file extension without the leading '.'
86 * @return The MIME type for the given extension or null iff there is none.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080087 */
88 public String getMimeTypeFromExtension(String extension) {
Elliott Hughes0f1169612010-08-02 13:37:48 -070089 return MimeUtils.guessMimeTypeFromExtension(extension);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080090 }
91
Patrick Scott021b7b42010-01-13 14:12:43 -050092 // Static method called by jni.
93 private static String mimeTypeFromExtension(String extension) {
Elliott Hughes0f1169612010-08-02 13:37:48 -070094 return MimeUtils.guessMimeTypeFromExtension(extension);
Patrick Scott021b7b42010-01-13 14:12:43 -050095 }
96
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097 /**
Patrick Scott9f617322009-07-21 13:39:45 -040098 * Return true if the given extension has a registered MIME type.
99 * @param extension A file extension without the leading '.'
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800100 * @return True iff there is an extension entry in the map.
101 */
102 public boolean hasExtension(String extension) {
Elliott Hughes0f1169612010-08-02 13:37:48 -0700103 return MimeUtils.hasExtension(extension);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800104 }
105
106 /**
Patrick Scott9f617322009-07-21 13:39:45 -0400107 * Return the registered extension for the given MIME type. Note that some
108 * MIME types map to multiple extensions. This call will return the most
109 * common extension for the given MIME type.
110 * @param mimeType A MIME type (i.e. text/plain)
111 * @return The extension for the given MIME type or null iff there is none.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800112 */
113 public String getExtensionFromMimeType(String mimeType) {
Elliott Hughes0f1169612010-08-02 13:37:48 -0700114 return MimeUtils.guessExtensionFromMimeType(mimeType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800115 }
116
117 /**
Iain Merrickd77f9b72010-10-18 18:22:25 +0100118 * If the given MIME type is null, or one of the "generic" types (text/plain
119 * or application/octet-stream) map it to a type that Android can deal with.
120 * If the given type is not generic, return it unchanged.
121 *
122 * @param mimeType MIME type provided by the server.
123 * @param url URL of the data being loaded.
124 * @param contentDisposition Content-disposition header given by the server.
125 * @return The MIME type that should be used for this data.
126 */
127 /* package */ String remapGenericMimeType(String mimeType, String url,
128 String contentDisposition) {
129 // If we have one of "generic" MIME types, try to deduce
130 // the right MIME type from the file extension (if any):
131 if ("text/plain".equals(mimeType) ||
132 "application/octet-stream".equals(mimeType)) {
133
134 // for attachment, use the filename in the Content-Disposition
135 // to guess the mimetype
136 String filename = null;
137 if (contentDisposition != null) {
138 filename = URLUtil.parseContentDisposition(contentDisposition);
139 }
140 if (filename != null) {
141 url = filename;
142 }
143 String extension = getFileExtensionFromUrl(url);
144 String newMimeType = getMimeTypeFromExtension(extension);
145 if (newMimeType != null) {
146 mimeType = newMimeType;
147 }
148 } else if ("text/vnd.wap.wml".equals(mimeType)) {
149 // As we don't support wml, render it as plain text
150 mimeType = "text/plain";
151 } else {
152 // It seems that xhtml+xml and vnd.wap.xhtml+xml mime
153 // subtypes are used interchangeably. So treat them the same.
154 if ("application/vnd.wap.xhtml+xml".equals(mimeType)) {
155 mimeType = "application/xhtml+xml";
156 }
157 }
158 return mimeType;
159 }
160
161 /**
Patrick Scott9f617322009-07-21 13:39:45 -0400162 * Get the singleton instance of MimeTypeMap.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800163 * @return The singleton instance of the MIME-type map.
164 */
165 public static MimeTypeMap getSingleton() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800166 return sMimeTypeMap;
167 }
168}