1 // Copyright 2013 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.content.browser; 6 7 import android.content.Context; 8 import android.content.Intent; 9 import android.content.pm.ApplicationInfo; 10 import android.content.pm.PackageInfo; 11 import android.content.pm.PackageManager; 12 import android.content.pm.PackageManager.NameNotFoundException; 13 import android.content.pm.ResolveInfo; 14 import android.content.pm.ServiceInfo; 15 import android.os.Bundle; 16 import android.util.Log; 17 18 import java.util.List; 19 20 /** 21 * {@link PepperPluginManager} collects meta data about plugins from preloaded android apps 22 * that reply to PEPPERPLUGIN intent query. 23 */ 24 public class PepperPluginManager { 25 26 private static final String LOGTAG = "PepperPluginManager"; 27 28 /** 29 * Service Action: A plugin wishes to be loaded in the ContentView must 30 * provide {@link android.content.IntentFilter IntentFilter} that accepts 31 * this action in its AndroidManifest.xml. 32 */ 33 public static final String PEPPER_PLUGIN_ACTION = "org.chromium.intent.PEPPERPLUGIN"; 34 public static final String PEPPER_PLUGIN_ROOT = "/system/lib/pepperplugin/"; 35 36 // A plugin will specify the following fields in its AndroidManifest.xml. 37 private static final String FILENAME = "filename"; 38 private static final String MIMETYPE = "mimetype"; 39 private static final String NAME = "name"; 40 private static final String DESCRIPTION = "description"; 41 private static final String VERSION = "version"; 42 getPluginDescription(Bundle metaData)43 private static String getPluginDescription(Bundle metaData) { 44 // Find the name of the plugin's shared library. 45 String filename = metaData.getString(FILENAME); 46 if (filename == null || filename.isEmpty()) { 47 return null; 48 } 49 // Find the mimetype of the plugin. Flash is handled in getFlashPath. 50 String mimetype = metaData.getString(MIMETYPE); 51 if (mimetype == null || mimetype.isEmpty()) { 52 return null; 53 } 54 // Assemble the plugin info, according to the format described in 55 // pepper_plugin_list.cc. 56 // (eg. path<#name><#description><#version>;mimetype) 57 StringBuffer plugin = new StringBuffer(PEPPER_PLUGIN_ROOT); 58 plugin.append(filename); 59 60 // Find the (optional) name/description/version of the plugin. 61 String name = metaData.getString(NAME); 62 String description = metaData.getString(DESCRIPTION); 63 String version = metaData.getString(VERSION); 64 65 if (name != null && !name.isEmpty()) { 66 plugin.append("#"); 67 plugin.append(name); 68 if (description != null && !description.isEmpty()) { 69 plugin.append("#"); 70 plugin.append(description); 71 if (version != null && !version.isEmpty()) { 72 plugin.append("#"); 73 plugin.append(version); 74 } 75 } 76 } 77 plugin.append(';'); 78 plugin.append(mimetype); 79 80 return plugin.toString(); 81 } 82 83 /** 84 * Collects information about installed plugins and returns a plugin description 85 * string, which will be appended to for command line to load plugins. 86 * 87 * @param context Android context 88 * @return Description string for plugins 89 */ getPlugins(final Context context)90 public static String getPlugins(final Context context) { 91 StringBuffer ret = new StringBuffer(); 92 PackageManager pm = context.getPackageManager(); 93 List<ResolveInfo> plugins = pm.queryIntentServices( 94 new Intent(PEPPER_PLUGIN_ACTION), 95 PackageManager.GET_SERVICES | PackageManager.GET_META_DATA); 96 for (ResolveInfo info : plugins) { 97 // Retrieve the plugin's service information. 98 ServiceInfo serviceInfo = info.serviceInfo; 99 if (serviceInfo == null || serviceInfo.metaData == null || 100 serviceInfo.packageName == null) { 101 Log.e(LOGTAG, "Can't get service information from " + info); 102 continue; 103 } 104 105 // Retrieve the plugin's package information. 106 PackageInfo pkgInfo; 107 try { 108 pkgInfo = pm.getPackageInfo(serviceInfo.packageName, 0); 109 } catch (NameNotFoundException e) { 110 Log.e(LOGTAG, "Can't find plugin: " + serviceInfo.packageName); 111 continue; 112 } 113 if (pkgInfo == null || 114 (pkgInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) { 115 continue; 116 } 117 Log.i(LOGTAG, "The given plugin package is preloaded: " + serviceInfo.packageName); 118 119 String plugin = getPluginDescription(serviceInfo.metaData); 120 if (plugin == null) { 121 continue; 122 } 123 if (ret.length() > 0) { 124 ret.append(','); 125 } 126 ret.append(plugin); 127 } 128 return ret.toString(); 129 } 130 } 131