// Copyright (c) 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_registry.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();
}
}