Bug 1381916 - Remove frontend support for plugins in Fennec r=nechen draft
authorJames Willcox <snorp@snorp.net>
Tue, 18 Jul 2017 15:46:53 -0500
changeset 610874 19051075bd39e5d894a07a1024a0760898f19ac9
parent 610765 66c0563595f422371977b8f1735cee995a52fd25
child 610875 d20cf92a957f805d8acca7c7b0bca1842655c328
push id69022
push userbmo:snorp@snorp.net
push dateTue, 18 Jul 2017 21:31:31 +0000
reviewersnechen
bugs1381916
milestone56.0a1
Bug 1381916 - Remove frontend support for plugins in Fennec r=nechen MozReview-Commit-ID: Gkqe8Y5AMPV
mobile/android/app/mobile.js
mobile/android/app/src/main/res/layout/gecko_app.xml
mobile/android/app/src/main/res/values/arrays.xml
mobile/android/app/src/main/res/xml/preferences_advanced.xml
mobile/android/base/java/org/mozilla/gecko/GeckoApp.java
mobile/android/base/locales/en-US/android_strings.dtd
mobile/android/base/strings.xml.in
mobile/android/chrome/content/browser.js
mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoAppShell.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoThread.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/mozglue/GeckoLoader.java
widget/android/GeneratedJNIWrappers.cpp
widget/android/GeneratedJNIWrappers.h
--- a/mobile/android/app/mobile.js
+++ b/mobile/android/app/mobile.js
@@ -442,25 +442,19 @@ pref("ui.mouse.radius.reposition", true)
 // manipulation is allowed.
 pref("browser.ui.scroll-toolbar-threshold", 10);
 
 // Maximum distance from the point where the user pressed where we still
 // look for text to select
 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/");
 
 pref("app.support.baseURL", "https://support.mozilla.org/1/mobile/%VERSION%/%OS%/%LOCALE%/");
 pref("app.supportURL", "https://support.mozilla.org/1/mobile/%VERSION%/%OS%/%LOCALE%/mobile-help");
 pref("app.faqURL", "https://support.mozilla.org/1/mobile/%VERSION%/%OS%/%LOCALE%/faq");
 
--- a/mobile/android/app/src/main/res/layout/gecko_app.xml
+++ b/mobile/android/app/src/main/res/layout/gecko_app.xml
@@ -27,21 +27,16 @@
                         android:layout_above="@+id/find_in_page">
 
             <fragment class="org.mozilla.gecko.GeckoViewFragment"
                       android:id="@+id/layer_view"
                       android:layout_width="match_parent"
                       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"
                                                android:visibility="gone"/>
 
             <view class="org.mozilla.gecko.media.VideoPlayer" android:id="@+id/video_player"
                          android:layout_height="match_parent"
                          android:layout_width="match_parent">
--- a/mobile/android/app/src/main/res/values/arrays.xml
+++ b/mobile/android/app/src/main/res/values/arrays.xml
@@ -8,26 +8,16 @@
     <string-array name="pref_home_updates_entries">
         <item>@string/pref_home_updates_enabled</item>
         <item>@string/pref_home_updates_wifi</item>
     </string-array>
     <string-array name="pref_home_updates_values">
         <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>
     </string-array>
     <string-array name="pref_char_encoding_values">
         <item>true</item>
         <item>false</item>
     </string-array>
--- a/mobile/android/app/src/main/res/xml/preferences_advanced.xml
+++ b/mobile/android/app/src/main/res/xml/preferences_advanced.xml
@@ -49,22 +49,16 @@
         <SwitchPreference android:key="browser.display.use_document_fonts"
                           android:title="@string/pref_show_web_fonts"
                           android:summary="@string/pref_show_web_fonts_summary"/>
 
     </PreferenceCategory>
 
     <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" />
 
     </PreferenceCategory>
 
     <PreferenceCategory android:title="@string/pref_category_developer_tools">
 
