mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 11:55:49 +00:00
Bug 1588150 - Add Install AddOn to GVE. r=snorp
This patch adds a new menu item to GVE that allows users to install an arbitrary extension given it's URL (usually from a.m.o, but we don't really verify that). Differential Revision: https://phabricator.services.mozilla.com/D59973 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
acf609f3d9
commit
f3a473d590
@ -29,6 +29,7 @@ import org.mozilla.geckoview.WebResponse;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.DownloadManager;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationChannel;
|
||||
@ -46,12 +47,14 @@ import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.os.SystemClock;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.ActivityCompat;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import android.support.v4.app.NotificationManagerCompat;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.text.InputType;
|
||||
import android.util.Log;
|
||||
import android.util.LruCache;
|
||||
import android.view.LayoutInflater;
|
||||
@ -61,6 +64,7 @@ import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.RelativeLayout;
|
||||
|
||||
@ -88,7 +92,9 @@ interface BrowserActionDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
class WebExtensionManager implements WebExtension.ActionDelegate, TabSessionManager.TabObserver {
|
||||
class WebExtensionManager implements WebExtension.ActionDelegate,
|
||||
WebExtensionController.PromptDelegate,
|
||||
TabSessionManager.TabObserver {
|
||||
public WebExtension extension;
|
||||
|
||||
private LruCache<WebExtension.Icon, Bitmap> mBitmapCache = new LruCache<>(5);
|
||||
@ -97,6 +103,12 @@ class WebExtensionManager implements WebExtension.ActionDelegate, TabSessionMana
|
||||
|
||||
private WeakReference<BrowserActionDelegate> mActionDelegate;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public GeckoResult<AllowOrDeny> onInstallPrompt(final @NonNull WebExtension extension) {
|
||||
return GeckoResult.fromValue(AllowOrDeny.ALLOW);
|
||||
}
|
||||
|
||||
// We only support either one browserAction or one pageAction
|
||||
private void onAction(final WebExtension extension, final GeckoSession session,
|
||||
final WebExtension.Action action) {
|
||||
@ -181,7 +193,7 @@ class WebExtensionManager implements WebExtension.ActionDelegate, TabSessionMana
|
||||
return;
|
||||
}
|
||||
|
||||
if (resolved.enabled == null || !resolved.enabled) {
|
||||
if (resolved == null || resolved.enabled == null || !resolved.enabled) {
|
||||
actionDelegate.onActionButton(null);
|
||||
return;
|
||||
}
|
||||
@ -208,7 +220,10 @@ class WebExtensionManager implements WebExtension.ActionDelegate, TabSessionMana
|
||||
}
|
||||
|
||||
public void onClicked(TabSession session) {
|
||||
actionFor(session).click();
|
||||
WebExtension.Action action = actionFor(session);
|
||||
if (action != null) {
|
||||
action.click();
|
||||
}
|
||||
}
|
||||
|
||||
public void setActionDelegate(BrowserActionDelegate delegate) {
|
||||
@ -229,12 +244,37 @@ class WebExtensionManager implements WebExtension.ActionDelegate, TabSessionMana
|
||||
}
|
||||
}
|
||||
|
||||
public WebExtensionManager(GeckoRuntime runtime) {
|
||||
public GeckoResult<Void> unregisterExtension(TabSessionManager tabManager) {
|
||||
if (extension == null) {
|
||||
return GeckoResult.fromValue(null);
|
||||
}
|
||||
|
||||
tabManager.unregisterWebExtension();
|
||||
|
||||
return mRuntime.getWebExtensionController().uninstall(extension).accept((unused) -> {
|
||||
extension = null;
|
||||
mDefaultAction = null;
|
||||
updateAction(null);
|
||||
});
|
||||
}
|
||||
|
||||
public void registerExtension(WebExtension extension,
|
||||
TabSessionManager tabManager) {
|
||||
extension.setActionDelegate(this);
|
||||
tabManager.setWebExtensionActionDelegate(extension, this);
|
||||
this.extension = extension;
|
||||
}
|
||||
|
||||
public WebExtensionManager(GeckoRuntime runtime,
|
||||
TabSessionManager tabManager) {
|
||||
runtime.getWebExtensionController()
|
||||
.list().accept(extensions -> {
|
||||
for (final WebExtension extension : extensions) {
|
||||
registerExtension(extension, tabManager);
|
||||
}
|
||||
});
|
||||
|
||||
mRuntime = runtime;
|
||||
// TODO: allow users to install an extension from file
|
||||
// extension = new WebExtension("resource://android/assets/chill-out/");
|
||||
// extension.setActionDelegate(this);
|
||||
// mRuntime.registerWebExtension(extension);
|
||||
}
|
||||
}
|
||||
|
||||
@ -365,12 +405,14 @@ public class GeckoViewActivity
|
||||
@Override
|
||||
public GeckoResult<AllowOrDeny> onCloseTab(WebExtension source, GeckoSession session) {
|
||||
TabSession tabSession = mTabSessionManager.getSession(session);
|
||||
if (tabSession != null) {
|
||||
closeTab(tabSession);
|
||||
}
|
||||
return GeckoResult.fromValue(AllowOrDeny.ALLOW);
|
||||
}
|
||||
});
|
||||
|
||||
sExtensionManager = new WebExtensionManager(sGeckoRuntime);
|
||||
sExtensionManager = new WebExtensionManager(sGeckoRuntime, mTabSessionManager);
|
||||
mTabSessionManager.setTabObserver(sExtensionManager);
|
||||
|
||||
// `getSystemService` call requires API level 23
|
||||
@ -483,8 +525,19 @@ public class GeckoViewActivity
|
||||
|
||||
ViewGroup.LayoutParams params = mPopupView.getLayoutParams();
|
||||
boolean shouldShow = force || params.width == 0;
|
||||
setPopupVisibility(shouldShow);
|
||||
|
||||
if (shouldShow) {
|
||||
return shouldShow ? mPopupSession : null;
|
||||
}
|
||||
|
||||
private void setPopupVisibility(boolean visible) {
|
||||
if (mPopupView == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
ViewGroup.LayoutParams params = mPopupView.getLayoutParams();
|
||||
|
||||
if (visible) {
|
||||
params.height = 1100;
|
||||
params.width = 1200;
|
||||
} else {
|
||||
@ -493,7 +546,6 @@ public class GeckoViewActivity
|
||||
}
|
||||
|
||||
mPopupView.setLayoutParams(params);
|
||||
return shouldShow ? mPopupSession : null;
|
||||
}
|
||||
|
||||
private void openPopupSession() {
|
||||
@ -701,6 +753,9 @@ public class GeckoViewActivity
|
||||
mUsePrivateBrowsing = !mUsePrivateBrowsing;
|
||||
recreateSession();
|
||||
break;
|
||||
case R.id.install_addon:
|
||||
installAddon();
|
||||
break;
|
||||
case R.id.action_new_tab:
|
||||
createNewTab();
|
||||
break;
|
||||
@ -718,6 +773,37 @@ public class GeckoViewActivity
|
||||
return true;
|
||||
}
|
||||
|
||||
private void installAddon() {
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setTitle(R.string.install_addon);
|
||||
|
||||
final EditText input = new EditText(this);
|
||||
input.setInputType(InputType.TYPE_CLASS_TEXT);
|
||||
input.setHint(R.string.install_addon_hint);
|
||||
builder.setView(input);
|
||||
|
||||
builder.setPositiveButton(R.string.install, (dialog, which) -> {
|
||||
final String uri = input.getText().toString();
|
||||
|
||||
// We only suopport one extension at a time, so remove the currently installed
|
||||
// extension if there is one
|
||||
setPopupVisibility(false);
|
||||
mPopupView = null;
|
||||
mPopupSession = null;
|
||||
sExtensionManager.unregisterExtension(mTabSessionManager).then(unused -> {
|
||||
final WebExtensionController controller = sGeckoRuntime.getWebExtensionController();
|
||||
controller.setPromptDelegate(sExtensionManager);
|
||||
return controller.install(uri);
|
||||
}).accept(extension ->
|
||||
sExtensionManager.registerExtension(extension, mTabSessionManager));
|
||||
});
|
||||
builder.setNegativeButton(R.string.cancel, (dialog, which) -> {
|
||||
// Nothing to do
|
||||
});
|
||||
|
||||
builder.show();
|
||||
}
|
||||
|
||||
private void createNewTab() {
|
||||
TabSession newSession = createSession();
|
||||
newSession.open(sGeckoRuntime);
|
||||
|
@ -4,6 +4,7 @@ import android.support.annotation.Nullable;
|
||||
|
||||
import org.mozilla.geckoview.GeckoSession;
|
||||
import org.mozilla.geckoview.GeckoSessionSettings;
|
||||
import org.mozilla.geckoview.WebExtension;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@ -19,6 +20,19 @@ public class TabSessionManager {
|
||||
public TabSessionManager() {
|
||||
}
|
||||
|
||||
public void unregisterWebExtension() {
|
||||
for (final TabSession session : mTabSessions) {
|
||||
session.action = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void setWebExtensionActionDelegate(WebExtension extension,
|
||||
WebExtension.ActionDelegate delegate) {
|
||||
for (final TabSession session : mTabSessions) {
|
||||
session.setWebExtensionActionDelegate(extension, delegate);
|
||||
}
|
||||
}
|
||||
|
||||
public void setTabObserver(TabObserver observer) {
|
||||
mTabObserver = observer;
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
<item android:title="@string/private_browsing" android:checkable="true" android:id="@+id/action_pb"/>
|
||||
<item android:title="@string/remote_debugging" android:checkable="true" android:id="@+id/action_remote_debugging"/>
|
||||
<item android:title="@string/new_tab" android:id="@+id/action_new_tab"/>
|
||||
<item android:title="@string/install_addon" android:id="@+id/install_addon"/>
|
||||
<item android:title="@string/close_tab" android:id="@+id/action_close_tab"/>
|
||||
<item android:title="@string/forward" android:id="@+id/action_forward"/>
|
||||
<item android:title="@string/reload" android:id="@+id/action_reload"/>
|
||||
|
@ -36,9 +36,14 @@
|
||||
<string name="device_sharing_camera">Camera is on</string>
|
||||
<string name="device_sharing_camera_and_mic">Camera and microphone are on</string>
|
||||
<string name="new_tab">New tab</string>
|
||||
<string name="install_addon">Install Add-on...</string>
|
||||
<string name="install_addon_hint">Add-on URL: https://addons.mozilla.org/...</string>
|
||||
<string name="close_tab">Close tab</string>
|
||||
<string name="desktop_mode">Desktop site</string>
|
||||
<string name="slow_script">A script on this page is causing your web browser to run slowly</string>
|
||||
<string name="wait">Wait</string>
|
||||
<string name="stop">Stop</string>
|
||||
<string name="install">Install</string>
|
||||
<string name="cancel">Cancel</string>
|
||||
<string name="addon_uri">WebExtension xpi URL</string>
|
||||
</resources>
|
||||
|
Loading…
Reference in New Issue
Block a user