Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(355)

Side by Side Diff: content/public/android/java/src/org/chromium/content/browser/ResourceExtractor.java

Issue 156333002: Enable icu_use_data_file_flag on Android (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: tab removed. log removed Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/chrome_android_paks.gypi ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
101 if (p.length() > 0) p.append('|');
102 p.append(ICU_DATA_FILENAME);
103
99 Pattern paksToInstall = Pattern.compile(p.toString()); 104 Pattern paksToInstall = Pattern.compile(p.toString());
100 105
101 AssetManager manager = mContext.getResources().getAssets(); 106 AssetManager manager = mContext.getResources().getAssets();
102 try { 107 try {
103 // Loop through every asset file that we have in the APK, and lo ok for the 108 // 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 109 // ones that we need to extract by trying to match the Patterns that we
105 // created above. 110 // created above.
106 byte[] buffer = null; 111 byte[] buffer = null;
107 String[] files = manager.list(""); 112 String[] files = manager.list("");
108 for (String file : files) { 113 for (String file : files) {
109 if (!paksToInstall.matcher(file).matches()) { 114 if (!paksToInstall.matcher(file).matches()) {
110 continue; 115 continue;
111 } 116 }
112 File output = new File(mOutputDir, file); 117 boolean isICUData = file.equals(ICU_DATA_FILENAME);
118 File output = new File(isICUData ? mAppDataDir : mOutputDir, file);
113 if (output.exists()) { 119 if (output.exists()) {
114 continue; 120 continue;
115 } 121 }
116 122
117 InputStream is = null; 123 InputStream is = null;
118 OutputStream os = null; 124 OutputStream os = null;
119 try { 125 try {
120 is = manager.open(file); 126 is = manager.open(file);
121 os = new FileOutputStream(output); 127 os = new FileOutputStream(output);
122 Log.i(LOGTAG, "Extracting resource " + file); 128 Log.i(LOGTAG, "Extracting resource " + file);
123 if (buffer == null) { 129 if (buffer == null) {
124 buffer = new byte[BUFFER_SIZE]; 130 buffer = new byte[BUFFER_SIZE];
125 } 131 }
126 132
127 int count = 0; 133 int count = 0;
128 while ((count = is.read(buffer, 0, BUFFER_SIZE)) != -1) { 134 while ((count = is.read(buffer, 0, BUFFER_SIZE)) != -1) {
129 os.write(buffer, 0, count); 135 os.write(buffer, 0, count);
130 } 136 }
131 os.flush(); 137 os.flush();
132 138
133 // Ensure something reasonable was written. 139 // Ensure something reasonable was written.
134 if (output.length() == 0) { 140 if (output.length() == 0) {
135 throw new IOException(file + " extracted with 0 leng th!"); 141 throw new IOException(file + " extracted with 0 leng th!");
136 } 142 }
137 143
138 filenames.add(file); 144 if (!isICUData) {
145 filenames.add(file);
146 } else {
147 // icudata needs to be accessed by a renderer proces s.
148 output.setReadable(true, false);
149 }
139 } finally { 150 } finally {
140 try { 151 try {
141 if (is != null) { 152 if (is != null) {
142 is.close(); 153 is.close();
143 } 154 }
144 } finally { 155 } finally {
145 if (os != null) { 156 if (os != null) {
146 os.close(); 157 os.close();
147 } 158 }
148 } 159 }
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
216 return expectedTimestamp; 227 return expectedTimestamp;
217 } 228 }
218 229
219 // timestamp file is already up-to date. 230 // timestamp file is already up-to date.
220 return null; 231 return null;
221 } 232 }
222 } 233 }
223 234
224 private final Context mContext; 235 private final Context mContext;
225 private ExtractTask mExtractTask; 236 private ExtractTask mExtractTask;
237 private final File mAppDataDir;
226 private final File mOutputDir; 238 private final File mOutputDir;
227 239
228 private static ResourceExtractor sInstance; 240 private static ResourceExtractor sInstance;
229 241
230 public static ResourceExtractor get(Context context) { 242 public static ResourceExtractor get(Context context) {
231 if (sInstance == null) { 243 if (sInstance == null) {
232 sInstance = new ResourceExtractor(context); 244 sInstance = new ResourceExtractor(context);
233 } 245 }
234 return sInstance; 246 return sInstance;
235 } 247 }
(...skipping 20 matching lines...) Expand all
256 * pak files specified in sMandatoryPaks. 268 * pak files specified in sMandatoryPaks.
257 */ 269 */
258 public static void setExtractImplicitLocaleForTesting(boolean extract) { 270 public static void setExtractImplicitLocaleForTesting(boolean extract) {
259 assert (sInstance == null || sInstance.mExtractTask == null) 271 assert (sInstance == null || sInstance.mExtractTask == null)
260 : "Must be called before startExtractingResources is called"; 272 : "Must be called before startExtractingResources is called";
261 sExtractImplicitLocalePak = extract; 273 sExtractImplicitLocalePak = extract;
262 } 274 }
263 275
264 private ResourceExtractor(Context context) { 276 private ResourceExtractor(Context context) {
265 mContext = context; 277 mContext = context;
278 mAppDataDir = getAppDataDirFromContext(mContext);
266 mOutputDir = getOutputDirFromContext(mContext); 279 mOutputDir = getOutputDirFromContext(mContext);
267 } 280 }
268 281
269 public void waitForCompletion() { 282 public void waitForCompletion() {
270 if (shouldSkipPakExtraction()) { 283 if (shouldSkipExtraction()) {
271 return; 284 return;
272 } 285 }
273 286
274 assert mExtractTask != null; 287 assert mExtractTask != null;
275 288
276 try { 289 try {
277 mExtractTask.get(); 290 mExtractTask.get();
278 } catch (CancellationException e) { 291 } catch (CancellationException e) {
279 // Don't leave the files in an inconsistent state. 292 // Don't leave the files in an inconsistent state.
280 deleteFiles(mContext); 293 deleteFiles(mContext);
281 } catch (ExecutionException e2) { 294 } catch (ExecutionException e2) {
282 deleteFiles(mContext); 295 deleteFiles(mContext);
283 } catch (InterruptedException e3) { 296 } catch (InterruptedException e3) {
284 deleteFiles(mContext); 297 deleteFiles(mContext);
285 } 298 }
286 } 299 }
287 300
288 /** 301 /**
289 * This will extract the application pak resources in an 302 * This will extract the application pak resources in an
290 * AsyncTask. Call waitForCompletion() at the point resources 303 * AsyncTask. Call waitForCompletion() at the point resources
291 * are needed to block until the task completes. 304 * are needed to block until the task completes.
292 */ 305 */
293 public void startExtractingResources() { 306 public void startExtractingResources() {
294 if (mExtractTask != null) { 307 if (mExtractTask != null) {
295 return; 308 return;
296 } 309 }
297 310
298 if (shouldSkipPakExtraction()) { 311 if (shouldSkipExtraction()) {
299 return; 312 return;
300 } 313 }
301 314
302 mExtractTask = new ExtractTask(); 315 mExtractTask = new ExtractTask();
303 mExtractTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 316 mExtractTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
304 } 317 }
305 318
319 public static File getAppDataDirFromContext(Context context) {
320 return new File(PathUtils.getDataDirectory(context.getApplicationContext ()));
321 }
306 public static File getOutputDirFromContext(Context context) { 322 public static File getOutputDirFromContext(Context context) {
307 return new File(PathUtils.getDataDirectory(context.getApplicationContext ()), "paks"); 323 return new File(getAppDataDirFromContext(context), "paks");
308 } 324 }
309 325
310 public static void deleteFiles(Context context) { 326 public static void deleteFiles(Context context) {
327 File icudata = new File(getAppDataDirFromContext(context), ICU_DATA_FILE NAME);
328 if (icudata.exists() && !icudata.delete()) {
329 Log.w(LOGTAG, "Unable to remove the icudata " + icudata.getName());
330 }
311 File dir = getOutputDirFromContext(context); 331 File dir = getOutputDirFromContext(context);
312 if (dir.exists()) { 332 if (dir.exists()) {
313 File[] files = dir.listFiles(); 333 File[] files = dir.listFiles();
314 for (File file : files) { 334 for (File file : files) {
315 if (!file.delete()) { 335 if (!file.delete()) {
316 Log.w(LOGTAG, "Unable to remove existing resource " + file.g etName()); 336 Log.w(LOGTAG, "Unable to remove existing resource " + file.g etName());
317 } 337 }
318 } 338 }
319 } 339 }
320 } 340 }
321 341
322 /** 342 /**
323 * Pak extraction not necessarily required by the embedder; we allow them to skip 343 * 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. 344 * this process if they call setMandatoryPaksToExtract with a single empty S tring and the
345 * icudata is absent. icudtl.dat will be present only when icu_use_data_file _flag == 1, which is
346 * false for the WebView build.
benm (inactive) 2014/02/10 21:30:45 i think that if an app using WebView had bundled a
jungshik at Google 2014/02/10 22:10:31 Although that's not likely, I agree that we'd bett
benm (inactive) 2014/02/10 22:28:32 I think that the other use will only happen in the
jungshik at Google 2014/02/10 23:41:46 That's what I expect us to do, but my reading of t
325 */ 347 */
348 private boolean shouldSkipExtraction() {
349 AssetManager manager = mContext.getResources().getAssets();
350 String[] files = null;
351 try {
352 files = manager.list(ICU_DATA_FILENAME);
353 } catch (IOException e) {
354 Log.w(LOGTAG, ICU_DATA_FILENAME + " is not found.");
355 }
356 return (files == null) && shouldSkipPakExtraction();
357 }
358
326 private static boolean shouldSkipPakExtraction() { 359 private static boolean shouldSkipPakExtraction() {
327 // Must call setMandatoryPaksToExtract before beginning resource extract ion. 360 // Must call setMandatoryPaksToExtract before beginning resource extract ion.
328 assert sMandatoryPaks != null; 361 assert sMandatoryPaks != null;
329 return sMandatoryPaks.length == 1 && "".equals(sMandatoryPaks[0]); 362 return sMandatoryPaks.length == 1 && "".equals(sMandatoryPaks[0]);
330 } 363 }
331 } 364 }
OLDNEW
« no previous file with comments | « chrome/chrome_android_paks.gypi ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698