PluginManager.java revision 01d0fbfa683012623f030ec75a63e1a9fabcb916
1658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba/* 2658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba * Copyright (C) 2009 The Android Open Source Project 3658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba * 4658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba * Licensed under the Apache License, Version 2.0 (the "License"); 5658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba * you may not use this file except in compliance with the License. 6658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba * You may obtain a copy of the License at 7658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba * 8658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba * http://www.apache.org/licenses/LICENSE-2.0 9658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba * 10658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba * Unless required by applicable law or agreed to in writing, software 11658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba * distributed under the License is distributed on an "AS IS" BASIS, 12658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba * See the License for the specific language governing permissions and 14658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba * limitations under the License. 15658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba */ 16658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba 17658ab7d787f64987d7c45aae08e5a12a073afe78Grace Klobapackage android.webkit; 18658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba 19658ab7d787f64987d7c45aae08e5a12a073afe78Grace Klobaimport java.util.ArrayList; 20658ab7d787f64987d7c45aae08e5a12a073afe78Grace Klobaimport java.util.List; 21658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba 22658ab7d787f64987d7c45aae08e5a12a073afe78Grace Klobaimport android.annotation.SdkConstant; 23658ab7d787f64987d7c45aae08e5a12a073afe78Grace Klobaimport android.annotation.SdkConstant.SdkConstantType; 24658ab7d787f64987d7c45aae08e5a12a073afe78Grace Klobaimport android.content.Context; 25658ab7d787f64987d7c45aae08e5a12a073afe78Grace Klobaimport android.content.Intent; 26658ab7d787f64987d7c45aae08e5a12a073afe78Grace Klobaimport android.content.pm.PackageInfo; 27658ab7d787f64987d7c45aae08e5a12a073afe78Grace Klobaimport android.content.pm.PackageManager; 28658ab7d787f64987d7c45aae08e5a12a073afe78Grace Klobaimport android.content.pm.ResolveInfo; 29658ab7d787f64987d7c45aae08e5a12a073afe78Grace Klobaimport android.content.pm.ServiceInfo; 30658ab7d787f64987d7c45aae08e5a12a073afe78Grace Klobaimport android.content.pm.Signature; 31658ab7d787f64987d7c45aae08e5a12a073afe78Grace Klobaimport android.content.pm.PackageManager.NameNotFoundException; 322919f49273ee5a6669dc4689c88759b3cc6a083fGrace Klobaimport android.os.SystemProperties; 33658ab7d787f64987d7c45aae08e5a12a073afe78Grace Klobaimport android.util.Log; 34cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenbergerimport android.webkit.plugin.NativePlugin; 35cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenbergerimport android.webkit.plugin.WebkitPlugin; 36658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba 37658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba/** 38658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba * Class for managing the relationship between the {@link WebView} and installed 39658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba * plugins in the system. You can find this class through 40658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba * {@link PluginManager#getInstance}. 41658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba * 42658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba * @hide pending API solidification 43658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba */ 44658ab7d787f64987d7c45aae08e5a12a073afe78Grace Klobapublic class PluginManager { 45658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba 46cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger private class PluginInfo { 47cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger public PackageInfo packageInfo; 48cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger public boolean isNative; 49cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger public Class<? extends WebkitPlugin> pluginClass; 50cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger } 51cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger 52658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba /** 53658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba * Service Action: A plugin wishes to be loaded in the WebView must provide 54658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba * {@link android.content.IntentFilter IntentFilter} that accepts this 55658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba * action in their AndroidManifest.xml. 56658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba * <p> 57658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba * TODO: we may change this to a new PLUGIN_ACTION if this is going to be 58658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba * public. 59658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba */ 60658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba @SdkConstant(SdkConstantType.SERVICE_ACTION) 61658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba public static final String PLUGIN_ACTION = "android.webkit.PLUGIN"; 62658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba 63658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba /** 64658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba * A plugin wishes to be loaded in the WebView must provide this permission 65658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba * in their AndroidManifest.xml. 66658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba */ 67658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba public static final String PLUGIN_PERMISSION = "android.webkit.permission.PLUGIN"; 68658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba 69658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba private static final String LOGTAG = "webkit"; 70658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba 71cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger private static final String PLUGIN_TYPE = "type"; 72cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger private static final String TYPE_NATIVE = "native"; 73cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger 74658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba private static PluginManager mInstance = null; 75658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba 76658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba private final Context mContext; 77658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba 78cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger private ArrayList<PluginInfo> mPluginInfoCache; 79c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger 8073477e7336cd1bdd67984a0f6374c79108a8f098Grace Kloba // Only plugin matches one of the signatures in the list can be loaded 8173477e7336cd1bdd67984a0f6374c79108a8f098Grace Kloba // inside the WebView process 822919f49273ee5a6669dc4689c88759b3cc6a083fGrace Kloba private static final String SIGNATURE_1 = "308204c5308203ada003020102020900d7cb412f75f4887e300d06092a864886f70d010105050030819d310b3009060355040613025553311330110603550408130a43616c69666f726e69613111300f0603550407130853616e204a6f736531233021060355040a131a41646f62652053797374656d7320496e636f72706f7261746564311c301a060355040b1313496e666f726d6174696f6e2053797374656d73312330210603550403131a41646f62652053797374656d7320496e636f72706f7261746564301e170d3039313030313030323331345a170d3337303231363030323331345a30819d310b3009060355040613025553311330110603550408130a43616c69666f726e69613111300f0603550407130853616e204a6f736531233021060355040a131a41646f62652053797374656d7320496e636f72706f7261746564311c301a060355040b1313496e666f726d6174696f6e2053797374656d73312330210603550403131a41646f62652053797374656d7320496e636f72706f726174656430820120300d06092a864886f70d01010105000382010d0030820108028201010099724f3e05bbd78843794f357776e04b340e13cb1c9ccb3044865180d7d8fec8166c5bbd876da8b80aa71eb6ba3d4d3455c9a8de162d24a25c4c1cd04c9523affd06a279fc8f0d018f242486bdbb2dbfbf6fcb21ed567879091928b876f7ccebc7bccef157366ebe74e33ae1d7e9373091adab8327482154afc0693a549522f8c796dd84d16e24bb221f5dbb809ca56dd2b6e799c5fa06b6d9c5c09ada54ea4c5db1523a9794ed22a3889e5e05b29f8ee0a8d61efe07ae28f65dece2ff7edc5b1416d7c7aad7f0d35e8f4a4b964dbf50ae9aa6d620157770d974131b3e7e3abd6d163d65758e2f0822db9c88598b9db6263d963d13942c91fc5efe34fc1e06e3020103a382010630820102301d0603551d0e041604145af418e419a639e1657db960996364a37ef20d403081d20603551d230481ca3081c780145af418e419a639e1657db960996364a37ef20d40a181a3a481a030819d310b3009060355040613025553311330110603550408130a43616c69666f726e69613111300f0603550407130853616e204a6f736531233021060355040a131a41646f62652053797374656d7320496e636f72706f7261746564311c301a060355040b1313496e666f726d6174696f6e2053797374656d73312330210603550403131a41646f62652053797374656d7320496e636f72706f7261746564820900d7cb412f75f4887e300c0603551d13040530030101ff300d06092a864886f70d0101050500038201010076c2a11fe303359689c2ebc7b2c398eff8c3f9ad545cdbac75df63bf7b5395b6988d1842d6aa1556d595b5692e08224d667a4c9c438f05e74906c53dd8016dde7004068866f01846365efd146e9bfaa48c9ecf657f87b97c757da11f225c4a24177bf2d7188e6cce2a70a1e8a841a14471eb51457398b8a0addd8b6c8c1538ca8f1e40b4d8b960009ea22c188d28924813d2c0b4a4d334b7cf05507e1fcf0a06fe946c7ffc435e173af6fc3e3400643710acc806f830a14788291d46f2feed9fb5c70423ca747ed1572d752894ac1f19f93989766308579393fabb43649aa8806a313b1ab9a50922a44c2467b9062037f2da0d484d9ffd8fe628eeea629ba637"; 8373477e7336cd1bdd67984a0f6374c79108a8f098Grace Kloba 8473477e7336cd1bdd67984a0f6374c79108a8f098Grace Kloba private static final Signature[] SIGNATURES = new Signature[] { 852919f49273ee5a6669dc4689c88759b3cc6a083fGrace Kloba new Signature(SIGNATURE_1) 8673477e7336cd1bdd67984a0f6374c79108a8f098Grace Kloba }; 8773477e7336cd1bdd67984a0f6374c79108a8f098Grace Kloba 88658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba private PluginManager(Context context) { 89658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba mContext = context; 90cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger mPluginInfoCache = new ArrayList<PluginInfo>(); 91658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba } 92658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba 93658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba public static synchronized PluginManager getInstance(Context context) { 94658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba if (mInstance == null) { 95658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba if (context == null) { 96658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba throw new IllegalStateException( 97658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba "First call to PluginManager need a valid context."); 98658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba } 9901d0fbfa683012623f030ec75a63e1a9fabcb916Romain Guy mInstance = new PluginManager(context.getApplicationContext()); 100658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba } 101658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba return mInstance; 102658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba } 103658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba 104658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba /** 105658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba * Signal the WebCore thread to refresh its list of plugins. Use this if the 106658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba * directory contents of one of the plugin directories has been modified and 107658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba * needs its changes reflecting. May cause plugin load and/or unload. 108658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba * 109658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba * @param reloadOpenPages Set to true to reload all open pages. 110658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba */ 111658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba public void refreshPlugins(boolean reloadOpenPages) { 112658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba BrowserFrame.sJavaBridge.obtainMessage( 113658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba JWebCoreJavaBridge.REFRESH_PLUGINS, reloadOpenPages) 114658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba .sendToTarget(); 115658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba } 116658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba 11737eb3c35152fadc2541ebe6af3e39b246ca87fb7Derek Sollenberger String[] getPluginDirectories() { 118c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger 119658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba ArrayList<String> directories = new ArrayList<String>(); 120658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba PackageManager pm = mContext.getPackageManager(); 121658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba List<ResolveInfo> plugins = pm.queryIntentServices(new Intent( 122cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger PLUGIN_ACTION), PackageManager.GET_SERVICES 123cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger | PackageManager.GET_META_DATA); 124c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger 125cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger synchronized(mPluginInfoCache) { 126c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger 127c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger // clear the list of existing packageInfo objects 128cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger mPluginInfoCache.clear(); 129c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger 130c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger for (ResolveInfo info : plugins) { 131cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger 132cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger // retrieve the plugin's service information 133c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger ServiceInfo serviceInfo = info.serviceInfo; 134c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger if (serviceInfo == null) { 135c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger Log.w(LOGTAG, "Ignore bad plugin"); 136c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger continue; 137c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger } 138cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger 139cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger // retrieve information from the plugin's manifest 140c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger PackageInfo pkgInfo; 141c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger try { 142c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger pkgInfo = pm.getPackageInfo(serviceInfo.packageName, 143c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger PackageManager.GET_PERMISSIONS 144c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger | PackageManager.GET_SIGNATURES); 145c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger } catch (NameNotFoundException e) { 146cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger Log.w(LOGTAG, "Can't find plugin: " + serviceInfo.packageName); 147c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger continue; 148c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger } 149c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger if (pkgInfo == null) { 150c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger continue; 151c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger } 152cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger 153cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger // check if their is a conflict in the lib directory names 154c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger String directory = pkgInfo.applicationInfo.dataDir + "/lib"; 155c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger if (directories.contains(directory)) { 156c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger continue; 157c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger } 158cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger 159cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger // check if the plugin has the required permissions 160c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger String permissions[] = pkgInfo.requestedPermissions; 161c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger if (permissions == null) { 162c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger continue; 163c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger } 164c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger boolean permissionOk = false; 165c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger for (String permit : permissions) { 166c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger if (PLUGIN_PERMISSION.equals(permit)) { 167c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger permissionOk = true; 168c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger break; 169c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger } 170c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger } 171c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger if (!permissionOk) { 172c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger continue; 173c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger } 174cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger 175cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger // check to ensure the plugin is properly signed 176c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger Signature signatures[] = pkgInfo.signatures; 177c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger if (signatures == null) { 178c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger continue; 179c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger } 1802919f49273ee5a6669dc4689c88759b3cc6a083fGrace Kloba if (SystemProperties.getBoolean("ro.secure", false)) { 1812919f49273ee5a6669dc4689c88759b3cc6a083fGrace Kloba boolean signatureMatch = false; 1822919f49273ee5a6669dc4689c88759b3cc6a083fGrace Kloba for (Signature signature : signatures) { 1832919f49273ee5a6669dc4689c88759b3cc6a083fGrace Kloba for (int i = 0; i < SIGNATURES.length; i++) { 1842919f49273ee5a6669dc4689c88759b3cc6a083fGrace Kloba if (SIGNATURES[i].equals(signature)) { 1852919f49273ee5a6669dc4689c88759b3cc6a083fGrace Kloba signatureMatch = true; 1862919f49273ee5a6669dc4689c88759b3cc6a083fGrace Kloba break; 1872919f49273ee5a6669dc4689c88759b3cc6a083fGrace Kloba } 18873477e7336cd1bdd67984a0f6374c79108a8f098Grace Kloba } 18973477e7336cd1bdd67984a0f6374c79108a8f098Grace Kloba } 1902919f49273ee5a6669dc4689c88759b3cc6a083fGrace Kloba if (!signatureMatch) { 1912919f49273ee5a6669dc4689c88759b3cc6a083fGrace Kloba continue; 1922919f49273ee5a6669dc4689c88759b3cc6a083fGrace Kloba } 193c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger } 194cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger 195cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger PluginInfo pluginInfo = new PluginInfo(); 196cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger pluginInfo.packageInfo = pkgInfo; 197cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger 198cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger // determine the type of plugin from the manifest 199cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger if (serviceInfo.metaData == null) { 200cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger Log.e(LOGTAG, "The plugin '" + serviceInfo.name + "' has no type defined"); 201cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger continue; 202cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger } 203cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger 204cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger String pluginType = serviceInfo.metaData.getString(PLUGIN_TYPE); 205cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger if (TYPE_NATIVE.equals(pluginType)) { 206cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger pluginInfo.isNative = true; 207cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger } else { 208cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger Log.e(LOGTAG, "Unrecognized plugin type: " + pluginType); 209cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger continue; 210cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger } 211cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger 212cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger try { 213cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger Class<?> cls = getPluginClass(serviceInfo.packageName, serviceInfo.name); 214cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger 215cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger boolean classFound = false; 216cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger for(Class<?> implemented : cls.getInterfaces()) { 217cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger if (pluginInfo.isNative && implemented.equals(NativePlugin.class)) { 218cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger pluginInfo.pluginClass = cls.asSubclass(WebkitPlugin.class); 219cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger classFound = true; 220cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger break; 221cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger } 222cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger } 223cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger 224cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger if (!classFound) { 225cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger Log.e(LOGTAG, "The plugin's class'" + serviceInfo.name + "' does not extend the appropriate interface."); 226cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger continue; 227cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger } 228cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger 229cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger } catch (NameNotFoundException e) { 230cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger Log.e(LOGTAG, "Can't find plugin: " + serviceInfo.packageName); 231cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger continue; 232cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger } catch (ClassNotFoundException e) { 233cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger Log.e(LOGTAG, "Can't find plugin's class: " + serviceInfo.name); 234cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger continue; 235cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger } 236cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger 237cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger // if all checks have passed then make the plugin available 238cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger mPluginInfoCache.add(pluginInfo); 239c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger directories.add(directory); 240658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba } 241658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba } 24237eb3c35152fadc2541ebe6af3e39b246ca87fb7Derek Sollenberger 243658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba return directories.toArray(new String[directories.size()]); 244658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba } 245fd055b2d7cebd6693925a30adad6c66a697af407Grace Kloba 246cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger /* package */ 247c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger String getPluginsAPKName(String pluginLib) { 248c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger 249c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger // basic error checking on input params 250c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger if (pluginLib == null || pluginLib.length() == 0) { 251c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger return null; 252c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger } 253c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger 254c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger // must be synchronized to ensure the consistency of the cache 255cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger synchronized(mPluginInfoCache) { 256cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger for (PluginInfo pluginInfo : mPluginInfoCache) { 257cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger PackageInfo pkgInfo = pluginInfo.packageInfo; 258c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger if (pluginLib.startsWith(pkgInfo.applicationInfo.dataDir)) { 259c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger return pkgInfo.packageName; 260c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger } 261c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger } 262c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger } 263c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger 264c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger // if no apk was found then return null 265c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger return null; 266c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger } 267c0b8a96d28c55cb51e4f9e1f85c8d3ecf1ff13bfDerek Sollenberger 268fd055b2d7cebd6693925a30adad6c66a697af407Grace Kloba String getPluginSharedDataDirectory() { 269fd055b2d7cebd6693925a30adad6c66a697af407Grace Kloba return mContext.getDir("plugins", 0).getPath(); 270fd055b2d7cebd6693925a30adad6c66a697af407Grace Kloba } 271cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger 272cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger /* package */ 273cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger WebkitPlugin getPluginInstance(String pkgName, int npp) { 274cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger 275cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger // must be synchronized to ensure the consistency of the cache 276cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger synchronized(mPluginInfoCache) { 277cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger 278cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger // lookup plugin based on pkgName and instantiate if possible. 279cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger for (PluginInfo pluginInfo : mPluginInfoCache) { 280cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger 281cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger if (pluginInfo.packageInfo.packageName.equals(pkgName)) { 282cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger 283cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger try { 284cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger WebkitPlugin webkitPlugin = pluginInfo.pluginClass.newInstance(); 285cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger 286cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger if (pluginInfo.isNative) { 287cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger NativePlugin nativePlugin = (NativePlugin) webkitPlugin; 288cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger nativePlugin.initializePlugin(npp, mContext); 289cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger } 290cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger 291cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger return webkitPlugin; 292cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger } catch (Exception e) { 293cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger // Any number of things could have happened. Log the exception and 294cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger // return null. Careful not to use Log.e(LOGTAG, "String", e) 295cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger // because that reports the exception to the checkin service. 296cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger Log.e(LOGTAG, Log.getStackTraceString(e)); 297cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger } 298cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger break; 299cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger } 300cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger } 301cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger } 302cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger return null; 303cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger } 304cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger 305cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger /* package */ 306cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger Class<?> getPluginClass(String packageName, String className) 307cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger throws NameNotFoundException, ClassNotFoundException { 308cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger Context pluginContext = mContext.createPackageContext(packageName, 309cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger Context.CONTEXT_INCLUDE_CODE | 310cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger Context.CONTEXT_IGNORE_SECURITY); 311cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger ClassLoader pluginCL = pluginContext.getClassLoader(); 312cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger return pluginCL.loadClass(className); 313cb37e71509da43e0d8d809591b09e8f5a582b5cdDerek Sollenberger } 314658ab7d787f64987d7c45aae08e5a12a073afe78Grace Kloba} 315