OLD | NEW |
---|---|
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package org.chromium.content.browser; | 5 package org.chromium.content.browser; |
6 | 6 |
7 import android.content.Context; | 7 import android.content.Context; |
8 import android.content.SharedPreferences; | 8 import android.content.SharedPreferences; |
9 import android.content.pm.PackageInfo; | 9 import android.content.pm.PackageInfo; |
10 import android.content.pm.PackageManager; | 10 import android.content.pm.PackageManager; |
(...skipping 18 matching lines...) Expand all Loading... | |
29 | 29 |
30 /** | 30 /** |
31 * Handles extracting the necessary resources bundled in an APK and moving them to a location on | 31 * Handles extracting the necessary resources bundled in an APK and moving them to a location on |
32 * the file system accessible from the native code. | 32 * the file system accessible from the native code. |
33 */ | 33 */ |
34 public class ResourceExtractor { | 34 public class ResourceExtractor { |
35 | 35 |
36 private static final String LOGTAG = "ResourceExtractor"; | 36 private static final String LOGTAG = "ResourceExtractor"; |
37 private static final String LAST_LANGUAGE = "Last language"; | 37 private static final String LAST_LANGUAGE = "Last language"; |
38 private static final String PAK_FILENAMES = "Pak filenames"; | 38 private static final String PAK_FILENAMES = "Pak filenames"; |
39 private static final String ICU_DATA_FILENAME = "icudtl.dat"; | |
39 | 40 |
40 private static String[] sMandatoryPaks = null; | 41 private static String[] sMandatoryPaks = null; |
41 | 42 |
42 // By default, we attempt to extract a pak file for the users | 43 // By default, we attempt to extract a pak file for the users |
43 // current device locale. Use setExtractImplicitLocale() to | 44 // current device locale. Use setExtractImplicitLocale() to |
44 // change this behavior. | 45 // change this behavior. |
45 private static boolean sExtractImplicitLocalePak = true; | 46 private static boolean sExtractImplicitLocalePak = true; |
46 | 47 |
47 private class ExtractTask extends AsyncTask<Void, Void, Void> { | 48 private class ExtractTask extends AsyncTask<Void, Void, Void> { |
48 private static final int BUFFER_SIZE = 16 * 1024; | 49 private static final int BUFFER_SIZE = 16 * 1024; |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
89 } | 90 } |
90 | 91 |
91 if (sExtractImplicitLocalePak) { | 92 if (sExtractImplicitLocalePak) { |
92 if (p.length() > 0) p.append('|'); | 93 if (p.length() > 0) p.append('|'); |
93 // As well as the minimum required set of .paks above, we'll als o add all .paks that | 94 // As well as the minimum required set of .paks above, we'll als o add all .paks that |
94 // we have for the user's currently selected language. | 95 // we have for the user's currently selected language. |
95 | 96 |
96 p.append(currentLanguage); | 97 p.append(currentLanguage); |
97 p.append("(-\\w+)?\\.pak"); | 98 p.append("(-\\w+)?\\.pak"); |
98 } | 99 } |
100 | |
99 Pattern paksToInstall = Pattern.compile(p.toString()); | 101 Pattern paksToInstall = Pattern.compile(p.toString()); |
100 | 102 |
101 AssetManager manager = mContext.getResources().getAssets(); | 103 AssetManager manager = mContext.getResources().getAssets(); |
102 try { | 104 try { |
103 // Loop through every asset file that we have in the APK, and lo ok for the | 105 // Loop through every asset file that we have in the APK, and lo ok for the |
104 // ones that we need to extract by trying to match the Patterns that we | 106 // ones that we need to extract by trying to match the Patterns that we |
105 // created above. | 107 // created above. |
106 byte[] buffer = null; | 108 byte[] buffer = null; |
107 String[] files = manager.list(""); | 109 String[] files = manager.list(""); |
108 for (String file : files) { | 110 for (String file : files) { |
109 if (!paksToInstall.matcher(file).matches()) { | 111 if (!paksToInstall.matcher(file).matches()) { |
110 continue; | 112 continue; |
111 } | 113 } |
112 File output = new File(mOutputDir, file); | 114 boolean isICUData = file.equals(ICU_DATA_FILENAME); |
115 File output = new File(isICUData ? mAppDataDir : mOutputDir, file); | |
113 if (output.exists()) { | 116 if (output.exists()) { |
114 continue; | 117 continue; |
115 } | 118 } |
116 | 119 |
117 InputStream is = null; | 120 InputStream is = null; |
118 OutputStream os = null; | 121 OutputStream os = null; |
119 try { | 122 try { |
120 is = manager.open(file); | 123 is = manager.open(file); |
121 os = new FileOutputStream(output); | 124 os = new FileOutputStream(output); |
122 Log.i(LOGTAG, "Extracting resource " + file); | 125 Log.i(LOGTAG, "Extracting resource " + file); |
123 if (buffer == null) { | 126 if (buffer == null) { |
124 buffer = new byte[BUFFER_SIZE]; | 127 buffer = new byte[BUFFER_SIZE]; |
125 } | 128 } |
126 | 129 |
127 int count = 0; | 130 int count = 0; |
128 while ((count = is.read(buffer, 0, BUFFER_SIZE)) != -1) { | 131 while ((count = is.read(buffer, 0, BUFFER_SIZE)) != -1) { |
129 os.write(buffer, 0, count); | 132 os.write(buffer, 0, count); |
130 } | 133 } |
131 os.flush(); | 134 os.flush(); |
132 | 135 |
133 // Ensure something reasonable was written. | 136 // Ensure something reasonable was written. |
134 if (output.length() == 0) { | 137 if (output.length() == 0) { |
135 throw new IOException(file + " extracted with 0 leng th!"); | 138 throw new IOException(file + " extracted with 0 leng th!"); |
136 } | 139 } |
137 | 140 |
138 filenames.add(file); | 141 if (!isICUData) { |
142 filenames.add(file); | |
143 } else { | |
144 // icudata needs to be accessed by a renderer proces s. | |
145 output.setReadable(true, false); | |
146 } | |
139 } finally { | 147 } finally { |
140 try { | 148 try { |
141 if (is != null) { | 149 if (is != null) { |
142 is.close(); | 150 is.close(); |
143 } | 151 } |
144 } finally { | 152 } finally { |
145 if (os != null) { | 153 if (os != null) { |
146 os.close(); | 154 os.close(); |
147 } | 155 } |
148 } | 156 } |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
216 return expectedTimestamp; | 224 return expectedTimestamp; |
217 } | 225 } |
218 | 226 |
219 // timestamp file is already up-to date. | 227 // timestamp file is already up-to date. |
220 return null; | 228 return null; |
221 } | 229 } |
222 } | 230 } |
223 | 231 |
224 private final Context mContext; | 232 private final Context mContext; |
225 private ExtractTask mExtractTask; | 233 private ExtractTask mExtractTask; |
234 private final File mAppDataDir; | |
226 private final File mOutputDir; | 235 private final File mOutputDir; |
227 | 236 |
228 private static ResourceExtractor sInstance; | 237 private static ResourceExtractor sInstance; |
229 | 238 |
230 public static ResourceExtractor get(Context context) { | 239 public static ResourceExtractor get(Context context) { |
231 if (sInstance == null) { | 240 if (sInstance == null) { |
232 sInstance = new ResourceExtractor(context); | 241 sInstance = new ResourceExtractor(context); |
233 } | 242 } |
234 return sInstance; | 243 return sInstance; |
235 } | 244 } |
(...skipping 20 matching lines...) Expand all Loading... | |
256 * pak files specified in sMandatoryPaks. | 265 * pak files specified in sMandatoryPaks. |
257 */ | 266 */ |
258 public static void setExtractImplicitLocaleForTesting(boolean extract) { | 267 public static void setExtractImplicitLocaleForTesting(boolean extract) { |
259 assert (sInstance == null || sInstance.mExtractTask == null) | 268 assert (sInstance == null || sInstance.mExtractTask == null) |
260 : "Must be called before startExtractingResources is called"; | 269 : "Must be called before startExtractingResources is called"; |
261 sExtractImplicitLocalePak = extract; | 270 sExtractImplicitLocalePak = extract; |
262 } | 271 } |
263 | 272 |
264 private ResourceExtractor(Context context) { | 273 private ResourceExtractor(Context context) { |
265 mContext = context; | 274 mContext = context; |
275 mAppDataDir = getAppDataDirFromContext(mContext); | |
266 mOutputDir = getOutputDirFromContext(mContext); | 276 mOutputDir = getOutputDirFromContext(mContext); |
267 } | 277 } |
268 | 278 |
269 public void waitForCompletion() { | 279 public void waitForCompletion() { |
270 if (shouldSkipPakExtraction()) { | 280 if (shouldSkipPakExtraction()) { |
271 return; | 281 return; |
272 } | 282 } |
273 | 283 |
274 assert mExtractTask != null; | 284 assert mExtractTask != null; |
275 | 285 |
(...skipping 20 matching lines...) Expand all Loading... | |
296 } | 306 } |
297 | 307 |
298 if (shouldSkipPakExtraction()) { | 308 if (shouldSkipPakExtraction()) { |
299 return; | 309 return; |
300 } | 310 } |
301 | 311 |
302 mExtractTask = new ExtractTask(); | 312 mExtractTask = new ExtractTask(); |
303 mExtractTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); | 313 mExtractTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); |
304 } | 314 } |
305 | 315 |
316 public static File getAppDataDirFromContext(Context context) { | |
317 return new File(PathUtils.getDataDirectory(context.getApplicationContext ())); | |
318 } | |
319 | |
306 public static File getOutputDirFromContext(Context context) { | 320 public static File getOutputDirFromContext(Context context) { |
307 return new File(PathUtils.getDataDirectory(context.getApplicationContext ()), "paks"); | 321 return new File(getAppDataDirFromContext(context), "paks"); |
308 } | 322 } |
309 | 323 |
310 public static void deleteFiles(Context context) { | 324 public static void deleteFiles(Context context) { |
325 File icudata = new File(getAppDataDirFromContext(context), ICU_DATA_FILE NAME); | |
326 if (icudata.exists() && !icudata.delete()) { | |
327 Log.w(LOGTAG, "Unable to remove the icudata " + icudata.getName()); | |
Andrew Hayden (chromium.org)
2014/02/21 08:49:39
This is worse than a warning. If we fail to update
benm (inactive)
2014/02/21 13:55:42
It's a fair point, but I don't think it's any diff
jungshik at Google
2014/02/21 21:50:49
What Andrew worries about would not happen often (
| |
328 } | |
311 File dir = getOutputDirFromContext(context); | 329 File dir = getOutputDirFromContext(context); |
312 if (dir.exists()) { | 330 if (dir.exists()) { |
313 File[] files = dir.listFiles(); | 331 File[] files = dir.listFiles(); |
314 for (File file : files) { | 332 for (File file : files) { |
315 if (!file.delete()) { | 333 if (!file.delete()) { |
316 Log.w(LOGTAG, "Unable to remove existing resource " + file.g etName()); | 334 Log.w(LOGTAG, "Unable to remove existing resource " + file.g etName()); |
317 } | 335 } |
318 } | 336 } |
319 } | 337 } |
320 } | 338 } |
321 | 339 |
322 /** | 340 /** |
323 * Pak extraction not necessarily required by the embedder; we allow them to skip | 341 * Pak extraction not necessarily required by the embedder; we allow them to skip |
324 * this process if they call setMandatoryPaksToExtract with a single empty S tring. | 342 * this process if they call setMandatoryPaksToExtract with a single empty S tring. |
325 */ | 343 */ |
326 private static boolean shouldSkipPakExtraction() { | 344 private static boolean shouldSkipPakExtraction() { |
327 // Must call setMandatoryPaksToExtract before beginning resource extract ion. | 345 // Must call setMandatoryPaksToExtract before beginning resource extract ion. |
328 assert sMandatoryPaks != null; | 346 assert sMandatoryPaks != null; |
329 return sMandatoryPaks.length == 1 && "".equals(sMandatoryPaks[0]); | 347 return sMandatoryPaks.length == 1 && "".equals(sMandatoryPaks[0]); |
330 } | 348 } |
331 } | 349 } |
OLD | NEW |