--- a/mobile/android/base/java/org/mozilla/gecko/GeckoApp.java
+++ b/mobile/android/base/java/org/mozilla/gecko/GeckoApp.java
@@ -189,19 +189,16 @@ public abstract class GeckoApp extends G
     private PromptService mPromptService;
     protected TextSelection mTextSelection;
 
     protected DoorHangerPopup mDoorHangerPopup;
     protected FormAssistPopup mFormAssistPopup;
 
     protected GeckoView mLayerView;
 
-    private FullScreenHolder mFullScreenPluginContainer;
-    private View mFullScreenPluginView;
-
     protected boolean mLastSessionCrashed;
     protected boolean mShouldRestore;
     private boolean mSessionRestoreParsingFinished = false;
 
     private boolean foregrounded = false;
 
     private static final class LastSessionParser extends SessionParser {
         private JSONArray tabs;
@@ -804,21 +801,16 @@ public abstract class GeckoApp extends G
             UpdateServiceHelper.checkForUpdate(this);
 
         } else if ("Update:Download".equals(event)) {
             UpdateServiceHelper.downloadUpdate(this);
 
         } 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);
 
         } else if ("Mma:web_save_media".equals(event) || "Mma:web_save_image".equals(event)) {
             MmaDelegate.track(DOWNLOAD_MEDIA_SAVED_IMAGE);
 
         }
 
@@ -912,123 +904,16 @@ public abstract class GeckoApp extends G
                     clearButton.setEnabled(false);
                 } else {
                     clearButton.setEnabled(true);
                 }
             }
         });
     }
 
