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 5package org.chromium.android_webview; 6 7import android.content.res.Resources; 8import android.util.SparseArray; 9 10import org.chromium.base.CalledByNative; 11import org.chromium.base.JNINamespace; 12 13import java.io.IOException; 14import java.io.InputStreamReader; 15import java.lang.ref.SoftReference; 16import java.util.NoSuchElementException; 17import 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") 24public 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 sRawLoadError; 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 sRawNoDomain; 34 35 // Array resource ID for the configuration of platform specific key-systems. 36 private static int sStringArrayConfigKeySystemUUIDMapping; 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 48 public static void setResources(Resources resources) { 49 sResources = resources; 50 sResourceCache = new SparseArray<SoftReference<String>>(); 51 } 52 53 public static void setErrorPageResources(int loaderror, int nodomain) { 54 sRawLoadError = loaderror; 55 sRawNoDomain = nodomain; 56 } 57 58 public static void setConfigKeySystemUuidMapping(int config) { 59 sStringArrayConfigKeySystemUUIDMapping = config; 60 } 61 62 @CalledByNative 63 public static String getNoDomainPageContent() { 64 return getResource(sRawNoDomain, TYPE_RAW); 65 } 66 67 @CalledByNative 68 public static String getLoadErrorPageContent() { 69 return getResource(sRawLoadError, TYPE_RAW); 70 } 71 72 public static String[] getConfigKeySystemUuidMapping() { 73 // No need to cache, since this should be called only once. 74 return sResources.getStringArray(sStringArrayConfigKeySystemUUIDMapping); 75 } 76 77 private static String getResource(int resid, int type) { 78 assert resid != 0; 79 assert sResources != null; 80 assert sResourceCache != null; 81 82 SoftReference<String> stringRef = sResourceCache.get(resid); 83 String result = stringRef == null ? null : stringRef.get(); 84 if (result == null) { 85 switch (type) { 86 case TYPE_STRING: 87 result = sResources.getString(resid); 88 break; 89 case TYPE_RAW: 90 result = getRawFileResourceContent(resid); 91 break; 92 default: 93 throw new IllegalArgumentException("Unknown resource type"); 94 } 95 96 sResourceCache.put(resid, new SoftReference<String>(result)); 97 } 98 return result; 99 } 100 101 private static String getRawFileResourceContent(int resid) { 102 assert resid != 0; 103 assert sResources != null; 104 105 InputStreamReader isr = null; 106 String result = null; 107 108 try { 109 isr = new InputStreamReader( 110 sResources.openRawResource(resid)); 111 // \A tells the scanner to use the beginning of the input 112 // as the delimiter, hence causes it to read the entire text. 113 result = new Scanner(isr).useDelimiter("\\A").next(); 114 } catch (Resources.NotFoundException e) { 115 return ""; 116 } catch (NoSuchElementException e) { 117 return ""; 118 } finally { 119 try { 120 if (isr != null) { 121 isr.close(); 122 } 123 } catch (IOException e) { 124 // Nothing to do if close() fails. 125 } 126 } 127 return result; 128 } 129} 130