mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 11:25:00 +00:00
Bug 1381916
- Remove frontend support for plugins in Fennec r=nechen
MozReview-Commit-ID: Gkqe8Y5AMPV
This commit is contained in:
parent
5d84114d12
commit
25dad4abf2
@ -447,15 +447,9 @@ pref("browser.ui.scroll-toolbar-threshold", 10);
|
||||
pref("browser.ui.selection.distance", 250);
|
||||
|
||||
// plugins
|
||||
pref("plugin.disable", false);
|
||||
pref("plugin.disable", true);
|
||||
pref("dom.ipc.plugins.enabled", false);
|
||||
|
||||
// This pref isn't actually used anymore, but we're leaving this here to avoid changing
|
||||
// the default so that we can migrate a user-set pref. See bug 885357.
|
||||
pref("plugins.click_to_play", true);
|
||||
// The default value for nsIPluginTag.enabledState (STATE_CLICKTOPLAY = 1)
|
||||
pref("plugin.default.state", 1);
|
||||
|
||||
// product URLs
|
||||
// The breakpad report server to link to in about:crashes
|
||||
pref("breakpad.reportURL", "https://crash-stats.mozilla.com/report/index/");
|
||||
|
@ -31,11 +31,6 @@
|
||||
android:layout_height="match_parent"
|
||||
android:scrollbars="none"/>
|
||||
|
||||
<AbsoluteLayout android:id="@+id/plugin_container"
|
||||
android:background="@android:color/transparent"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
|
||||
<org.mozilla.gecko.FormAssistPopup android:id="@+id/form_assist_popup"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
|
@ -13,16 +13,6 @@
|
||||
<item>0</item>
|
||||
<item>1</item>
|
||||
</string-array>
|
||||
<string-array name="pref_plugins_entries">
|
||||
<item>@string/pref_plugins_enabled</item>
|
||||
<item>@string/pref_plugins_tap_to_play</item>
|
||||
<item>@string/pref_plugins_disabled</item>
|
||||
</string-array>
|
||||
<string-array name="pref_plugins_values">
|
||||
<item>1</item>
|
||||
<item>2</item>
|
||||
<item>0</item>
|
||||
</string-array>
|
||||
<string-array name="pref_char_encoding_entries">
|
||||
<item>@string/pref_char_encoding_on</item>
|
||||
<item>@string/pref_char_encoding_off</item>
|
||||
|
@ -54,12 +54,6 @@
|
||||
|
||||
<PreferenceCategory android:title="@string/pref_category_media">
|
||||
|
||||
<ListPreference android:key="plugin.enable"
|
||||
android:title="@string/pref_plugins"
|
||||
android:entries="@array/pref_plugins_entries"
|
||||
android:entryValues="@array/pref_plugins_values"
|
||||
android:persistent="false" />
|
||||
|
||||
<SwitchPreference android:key="media.autoplay.enabled"
|
||||
android:title="@string/pref_media_autoplay_enabled"
|
||||
android:summary="@string/pref_media_autoplay_enabled_summary" />
|
||||
|
@ -194,9 +194,6 @@ public abstract class GeckoApp extends GeckoActivity
|
||||
|
||||
protected GeckoView mLayerView;
|
||||
|
||||
private FullScreenHolder mFullScreenPluginContainer;
|
||||
private View mFullScreenPluginView;
|
||||
|
||||
protected boolean mLastSessionCrashed;
|
||||
protected boolean mShouldRestore;
|
||||
private boolean mSessionRestoreParsingFinished = false;
|
||||
@ -809,11 +806,6 @@ public abstract class GeckoApp extends GeckoActivity
|
||||
} else if ("Update:Install".equals(event)) {
|
||||
UpdateServiceHelper.applyUpdate(this);
|
||||
|
||||
} else if ("PluginHelper:playFlash".equals(event)) {
|
||||
final SharedPreferences prefs = getSharedPreferences();
|
||||
int count = prefs.getInt(PREFS_FLASH_USAGE, 0);
|
||||
prefs.edit().putInt(PREFS_FLASH_USAGE, ++count).apply();
|
||||
|
||||
} else if ("Mma:reader_available".equals(event)) {
|
||||
MmaDelegate.track(READER_AVAILABLE);
|
||||
|
||||
@ -917,113 +909,6 @@ public abstract class GeckoApp extends GeckoActivity
|
||||
});
|
||||
}
|
||||
|
||||
/* package */ void addFullScreenPluginView(View view) {
|
||||
if (mFullScreenPluginView != null) {
|
||||
Log.w(LOGTAG, "Already have a fullscreen plugin view");
|
||||
return;
|
||||
}
|
||||
|
||||
setFullScreen(true);
|
||||
|
||||
view.setWillNotDraw(false);
|
||||
if (view instanceof SurfaceView) {
|
||||
((SurfaceView) view).setZOrderOnTop(true);
|
||||
}
|
||||
|
||||
mFullScreenPluginContainer = new FullScreenHolder(this);
|
||||
|
||||
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
Gravity.CENTER);
|
||||
mFullScreenPluginContainer.addView(view, layoutParams);
|
||||
|
||||
|
||||
FrameLayout decor = (FrameLayout)getWindow().getDecorView();
|
||||
decor.addView(mFullScreenPluginContainer, layoutParams);
|
||||
|
||||
mFullScreenPluginView = view;
|
||||
}
|
||||
|
||||
@WrapForJNI(calledFrom = "gecko")
|
||||
private static void addPluginView(final View view) {
|
||||
final Activity activity = GeckoActivityMonitor.getInstance().getCurrentActivity();
|
||||
if (!(activity instanceof GeckoApp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final GeckoApp geckoApp = (GeckoApp) activity;
|
||||
if (ThreadUtils.isOnUiThread()) {
|
||||
geckoApp.addFullScreenPluginView(view);
|
||||
} else {
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
geckoApp.addFullScreenPluginView(view);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/* package */ void removeFullScreenPluginView(View view) {
|
||||
if (mFullScreenPluginView == null) {
|
||||
Log.w(LOGTAG, "Don't have a fullscreen plugin view");
|
||||
return;
|
||||
}
|
||||
|
||||
if (mFullScreenPluginView != view) {
|
||||
Log.w(LOGTAG, "Passed view is not the current full screen view");
|
||||
return;
|
||||
}
|
||||
|
||||
mFullScreenPluginContainer.removeView(mFullScreenPluginView);
|
||||
|
||||
// We need do do this on the next iteration in order to avoid
|
||||
// a deadlock, see comment below in FullScreenHolder
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mLayerView.showSurface();
|
||||
}
|
||||
});
|
||||
|
||||
FrameLayout decor = (FrameLayout)getWindow().getDecorView();
|
||||
decor.removeView(mFullScreenPluginContainer);
|
||||
|
||||
mFullScreenPluginView = null;
|
||||
|
||||
GeckoScreenOrientation.getInstance().unlock();
|
||||
setFullScreen(false);
|
||||
}
|
||||
|
||||
@WrapForJNI(calledFrom = "gecko")
|
||||
private static void removePluginView(final View view) {
|
||||
final Activity activity = GeckoActivityMonitor.getInstance().getCurrentActivity();
|
||||
if (!(activity instanceof GeckoApp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final GeckoApp geckoApp = (GeckoApp) activity;
|
||||
if (ThreadUtils.isOnUiThread()) {
|
||||
geckoApp.removeFullScreenPluginView(view);
|
||||
} else {
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
geckoApp.removeFullScreenPluginView(view);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@WrapForJNI(calledFrom = "ui", dispatchTo = "gecko")
|
||||
private static native void onFullScreenPluginHidden(View view);
|
||||
|
||||
@WrapForJNI(calledFrom = "gecko")
|
||||
private static Context getPluginContext() {
|
||||
return GeckoActivityMonitor.getInstance().getCurrentActivity();
|
||||
}
|
||||
|
||||
private void showSetImageResult(final boolean success, final int message, final String path) {
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
@ -1303,7 +1188,6 @@ public abstract class GeckoApp extends GeckoActivity
|
||||
EventDispatcher.getInstance().registerGeckoThreadListener(this,
|
||||
"Accessibility:Ready",
|
||||
"Gecko:Ready",
|
||||
"PluginHelper:playFlash",
|
||||
null);
|
||||
|
||||
EventDispatcher.getInstance().registerUiThreadListener(this,
|
||||
@ -2330,7 +2214,6 @@ public abstract class GeckoApp extends GeckoActivity
|
||||
EventDispatcher.getInstance().unregisterGeckoThreadListener(this,
|
||||
"Accessibility:Ready",
|
||||
"Gecko:Ready",
|
||||
"PluginHelper:playFlash",
|
||||
null);
|
||||
|
||||
EventDispatcher.getInstance().unregisterUiThreadListener(this,
|
||||
@ -2545,12 +2428,6 @@ public abstract class GeckoApp extends GeckoActivity
|
||||
return;
|
||||
}
|
||||
|
||||
if (mFullScreenPluginView != null) {
|
||||
onFullScreenPluginHidden(mFullScreenPluginView);
|
||||
removeFullScreenPluginView(mFullScreenPluginView);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mLayerView != null && mLayerView.isFullScreen()) {
|
||||
EventDispatcher.getInstance().dispatch("FullScreen:Exit", null);
|
||||
return;
|
||||
@ -2683,71 +2560,6 @@ public abstract class GeckoApp extends GeckoActivity
|
||||
}
|
||||
}
|
||||
|
||||
private class FullScreenHolder extends FrameLayout {
|
||||
|
||||
public FullScreenHolder(Context ctx) {
|
||||
super(ctx);
|
||||
setBackgroundColor(0xff000000);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addView(View view, int index) {
|
||||
/**
|
||||
* This normally gets called when Flash adds a separate SurfaceView
|
||||
* for the video. It is unhappy if we have the LayerView underneath
|
||||
* it for some reason so we need to hide that. Hiding the LayerView causes
|
||||
* its surface to be destroyed, which causes a pause composition
|
||||
* event to be sent to Gecko. We synchronously wait for that to be
|
||||
* processed. Simultaneously, however, Flash is waiting on a mutex so
|
||||
* the post() below is an attempt to avoid a deadlock.
|
||||
*/
|
||||
super.addView(view, index);
|
||||
|
||||
ThreadUtils.postToUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mLayerView.hideSurface();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* The methods below are simply copied from what Android WebKit does.
|
||||
* It wasn't ever called in my testing, but might as well
|
||||
* keep it in case it is for some reason. The methods
|
||||
* all return true because we don't want any events
|
||||
* leaking out from the fullscreen view.
|
||||
*/
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
if (event.isSystem()) {
|
||||
return super.onKeyDown(keyCode, event);
|
||||
}
|
||||
mFullScreenPluginView.onKeyDown(keyCode, event);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
||||
if (event.isSystem()) {
|
||||
return super.onKeyUp(keyCode, event);
|
||||
}
|
||||
mFullScreenPluginView.onKeyUp(keyCode, event);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTrackballEvent(MotionEvent event) {
|
||||
mFullScreenPluginView.onTrackballEvent(event);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private int getVersionCode() {
|
||||
int versionCode = 0;
|
||||
try {
|
||||
|
@ -69,7 +69,6 @@ public class Tab {
|
||||
private int mFaviconLoadId;
|
||||
private String mContentType;
|
||||
private boolean mHasTouchListeners;
|
||||
private final ArrayList<View> mPluginViews;
|
||||
private int mState;
|
||||
private Bitmap mThumbnailBitmap;
|
||||
private boolean mDesktopMode;
|
||||
@ -129,7 +128,6 @@ public class Tab {
|
||||
mTitle = title == null ? "" : title;
|
||||
mSiteIdentity = new SiteIdentity();
|
||||
mContentType = "";
|
||||
mPluginViews = new ArrayList<View>();
|
||||
mState = shouldShowProgress(url) ? STATE_LOADING : STATE_SUCCESS;
|
||||
mLoadProgress = LOAD_PROGRESS_INIT;
|
||||
mIconRequestBuilder = Icons.with(mAppContext).pageUrl(mUrl);
|
||||
@ -736,18 +734,6 @@ public class Tab {
|
||||
}
|
||||
}
|
||||
|
||||
public void addPluginView(View view) {
|
||||
mPluginViews.add(view);
|
||||
}
|
||||
|
||||
public void removePluginView(View view) {
|
||||
mPluginViews.remove(view);
|
||||
}
|
||||
|
||||
public View[] getPluginViews() {
|
||||
return mPluginViews.toArray(new View[mPluginViews.size()]);
|
||||
}
|
||||
|
||||
public void setDesktopMode(boolean enabled) {
|
||||
mDesktopMode = enabled;
|
||||
}
|
||||
|
@ -361,10 +361,6 @@
|
||||
<!ENTITY pref_clear_on_exit_title3 "Clear private data on exit">
|
||||
<!ENTITY pref_clear_on_exit_summary2 "&brandShortName; will automatically clear your data whenever you select \u0022Quit\u0022 from the main menu">
|
||||
<!ENTITY pref_clear_on_exit_dialog_title "Select which data to clear">
|
||||
<!ENTITY pref_plugins "Plugins">
|
||||
<!ENTITY pref_plugins_enabled "Enabled">
|
||||
<!ENTITY pref_plugins_tap_to_play2 "Touch to play">
|
||||
<!ENTITY pref_plugins_disabled "Disabled">
|
||||
<!ENTITY pref_restore_tabs "Restore tabs">
|
||||
<!ENTITY pref_restore_always "Always restore">
|
||||
<!ENTITY pref_restore_quit "Don\'t restore after quitting &brandShortName;">
|
||||
|
@ -261,10 +261,6 @@
|
||||
<string name="pref_clear_on_exit_title">&pref_clear_on_exit_title3;</string>
|
||||
<string name="pref_clear_on_exit_summary2">&pref_clear_on_exit_summary2;</string>
|
||||
<string name="pref_clear_on_exit_dialog_title">&pref_clear_on_exit_dialog_title;</string>
|
||||
<string name="pref_plugins">&pref_plugins;</string>
|
||||
<string name="pref_plugins_enabled">&pref_plugins_enabled;</string>
|
||||
<string name="pref_plugins_tap_to_play">&pref_plugins_tap_to_play2;</string>
|
||||
<string name="pref_plugins_disabled">&pref_plugins_disabled;</string>
|
||||
<string name="pref_use_system_font_size">&pref_use_system_font_size;</string>
|
||||
<string name="pref_use_system_font_size_summary">&pref_use_system_font_size_summary;</string>
|
||||
<string name="pref_media_autoplay_enabled">&pref_media_autoplay_enabled;</string>
|
||||
|
@ -129,7 +129,6 @@ var WindowEventDispatcher = EventDispatcher.for(window);
|
||||
|
||||
var lazilyLoadedBrowserScripts = [
|
||||
["MasterPassword", "chrome://browser/content/MasterPassword.js"],
|
||||
["PluginHelper", "chrome://browser/content/PluginHelper.js"],
|
||||
["OfflineApps", "chrome://browser/content/OfflineApps.js"],
|
||||
["Linkifier", "chrome://browser/content/Linkify.js"],
|
||||
["CastingApps", "chrome://browser/content/CastingApps.js"],
|
||||
@ -1014,13 +1013,6 @@ var BrowserApp = {
|
||||
}
|
||||
|
||||
if (currentUIVersion < 1) {
|
||||
// Migrate user-set "plugins.click_to_play" pref. See bug 884694.
|
||||
// Because the default value is true, a user-set pref means that the pref was set to false.
|
||||
if (Services.prefs.prefHasUserValue("plugins.click_to_play")) {
|
||||
Services.prefs.setIntPref("plugin.default.state", Ci.nsIPluginTag.STATE_ENABLED);
|
||||
Services.prefs.clearUserPref("plugins.click_to_play");
|
||||
}
|
||||
|
||||
// Migrate the "privacy.donottrackheader.value" pref. See bug 1042135.
|
||||
if (Services.prefs.prefHasUserValue("privacy.donottrackheader.value")) {
|
||||
// Make sure the doNotTrack value conforms to the conversion from
|
||||
@ -1955,12 +1947,6 @@ var BrowserApp = {
|
||||
aSubject.QueryInterface(Ci.nsIWritableVariant);
|
||||
|
||||
switch (aData) {
|
||||
// The plugin pref is actually two separate prefs, so
|
||||
// we need to handle it differently
|
||||
case "plugin.enable":
|
||||
aSubject.setAsAString(PluginHelper.getPluginPreference());
|
||||
break;
|
||||
|
||||
// Handle master password
|
||||
case "privacy.masterpassword.enabled":
|
||||
aSubject.setAsBool(MasterPassword.enabled);
|
||||
@ -1991,13 +1977,6 @@ var BrowserApp = {
|
||||
let value = aSubject.QueryInterface(Ci.nsIVariant);
|
||||
|
||||
switch (aData) {
|
||||
// The plugin pref is actually two separate prefs, so we need to
|
||||
// handle it differently.
|
||||
case "plugin.enable":
|
||||
PluginHelper.setPluginPreference(value);
|
||||
aSubject.setAsEmpty();
|
||||
break;
|
||||
|
||||
// MasterPassword pref is not real, we just need take action and leave
|
||||
case "privacy.masterpassword.enabled":
|
||||
if (MasterPassword.enabled) {
|
||||
@ -3473,9 +3452,6 @@ function Tab(aURL, aParams) {
|
||||
this._parentId = -1;
|
||||
this.lastTouchedAt = Date.now();
|
||||
this.contentDocumentIsDisplayed = true;
|
||||
this.pluginDoorhangerTimeout = null;
|
||||
this.shouldShowPluginDoorhanger = true;
|
||||
this.clickToPlayPluginsActivated = false;
|
||||
this.desktopMode = false;
|
||||
this.originalURI = null;
|
||||
this.hasTouchListener = false;
|
||||
@ -3643,7 +3619,6 @@ Tab.prototype = {
|
||||
this.browser.addEventListener("DOMWindowFocus", this, true);
|
||||
|
||||
// Note that the XBL binding is untrusted
|
||||
this.browser.addEventListener("PluginBindingAttached", this, true, true);
|
||||
this.browser.addEventListener("VideoBindingAttached", this, true, true);
|
||||
this.browser.addEventListener("VideoBindingCast", this, true, true);
|
||||
|
||||
@ -3758,7 +3733,6 @@ Tab.prototype = {
|
||||
this.browser.removeEventListener("TabPreZombify", this, true);
|
||||
this.browser.removeEventListener("DOMWindowFocus", this, true);
|
||||
|
||||
this.browser.removeEventListener("PluginBindingAttached", this, true, true);
|
||||
this.browser.removeEventListener("VideoBindingAttached", this, true, true);
|
||||
this.browser.removeEventListener("VideoBindingCast", this, true, true);
|
||||
|
||||
@ -4271,11 +4245,6 @@ Tab.prototype = {
|
||||
break;
|
||||
}
|
||||
|
||||
case "PluginBindingAttached": {
|
||||
PluginHelper.handlePluginBindingAttached(this, aEvent);
|
||||
break;
|
||||
}
|
||||
|
||||
case "VideoBindingAttached": {
|
||||
CastingApps.handleVideoBindingAttached(this, aEvent);
|
||||
break;
|
||||
@ -4454,12 +4423,6 @@ Tab.prototype = {
|
||||
this.browser.messageManager.sendAsyncMessage("Reader:PushState", {isArticle: this.browser.isArticle});
|
||||
}
|
||||
|
||||
// Reset state of click-to-play plugin notifications.
|
||||
clearTimeout(this.pluginDoorhangerTimeout);
|
||||
this.pluginDoorhangerTimeout = null;
|
||||
this.shouldShowPluginDoorhanger = true;
|
||||
this.clickToPlayPluginsActivated = false;
|
||||
|
||||
let baseDomain = "";
|
||||
// For recognized scheme, get base domain from host.
|
||||
let principalURI = contentWin.document.nodePrincipal.URI;
|
||||
@ -5919,7 +5882,7 @@ var IdentityHandler = {
|
||||
}
|
||||
|
||||
// We also allow "about:" by allowing the selector to be empty (i.e. '(|.....|...|...)'
|
||||
let whitelist = /^about:($|about|accounts|addons|buildconfig|cache|config|crashes|devices|downloads|fennec|firefox|feedback|healthreport|home|license|logins|logo|memory|mozilla|networking|plugins|privatebrowsing|rights|serviceworkers|support|telemetry|webrtc)($|\?)/i;
|
||||
let whitelist = /^about:($|about|accounts|addons|buildconfig|cache|config|crashes|devices|downloads|fennec|firefox|feedback|healthreport|home|license|logins|logo|memory|mozilla|networking|privatebrowsing|rights|serviceworkers|support|telemetry|webrtc)($|\?)/i;
|
||||
if (uri.schemeIs("about") && whitelist.test(uri.spec)) {
|
||||
return this.IDENTITY_MODE_CHROMEUI;
|
||||
}
|
||||
|
@ -1407,229 +1407,6 @@ public class GeckoAppShell
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A plugin that wish to be loaded in the WebView must provide this permission
|
||||
* in their AndroidManifest.xml.
|
||||
*/
|
||||
public static final String PLUGIN_ACTION = "android.webkit.PLUGIN";
|
||||
public static final String PLUGIN_PERMISSION = "android.webkit.permission.PLUGIN";
|
||||
|
||||
private static final String PLUGIN_SYSTEM_LIB = "/system/lib/plugins/";
|
||||
|
||||
private static final String PLUGIN_TYPE = "type";
|
||||
private static final String TYPE_NATIVE = "native";
|
||||
public static final ArrayList<PackageInfo> mPackageInfoCache = new ArrayList<>();
|
||||
|
||||
// Returns null if plugins are blocked on the device.
|
||||
static String[] getPluginDirectories() {
|
||||
|
||||
// Block on Pixel C.
|
||||
if ((new File("/system/lib/hw/power.dragon.so")).exists()) {
|
||||
Log.w(LOGTAG, "Blocking plugins because of Pixel C device (bug 1255122)");
|
||||
return null;
|
||||
}
|
||||
// An awful hack to detect Tegra devices. Easiest way to do it without spinning up a EGL context.
|
||||
boolean isTegra = (new File("/system/lib/hw/gralloc.tegra.so")).exists() ||
|
||||
(new File("/system/lib/hw/gralloc.tegra3.so")).exists() ||
|
||||
(new File("/sys/class/nvidia-gpu")).exists();
|
||||
if (isTegra) {
|
||||
// disable on KitKat (bug 957694)
|
||||
if (Build.VERSION.SDK_INT >= 19) {
|
||||
Log.w(LOGTAG, "Blocking plugins because of Tegra (bug 957694)");
|
||||
return null;
|
||||
}
|
||||
|
||||
// disable Flash on Tegra ICS with CM9 and other custom firmware (bug 736421)
|
||||
final File vfile = new File("/proc/version");
|
||||
try {
|
||||
if (vfile.canRead()) {
|
||||
final BufferedReader reader = new BufferedReader(new FileReader(vfile));
|
||||
try {
|
||||
final String version = reader.readLine();
|
||||
if (version.indexOf("CM9") != -1 ||
|
||||
version.indexOf("cyanogen") != -1 ||
|
||||
version.indexOf("Nova") != -1) {
|
||||
Log.w(LOGTAG, "Blocking plugins because of Tegra 2 + unofficial ICS bug (bug 736421)");
|
||||
return null;
|
||||
}
|
||||
} finally {
|
||||
reader.close();
|
||||
}
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
// Do nothing.
|
||||
}
|
||||
}
|
||||
|
||||
ArrayList<String> directories = new ArrayList<String>();
|
||||
PackageManager pm = getApplicationContext().getPackageManager();
|
||||
List<ResolveInfo> plugins = pm.queryIntentServices(new Intent(PLUGIN_ACTION),
|
||||
PackageManager.GET_META_DATA);
|
||||
|
||||
synchronized (mPackageInfoCache) {
|
||||
|
||||
// clear the list of existing packageInfo objects
|
||||
mPackageInfoCache.clear();
|
||||
|
||||
|
||||
for (ResolveInfo info : plugins) {
|
||||
|
||||
// retrieve the plugin's service information
|
||||
ServiceInfo serviceInfo = info.serviceInfo;
|
||||
if (serviceInfo == null) {
|
||||
Log.w(LOGTAG, "Ignoring bad plugin.");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Blacklist HTC's flash lite.
|
||||
// See bug #704516 - We're not quite sure what Flash Lite does,
|
||||
// but loading it causes Flash to give errors and fail to draw.
|
||||
if (serviceInfo.packageName.equals("com.htc.flashliteplugin")) {
|
||||
Log.w(LOGTAG, "Skipping HTC's flash lite plugin");
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// Retrieve information from the plugin's manifest.
|
||||
PackageInfo pkgInfo;
|
||||
try {
|
||||
pkgInfo = pm.getPackageInfo(serviceInfo.packageName,
|
||||
PackageManager.GET_PERMISSIONS
|
||||
| PackageManager.GET_SIGNATURES);
|
||||
} catch (Exception e) {
|
||||
Log.w(LOGTAG, "Can't find plugin: " + serviceInfo.packageName);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pkgInfo == null) {
|
||||
Log.w(LOGTAG, "Not loading plugin: " + serviceInfo.packageName + ". Could not load package information.");
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* find the location of the plugin's shared library. The default
|
||||
* is to assume the app is either a user installed app or an
|
||||
* updated system app. In both of these cases the library is
|
||||
* stored in the app's data directory.
|
||||
*/
|
||||
String directory = pkgInfo.applicationInfo.dataDir + "/lib";
|
||||
final int appFlags = pkgInfo.applicationInfo.flags;
|
||||
final int updatedSystemFlags = ApplicationInfo.FLAG_SYSTEM |
|
||||
ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
|
||||
|
||||
// preloaded system app with no user updates
|
||||
if ((appFlags & updatedSystemFlags) == ApplicationInfo.FLAG_SYSTEM) {
|
||||
directory = PLUGIN_SYSTEM_LIB + pkgInfo.packageName;
|
||||
}
|
||||
|
||||
// check if the plugin has the required permissions
|
||||
String permissions[] = pkgInfo.requestedPermissions;
|
||||
if (permissions == null) {
|
||||
Log.w(LOGTAG, "Not loading plugin: " + serviceInfo.packageName + ". Does not have required permission.");
|
||||
continue;
|
||||
}
|
||||
boolean permissionOk = false;
|
||||
for (String permit : permissions) {
|
||||
if (PLUGIN_PERMISSION.equals(permit)) {
|
||||
permissionOk = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!permissionOk) {
|
||||
Log.w(LOGTAG, "Not loading plugin: " + serviceInfo.packageName + ". Does not have required permission (2).");
|
||||
continue;
|
||||
}
|
||||
|
||||
// check to ensure the plugin is properly signed
|
||||
Signature signatures[] = pkgInfo.signatures;
|
||||
if (signatures == null) {
|
||||
Log.w(LOGTAG, "Not loading plugin: " + serviceInfo.packageName + ". Not signed.");
|
||||
continue;
|
||||
}
|
||||
|
||||
// determine the type of plugin from the manifest
|
||||
if (serviceInfo.metaData == null) {
|
||||
Log.e(LOGTAG, "The plugin '" + serviceInfo.name + "' has no defined type.");
|
||||
continue;
|
||||
}
|
||||
|
||||
String pluginType = serviceInfo.metaData.getString(PLUGIN_TYPE);
|
||||
if (!TYPE_NATIVE.equals(pluginType)) {
|
||||
Log.e(LOGTAG, "Unrecognized plugin type: " + pluginType);
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
Class<?> cls = getPluginClass(serviceInfo.packageName, serviceInfo.name);
|
||||
|
||||
//TODO implement any requirements of the plugin class here!
|
||||
boolean classFound = true;
|
||||
|
||||
if (!classFound) {
|
||||
Log.e(LOGTAG, "The plugin's class' " + serviceInfo.name + "' does not extend the appropriate class.");
|
||||
continue;
|
||||
}
|
||||
|
||||
} catch (NameNotFoundException e) {
|
||||
Log.e(LOGTAG, "Can't find plugin: " + serviceInfo.packageName);
|
||||
continue;
|
||||
} catch (ClassNotFoundException e) {
|
||||
Log.e(LOGTAG, "Can't find plugin's class: " + serviceInfo.name);
|
||||
continue;
|
||||
}
|
||||
|
||||
// if all checks have passed then make the plugin available
|
||||
mPackageInfoCache.add(pkgInfo);
|
||||
directories.add(directory);
|
||||
}
|
||||
}
|
||||
|
||||
return directories.toArray(new String[directories.size()]);
|
||||
}
|
||||
|
||||
static String getPluginPackage(String pluginLib) {
|
||||
|
||||
if (pluginLib == null || pluginLib.length() == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
synchronized (mPackageInfoCache) {
|
||||
for (PackageInfo pkgInfo : mPackageInfoCache) {
|
||||
if (pluginLib.contains(pkgInfo.packageName)) {
|
||||
return pkgInfo.packageName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static Class<?> getPluginClass(String packageName, String className)
|
||||
throws NameNotFoundException, ClassNotFoundException {
|
||||
Context pluginContext = getApplicationContext().createPackageContext(packageName,
|
||||
Context.CONTEXT_INCLUDE_CODE |
|
||||
Context.CONTEXT_IGNORE_SECURITY);
|
||||
ClassLoader pluginCL = pluginContext.getClassLoader();
|
||||
return pluginCL.loadClass(className);
|
||||
}
|
||||
|
||||
@WrapForJNI
|
||||
private static Class<?> loadPluginClass(String className, String libName) {
|
||||
try {
|
||||
final String packageName = getPluginPackage(libName);
|
||||
final int contextFlags = Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY;
|
||||
final Context pluginContext = getApplicationContext().createPackageContext(
|
||||
packageName, contextFlags);
|
||||
return pluginContext.getClassLoader().loadClass(className);
|
||||
} catch (java.lang.ClassNotFoundException cnfe) {
|
||||
Log.w(LOGTAG, "Couldn't find plugin class " + className, cnfe);
|
||||
return null;
|
||||
} catch (android.content.pm.PackageManager.NameNotFoundException nnfe) {
|
||||
Log.w(LOGTAG, "Couldn't find package.", nnfe);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static Context sApplicationContext;
|
||||
|
||||
@WrapForJNI
|
||||
|
@ -259,15 +259,8 @@ public class GeckoThread extends Thread {
|
||||
res.updateConfiguration(config, null);
|
||||
}
|
||||
|
||||
String[] pluginDirs = null;
|
||||
try {
|
||||
pluginDirs = GeckoAppShell.getPluginDirectories();
|
||||
} catch (Exception e) {
|
||||
Log.w(LOGTAG, "Caught exception getting plugin dirs.", e);
|
||||
}
|
||||
|
||||
final String resourcePath = context.getPackageResourcePath();
|
||||
GeckoLoader.setupGeckoEnvironment(context, pluginDirs, context.getFilesDir().getPath());
|
||||
GeckoLoader.setupGeckoEnvironment(context, context.getFilesDir().getPath());
|
||||
|
||||
try {
|
||||
loadGeckoLibs(context, resourcePath);
|
||||
|
@ -57,34 +57,6 @@ public final class GeckoLoader {
|
||||
return sGREDir;
|
||||
}
|
||||
|
||||
private static void setupPluginEnvironment(Context context, String[] pluginDirs) {
|
||||
// setup plugin path directories
|
||||
try {
|
||||
// Check to see if plugins were blocked.
|
||||
if (pluginDirs == null) {
|
||||
putenv("MOZ_PLUGINS_BLOCKED=1");
|
||||
putenv("MOZ_PLUGIN_PATH=");
|
||||
return;
|
||||
}
|
||||
|
||||
StringBuilder pluginSearchPath = new StringBuilder();
|
||||
for (int i = 0; i < pluginDirs.length; i++) {
|
||||
pluginSearchPath.append(pluginDirs[i]);
|
||||
pluginSearchPath.append(":");
|
||||
}
|
||||
putenv("MOZ_PLUGIN_PATH=" + pluginSearchPath);
|
||||
|
||||
File pluginDataDir = context.getDir("plugins", 0);
|
||||
putenv("ANDROID_PLUGIN_DATADIR=" + pluginDataDir.getPath());
|
||||
|
||||
File pluginPrivateDataDir = context.getDir("plugins_private", 0);
|
||||
putenv("ANDROID_PLUGIN_DATADIR_PRIVATE=" + pluginPrivateDataDir.getPath());
|
||||
|
||||
} catch (Exception ex) {
|
||||
Log.w(LOGTAG, "Caught exception getting plugin dirs.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static void setupDownloadEnvironment(final Context context) {
|
||||
try {
|
||||
File downloadDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
|
||||
@ -134,7 +106,7 @@ public final class GeckoLoader {
|
||||
}
|
||||
}
|
||||
|
||||
public static void setupGeckoEnvironment(Context context, String[] pluginDirs, String profilePath) {
|
||||
public static void setupGeckoEnvironment(Context context, String profilePath) {
|
||||
// if we have an intent (we're being launched by an activity)
|
||||
// read in any environmental variables from it here
|
||||
final SafeIntent intent = sIntent;
|
||||
@ -155,7 +127,6 @@ public final class GeckoLoader {
|
||||
|
||||
putenv("MOZ_ANDROID_PACKAGE_NAME=" + context.getPackageName());
|
||||
|
||||
setupPluginEnvironment(context, pluginDirs);
|
||||
setupDownloadEnvironment(context);
|
||||
|
||||
// profile home path
|
||||
|
@ -1,17 +0,0 @@
|
||||
<html style="margin: 0; padding: 0">
|
||||
<head>
|
||||
<title>Adobe Flash Test</title>
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0"/>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
<body style="margin: 0; padding: 0">
|
||||
<object width="100" height="100"
|
||||
classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"
|
||||
codebase="http://fpdownload.macromedia.com/
|
||||
pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0">
|
||||
<param name="SRC" value="green.swf">
|
||||
<embed src="green.swf" width="100" height="100">
|
||||
</embed>
|
||||
</object>
|
||||
</body>
|
||||
</html>
|
@ -81,7 +81,6 @@ public class StringHelper {
|
||||
public final String ROBOCOP_PICTURE_LINK_URL = "/robocop/robocop_picture_link.html";
|
||||
public final String ROBOCOP_SEARCH_URL = "/robocop/robocop_search.html";
|
||||
public final String ROBOCOP_TEXT_PAGE_URL = "/robocop/robocop_text_page.html";
|
||||
public final String ROBOCOP_ADOBE_FLASH_URL = "/robocop/robocop_adobe_flash.html";
|
||||
public final String ROBOCOP_INPUT_URL = "/robocop/robocop_input.html";
|
||||
public final String ROBOCOP_READER_MODE_BASIC_ARTICLE = "/robocop/reader_mode_pages/basic_article.html";
|
||||
public final String ROBOCOP_LINK_TO_SLOW_LOADING = "/robocop/robocop_link_to_slow_loading.html";
|
||||
@ -218,8 +217,6 @@ public class StringHelper {
|
||||
public final String ADVANCED;
|
||||
public final String DONT_SHOW_MENU;
|
||||
public final String SHOW_MENU;
|
||||
public final String DISABLED;
|
||||
public final String TAP_TO_PLAY;
|
||||
public final String HIDE_TITLE_BAR;
|
||||
public final String RESTORE_TABS_LABEL;
|
||||
|
||||
@ -401,8 +398,6 @@ public class StringHelper {
|
||||
ADVANCED = res.getString(R.string.pref_category_advanced);
|
||||
DONT_SHOW_MENU = res.getString(R.string.pref_char_encoding_off);
|
||||
SHOW_MENU = res.getString(R.string.pref_char_encoding_on);
|
||||
DISABLED = res.getString(R.string.pref_plugins_disabled );
|
||||
TAP_TO_PLAY = res.getString(R.string.pref_plugins_tap_to_play);
|
||||
HIDE_TITLE_BAR = res.getString(R.string.pref_scroll_title_bar_summary );
|
||||
RESTORE_TABS_LABEL = res.getString(R.string.pref_restore);
|
||||
|
||||
|
@ -1,33 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko.tests;
|
||||
|
||||
import org.json.JSONObject;
|
||||
import org.mozilla.gecko.PaintedSurface;
|
||||
|
||||
import android.os.Build;
|
||||
|
||||
/**
|
||||
* Tests that Flash is working
|
||||
* - loads a page containing a Flash plugin
|
||||
* - verifies it rendered properly
|
||||
*/
|
||||
public class testAdobeFlash extends PixelTest {
|
||||
public void testLoad() {
|
||||
// Enable plugins
|
||||
setPreferenceAndWaitForChange("plugin.enable", "1");
|
||||
|
||||
blockForGeckoReady();
|
||||
|
||||
String url = getAbsoluteUrl(mStringHelper.ROBOCOP_ADOBE_FLASH_URL);
|
||||
PaintedSurface painted = loadAndGetPainted(url);
|
||||
|
||||
mAsserter.ispixel(painted.getPixelAt(0, 0), 0, 0xff, 0, "Pixel at 0, 0");
|
||||
mAsserter.ispixel(painted.getPixelAt(50, 50), 0, 0xff, 0, "Pixel at 50, 50");
|
||||
mAsserter.ispixel(painted.getPixelAt(101, 0), 0xff, 0xff, 0xff, "Pixel at 101, 0");
|
||||
mAsserter.ispixel(painted.getPixelAt(0, 101), 0xff, 0xff, 0xff, "Pixel at 0, 101");
|
||||
|
||||
}
|
||||
}
|
@ -465,14 +465,6 @@ auto GeckoAppShell::KillAnyZombies() -> void
|
||||
return mozilla::jni::Method<KillAnyZombies_t>::Call(GeckoAppShell::Context(), nullptr);
|
||||
}
|
||||
|
||||
constexpr char GeckoAppShell::LoadPluginClass_t::name[];
|
||||
constexpr char GeckoAppShell::LoadPluginClass_t::signature[];
|
||||
|
||||
auto GeckoAppShell::LoadPluginClass(mozilla::jni::String::Param a0, mozilla::jni::String::Param a1) -> mozilla::jni::Class::LocalRef
|
||||
{
|
||||
return mozilla::jni::Method<LoadPluginClass_t>::Call(GeckoAppShell::Context(), nullptr, a0, a1);
|
||||
}
|
||||
|
||||
constexpr char GeckoAppShell::LockScreenOrientation_t::name[];
|
||||
constexpr char GeckoAppShell::LockScreenOrientation_t::signature[];
|
||||
|
||||
|
@ -1256,27 +1256,6 @@ public:
|
||||
|
||||
static auto KillAnyZombies() -> void;
|
||||
|
||||
struct LoadPluginClass_t {
|
||||
typedef GeckoAppShell Owner;
|
||||
typedef mozilla::jni::Class::LocalRef ReturnType;
|
||||
typedef mozilla::jni::Class::Param SetterType;
|
||||
typedef mozilla::jni::Args<
|
||||
mozilla::jni::String::Param,
|
||||
mozilla::jni::String::Param> Args;
|
||||
static constexpr char name[] = "loadPluginClass";
|
||||
static constexpr char signature[] =
|
||||
"(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Class;";
|
||||
static const bool isStatic = true;
|
||||
static const mozilla::jni::ExceptionMode exceptionMode =
|
||||
mozilla::jni::ExceptionMode::ABORT;
|
||||
static const mozilla::jni::CallingThread callingThread =
|
||||
mozilla::jni::CallingThread::ANY;
|
||||
static const mozilla::jni::DispatchTarget dispatchTarget =
|
||||
mozilla::jni::DispatchTarget::CURRENT;
|
||||
};
|
||||
|
||||
static auto LoadPluginClass(mozilla::jni::String::Param, mozilla::jni::String::Param) -> mozilla::jni::Class::LocalRef;
|
||||
|
||||
struct LockScreenOrientation_t {
|
||||
typedef GeckoAppShell Owner;
|
||||
typedef void ReturnType;
|
||||
|
Loading…
Reference in New Issue
Block a user