// Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. package org.chromium.content.browser; import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.os.Bundle; import android.util.Log; import java.util.List; /** * {@link PepperPluginManager} collects meta data about plugins from preloaded android apps * that reply to PEPPERPLUGIN intent query. */ public class PepperPluginManager { private static final String LOGTAG = "PepperPluginManager"; /** * Service Action: A plugin wishes to be loaded in the ContentView must * provide {@link android.content.IntentFilter IntentFilter} that accepts * this action in its AndroidManifest.xml. */ public static final String PEPPER_PLUGIN_ACTION = "org.chromium.intent.PEPPERPLUGIN"; public static final String PEPPER_PLUGIN_ROOT = "/system/lib/pepperplugin/"; // A plugin will specify the following fields in its AndroidManifest.xml. private static final String FILENAME = "filename"; private static final String MIMETYPE = "mimetype"; private static final String NAME = "name"; private static final String DESCRIPTION = "description"; private static final String VERSION = "version"; private static String getPluginDescription(Bundle metaData) { // Find the name of the plugin's shared library. String filename = metaData.getString(FILENAME); if (filename == null || filename.isEmpty()) { return null; } // Find the mimetype of the plugin. Flash is handled in getFlashPath. String mimetype = metaData.getString(MIMETYPE); if (mimetype == null || mimetype.isEmpty()) { return null; } // Assemble the plugin info, according to the format described in // pepper_plugin_list.cc. // (eg. path<#name><#description><#version>;mimetype) StringBuffer plugin = new StringBuffer(PEPPER_PLUGIN_ROOT); plugin.append(filename); // Find the (optional) name/description/version of the plugin. String name = metaData.getString(NAME); String description = metaData.getString(DESCRIPTION); String version = metaData.getString(VERSION); if (name != null && !name.isEmpty()) { plugin.append("#"); plugin.append(name); if (description != null && !description.isEmpty()) { plugin.append("#"); plugin.append(description); if (version != null && !version.isEmpty()) { plugin.append("#"); plugin.append(version); } } } plugin.append(';'); plugin.append(mimetype); return plugin.toString(); } /** * Collects information about installed plugins and returns a plugin description * string, which will be appended to for command line to load plugins. * * @param context Android context * @return Description string for plugins */ public static String getPlugins(final Context context) { StringBuffer ret = new StringBuffer(); PackageManager pm = context.getPackageManager(); List<ResolveInfo> plugins = pm.queryIntentServices( new Intent(PEPPER_PLUGIN_ACTION), PackageManager.GET_SERVICES | PackageManager.GET_META_DATA); for (ResolveInfo info : plugins) { // Retrieve the plugin's service information. ServiceInfo serviceInfo = info.serviceInfo; if (serviceInfo == null || serviceInfo.metaData == null || serviceInfo.packageName == null) { Log.e(LOGTAG, "Can't get service information from " + info); continue; } // Retrieve the plugin's package information. PackageInfo pkgInfo; try { pkgInfo = pm.getPackageInfo(serviceInfo.packageName, 0); } catch (NameNotFoundException e) { Log.e(LOGTAG, "Can't find plugin: " + serviceInfo.packageName); continue; } if (pkgInfo == null || (pkgInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) { continue; } Log.i(LOGTAG, "The given plugin package is preloaded: " + serviceInfo.packageName); String plugin = getPluginDescription(serviceInfo.metaData); if (plugin == null) { continue; } if (ret.length() > 0) { ret.append(','); } ret.append(plugin); } return ret.toString(); } }