-    /* 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
             public void run() {
                 if (!success) {
                     SnackbarBuilder.builder(GeckoApp.this)
                             .message(message)
                             .duration(Snackbar.LENGTH_LONG)
@@ -1298,17 +1183,16 @@ public abstract class GeckoApp extends G
                 GeckoThread.speculativeConnect(uri);
             }
         }
 
         // To prevent races, register startup events before launching the Gecko thread.
         EventDispatcher.getInstance().registerGeckoThreadListener(this,
             "Accessibility:Ready",
             "Gecko:Ready",
-            "PluginHelper:playFlash",
             null);
 
         EventDispatcher.getInstance().registerUiThreadListener(this,
             "Update:Check",
             "Update:Download",
             "Update:Install",
             null);
 
@@ -2319,17 +2203,16 @@ public abstract class GeckoApp extends G
             // We did not initialize anything, so skip cleaning up.
             super.onDestroy();
             return;
         }
 
         EventDispatcher.getInstance().unregisterGeckoThreadListener(this,
             "Accessibility:Ready",
             "Gecko:Ready",
-            "PluginHelper:playFlash",
             null);
 
         EventDispatcher.getInstance().unregisterUiThreadListener(this,
             "Update:Check",
             "Update:Download",
             "Update:Install",
             null);
 
@@ -2534,22 +2417,16 @@ public abstract class GeckoApp extends G
             return;
         }
 
         if (mDoorHangerPopup != null && mDoorHangerPopup.isShowing()) {
             mDoorHangerPopup.dismiss();
             return;
         }
 
-        if (mFullScreenPluginView != null) {
-            onFullScreenPluginHidden(mFullScreenPluginView);
-            removeFullScreenPluginView(mFullScreenPluginView);
-            return;
-        }
-
         if (mLayerView != null && mLayerView.isFullScreen()) {
             EventDispatcher.getInstance().dispatch("FullScreen:Exit", null);
             return;
         }
 
         final Tabs tabs = Tabs.getInstance();
         final Tab tab = tabs.getSelectedTab();
         if (tab == null) {
@@ -2672,81 +2549,16 @@ public abstract class GeckoApp extends G
         public void setDrawingCacheEnabled(boolean enabled) {
             // Instead of setting drawing cache in the view itself, we simply
             // enable drawing caching on its children. This is mainly used in
             // animations (see PropertyAnimator)
             super.setChildrenDrawnWithCacheEnabled(enabled);
         }
     }
 
-    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 {
             versionCode = getPackageManager().getPackageInfo(getPackageName(), 0).versionCode;
         } catch (NameNotFoundException e) {
             Log.wtf(LOGTAG, getPackageName() + " not found", e);
         }
         return versionCode;
--- a/mobile/android/base/locales/en-US/android_strings.dtd
+++ b/mobile/android/base/locales/en-US/android_strings.dtd
@@ -356,20 +356,16 @@
 <!ENTITY pref_char_encoding_off "Don\'t show menu">
 <!ENTITY pref_clear_private_data2 "Clear private data">
 <!-- Localization note (pref_clear_private_data_now_tablet): This action to clear private data is only shown on tablets.
      The action is shown below a header saying "Clear private data"; See pref_clear_private_data -->
 <!ENTITY pref_clear_private_data_now_tablet "Clear now">
 <!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;">
 
 <!-- Localization note (pref_use_system_font_size, pref_use_system_font_size_summary):
      Font size here refers to the name of the corresponding Android system setting. -->
 <!ENTITY pref_use_system_font_size "Use system font size">
 <!ENTITY pref_use_system_font_size_summary "Scale web content according to the system font size">
--- a/mobile/android/base/strings.xml.in
+++ b/mobile/android/base/strings.xml.in
@@ -256,20 +256,16 @@
   <string name="pref_char_encoding">&pref_char_encoding;</string>
   <string name="pref_char_encoding_on">&pref_char_encoding_on;</string>
   <string name="pref_char_encoding_off">&pref_char_encoding_off;</string>
   <string name="pref_clear_private_data_now">&pref_clear_private_data2;</string>
   <string name="pref_clear_private_data_now_tablet">&pref_clear_private_data_now_tablet;</string>
   <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>
   <string name="pref_media_autoplay_enabled_summary">&pref_media_autoplay_enabled_summary;</string>
   <string name="pref_zoom_force_enabled">&pref_zoom_force_enabled;</string>
   <string name="pref_zoom_force_enabled_summary">&pref_zoom_force_enabled_summary;</string>
   <string name="pref_voice_input">&pref_voice_input;</string>
   <string name="pref_voice_input_summary">&pref_voice_input_summary2;</string>
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -124,17 +124,16 @@ XPCOMUtils.defineLazyServiceGetter(this,
   "@mozilla.org/gfx/fontenumerator;1",
   "nsIFontEnumerator");
 
 var GlobalEventDispatcher = EventDispatcher.instance;
 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"],
   ["RemoteDebugger", "chrome://browser/content/RemoteDebugger.js"],
 ];
 if (!AppConstants.RELEASE_OR_BETA) {
   lazilyLoadedBrowserScripts.push(
     ["WebcompatReporter", "chrome://browser/content/WebcompatReporter.js"]);
@@ -1009,23 +1008,16 @@ var BrowserApp = {
   _migrateUI: function() {
     const UI_VERSION = 3;
     let currentUIVersion = Services.prefs.getIntPref("browser.migration.version", 0);
     if (currentUIVersion >= UI_VERSION) {
       return;
     }
 
     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
         // three-state to two-state. (This reverts a setting of "please track me"
         // to the default "don't say anything").
         if (Services.prefs.getBoolPref("privacy.donottrackheader.enabled") &&
             (Services.prefs.getIntPref("privacy.donottrackheader.value") != 1)) {
           Services.prefs.clearUserPref("privacy.donottrackheader.enabled");
@@ -1950,22 +1942,16 @@ var BrowserApp = {
 
       case "android-get-pref": {
         // These pref names are not "real" pref names. They are used in the
         // setting menu, and these are passed when initializing the setting
         // menu. aSubject is a nsIWritableVariant to hold the pref value.
         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);
             break;
 
           case "privacy.trackingprotection.state": {
             aSubject.setAsAString(this.getTrackingProtectionState());
             break;
@@ -1986,23 +1972,16 @@ var BrowserApp = {
 
       case "android-set-pref": {
         // Pseudo-prefs. aSubject is an nsIWritableVariant that holds the pref
         // value. Set to empty to signal the pref was handled.
         aSubject.QueryInterface(Ci.nsIWritableVariant);
         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) {
               MasterPassword.removePassword(value);
             } else {
               MasterPassword.setPassword(value);
             }
             aSubject.setAsEmpty();
@@ -3468,19 +3447,16 @@ nsBrowserAccess.prototype = {
 
 function Tab(aURL, aParams) {
   this.filter = null;
   this.browser = null;
   this.id = 0;
   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;
   this.playingAudio = false;
 
   this.create(aURL, aParams);
 }
 
@@ -3638,17 +3614,16 @@ Tab.prototype = {
     this.browser.addEventListener("DOMAutoComplete", this, true);
     this.browser.addEventListener("blur", this, true);
     this.browser.addEventListener("pageshow", this, true);
     this.browser.addEventListener("MozApplicationManifest", this, true);
     this.browser.addEventListener("TabPreZombify", this, true);
     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);
 
     Services.obs.addObserver(this, "audioFocusChanged", false);
     Services.obs.addObserver(this, "before-first-paint");
     Services.obs.addObserver(this, "media-playback");
 
     // Always initialise new tabs with basic session store data to avoid
@@ -3753,17 +3728,16 @@ Tab.prototype = {
     this.browser.removeEventListener("DOMWillOpenModalDialog", this, true);
     this.browser.removeEventListener("DOMAutoComplete", this, true);
     this.browser.removeEventListener("blur", this, true);
     this.browser.removeEventListener("pageshow", this, true);
     this.browser.removeEventListener("MozApplicationManifest", this, true);
     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);
 
     Services.obs.removeObserver(this, "audioFocusChanged");
     Services.obs.removeObserver(this, "before-first-paint");
     Services.obs.removeObserver(this, "media-playback");
 
     // Make sure the previously selected panel remains selected. The selected panel of a deck is
@@ -4266,21 +4240,16 @@ Tab.prototype = {
       }
 
       case "DOMAutoComplete":
       case "blur": {
         LoginManagerContent.onUsernameInput(aEvent);
         break;
       }
 
-      case "PluginBindingAttached": {
-        PluginHelper.handlePluginBindingAttached(this, aEvent);
-        break;
-      }
-
       case "VideoBindingAttached": {
         CastingApps.handleVideoBindingAttached(this, aEvent);
         break;
       }
 
       case "VideoBindingCast": {
         CastingApps.handleVideoBindingCast(this, aEvent);
         break;
@@ -4449,22 +4418,16 @@ Tab.prototype = {
 
     // Let the reader logic know about same document changes because we won't get a DOMContentLoaded
     // or pageshow event, but we'll still want to update the reader view button to account for this change.
     // This mirrors the desktop logic in TabsProgressListener.
     if (aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_SAME_DOCUMENT) {
       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;
     if (principalURI && ["http", "https", "ftp"].includes(principalURI.scheme) && principalURI.host) {
       try {
         baseDomain = Services.eTLD.getBaseDomainFromHost(principalURI.host);
         if (!principalURI.host.endsWith(baseDomain)) {
           // getBaseDomainFromHost converts its resultant to ACE.
@@ -5914,17 +5877,17 @@ var IdentityHandler = {
       return this.IDENTITY_MODE_VERIFIED;
     }
 
     if (aState & Ci.nsIWebProgressListener.STATE_IS_SECURE) {
       return this.IDENTITY_MODE_IDENTIFIED;
     }
 
     // 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;
     }
 
     return this.IDENTITY_MODE_UNKNOWN;
   },
 
   getMixedDisplayMode: function getMixedDisplayMode(aState) {
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoAppShell.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoAppShell.java
@@ -1402,239 +1402,16 @@ public class GeckoAppShell
                                        Settings.System.TEXT_SHOW_PASSWORD, 1);
             return (showPassword > 0);
         }
         catch (Exception e) {
             return true;
         }
     }
 
-    /**
-     * 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
     public static Context getApplicationContext() {
         return sApplicationContext;
     }
 
     public static void setApplicationContext(final Context context) {
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoThread.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoThread.java
@@ -254,25 +254,18 @@ public class GeckoThread extends Thread 
         if (locale.toString().equalsIgnoreCase("zh_hk")) {
             final Locale mappedLocale = Locale.TRADITIONAL_CHINESE;
             Locale.setDefault(mappedLocale);
             Configuration config = res.getConfiguration();
             config.locale = mappedLocale;
             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);
 
         } catch (final Exception e) {
             // Cannot load libs; try clearing the cached files.
             Log.w(LOGTAG, "Clearing cache after load libs exception", e);
             FileUtils.delTree(GeckoLoader.getCacheDir(context),
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/mozglue/GeckoLoader.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/mozglue/GeckoLoader.java
@@ -52,44 +52,16 @@ public final class GeckoLoader {
 
     public static File getGREDir(Context context) {
         if (sGREDir == null) {
             sGREDir = new File(context.getApplicationInfo().dataDir);
         }
         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);
             File updatesDir  = context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS);
             if (downloadDir == null) {
                 downloadDir = new File(Environment.getExternalStorageDirectory().getPath(), "download");
             }
             if (updatesDir == null) {
@@ -129,17 +101,17 @@ public final class GeckoLoader {
     public static void addEnvironmentToIntent(Intent intent) {
         if (sEnvList != null) {
             for (int ix = 0; ix < sEnvList.length; ix++) {
                 intent.putExtra("env" + ix, sEnvList[ix]);
             }
         }
     }
 
-    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;
         if (intent != null) {
             final ArrayList<String> envList = new ArrayList<String>();
             String env = intent.getStringExtra("env0");
             Log.d(LOGTAG, "Gecko environment env0: " + env);
             for (int c = 1; env != null; c++) {
@@ -150,17 +122,16 @@ public final class GeckoLoader {
             }
             if (envList.size() > 0) {
               sEnvList = envList.toArray(new String[envList.size()]);
             }
         }
 
         putenv("MOZ_ANDROID_PACKAGE_NAME=" + context.getPackageName());
 
-        setupPluginEnvironment(context, pluginDirs);
         setupDownloadEnvironment(context);
 
         // profile home path
         putenv("HOME=" + profilePath);
 
         // setup the tmp path
         File f = getTmpDir(context);
         if (!f.exists()) {
--- a/widget/android/GeneratedJNIWrappers.cpp
+++ b/widget/android/GeneratedJNIWrappers.cpp
@@ -460,24 +460,16 @@ auto GeckoAppShell::IsTablet() -> bool
 constexpr char GeckoAppShell::KillAnyZombies_t::name[];
 constexpr char GeckoAppShell::KillAnyZombies_t::signature[];
 
 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[];
 
 auto GeckoAppShell::LockScreenOrientation(int32_t a0) -> void
 {
     return mozilla::jni::Method<LockScreenOrientation_t>::Call(GeckoAppShell::Context(), nullptr, a0);
 }
 
--- a/widget/android/GeneratedJNIWrappers.h
+++ b/widget/android/GeneratedJNIWrappers.h
@@ -1251,37 +1251,16 @@ public:
         static const mozilla::jni::CallingThread callingThread =
                 mozilla::jni::CallingThread::GECKO;
         static const mozilla::jni::DispatchTarget dispatchTarget =
                 mozilla::jni::DispatchTarget::CURRENT;
     };
 
     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;
         typedef void SetterType;
         typedef mozilla::jni::Args<
                 int32_t> Args;
         static constexpr char name[] = "lockScreenOrientation";
         static constexpr char signature[] =