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 3 // found in the LICENSE file. 4 5 package org.chromium.android_webview; 6 7 import android.content.res.Resources; 8 import android.util.SparseArray; 9 10 import org.chromium.base.CalledByNative; 11 import org.chromium.base.JNINamespace; 12 13 import java.io.IOException; 14 import java.io.InputStreamReader; 15 import java.lang.ref.SoftReference; 16 import java.util.NoSuchElementException; 17 import java.util.Scanner; 18 19 /** 20 * A class that defines a set of resource IDs and functionality to resolve 21 * those IDs to concrete resources. 22 */ 23 @JNINamespace("android_webview::AwResource") 24 public class AwResource { 25 // The following resource ID's must be initialized by the embedder. 26 27 // Raw resource ID for an HTML page to be displayed in the case of 28 // a specific load error. 29 private static int RAW_LOAD_ERROR; 30 31 // Raw resource ID for an HTML page to be displayed in the case of 32 // a generic load error. (It's called NO_DOMAIN for legacy reasons). 33 private static int RAW_NO_DOMAIN; 34 35 // Array resource ID for the configuration of platform specific key-systems. 36 private static int STRING_ARRAY_CONFIG_KEY_SYSTEM_UUID_MAPPING; 37 38 // The embedder should inject a Resources object that will be used 39 // to resolve Resource IDs into the actual resources. 40 private static Resources sResources; 41 42 // Loading some resources is expensive, so cache the results. 43 private static SparseArray<SoftReference<String>> sResourceCache; 44 45 private static final int TYPE_STRING = 0; 46 private static final int TYPE_RAW = 1; 47 setResources(Resources resources)48 public static void setResources(Resources resources) { 49 sResources = resources; 50 sResourceCache = new SparseArray<SoftReference<String>>(); 51 } 52 setErrorPageResources(int loaderror, int nodomain)53 public static void setErrorPageResources(int loaderror, int nodomain) { 54 RAW_LOAD_ERROR = loaderror; 55 RAW_NO_DOMAIN = nodomain; 56 } 57 setDefaultTextEncoding(int encoding)58 public static void setDefaultTextEncoding(int encoding) { 59 } 60 setConfigKeySystemUuidMapping(int config)61 public static void setConfigKeySystemUuidMapping(int config) { 62 STRING_ARRAY_CONFIG_KEY_SYSTEM_UUID_MAPPING = config; 63 } 64 65 @CalledByNative getDefaultTextEncoding()66 public static String getDefaultTextEncoding() { 67 return "UTF-8"; 68 } 69 70 @CalledByNative getNoDomainPageContent()71 public static String getNoDomainPageContent() { 72 return getResource(RAW_NO_DOMAIN, TYPE_RAW); 73 } 74 75 @CalledByNative getLoadErrorPageContent()76 public static String getLoadErrorPageContent() { 77 return getResource(RAW_LOAD_ERROR, TYPE_RAW); 78 } 79 getConfigKeySystemUuidMapping()80 public static String[] getConfigKeySystemUuidMapping() { 81 // No need to cache, since this should be called only once. 82 return sResources.getStringArray(STRING_ARRAY_CONFIG_KEY_SYSTEM_UUID_MAPPING); 83 } 84 getResource(int resid, int type)85 private static String getResource(int resid, int type) { 86 assert resid != 0; 87 assert sResources != null; 88 assert sResourceCache != null; 89 90 SoftReference<String> stringRef = sResourceCache.get(resid); 91 String result = stringRef == null ? null : stringRef.get(); 92 if (result == null) { 93 switch (type) { 94 case TYPE_STRING: 95 result = sResources.getString(resid); 96 break; 97 case TYPE_RAW: 98 result = getRawFileResourceContent(resid); 99 break; 100 default: 101 throw new IllegalArgumentException("Unknown resource type"); 102 } 103 104 sResourceCache.put(resid, new SoftReference<String>(result)); 105 } 106 return result; 107 } 108 getRawFileResourceContent(int resid)109 private static String getRawFileResourceContent(int resid) { 110 assert resid != 0; 111 assert sResources != null; 112 113 InputStreamReader isr = null; 114 String result = null; 115 116 try { 117 isr = new InputStreamReader( 118 sResources.openRawResource(resid)); 119 // \A tells the scanner to use the beginning of the input 120 // as the delimiter, hence causes it to read the entire text. 121 result = new Scanner(isr).useDelimiter("\\A").next(); 122 } catch (Resources.NotFoundException e) { 123 return ""; 124 } catch (NoSuchElementException e) { 125 return ""; 126 } finally { 127 try { 128 if (isr != null) { 129 isr.close(); 130 } 131 } catch (IOException e) { 132 // Nothing to do if close() fails. 133 } 134 } 135 return result; 136 } 137 } 138