PepperPluginManager.java revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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
5package org.chromium.content.browser;
6
7import android.content.Context;
8import android.content.Intent;
9import android.content.pm.ApplicationInfo;
10import android.content.pm.PackageInfo;
11import android.content.pm.PackageManager;
12import android.content.pm.PackageManager.NameNotFoundException;
13import android.content.pm.ResolveInfo;
14import android.content.pm.ServiceInfo;
15import android.os.Bundle;
16import android.util.Log;
17
18import 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 */
24public 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
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     */
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