Bug 1367079 - 5. Add TextSelection support in custom tabs and PWA; r=snorp draft
authorJim Chen <nchen@mozilla.com>
Fri, 15 Sep 2017 14:44:51 -0400
changeset 665616 62551fed32177d21a487f8c7fcebd56de0fc90af
parent 665615 456512bb53b3b188a42bee42cb94c5fb4e115e07
child 665617 5a7dc7967a30d3461be0800c335d22132eafa517
push id80120
push userbmo:nchen@mozilla.com
push dateFri, 15 Sep 2017 18:49:36 +0000
reviewerssnorp
bugs1367079
milestone57.0a1
Bug 1367079 - 5. Add TextSelection support in custom tabs and PWA; r=snorp Add TextSelection support in custom tabs and PWA. MozReview-Commit-ID: AcHjMfJ8onU
mobile/android/base/java/org/mozilla/gecko/customtabs/CustomTabsActivity.java
mobile/android/base/java/org/mozilla/gecko/webapps/WebAppActivity.java
--- a/mobile/android/base/java/org/mozilla/gecko/customtabs/CustomTabsActivity.java
+++ b/mobile/android/base/java/org/mozilla/gecko/customtabs/CustomTabsActivity.java
@@ -17,16 +17,17 @@ import android.os.Bundle;
 import android.provider.Browser;
 import android.support.annotation.ColorInt;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.support.design.widget.Snackbar;
 import android.support.v4.util.SparseArrayCompat;
 import android.support.v7.app.ActionBar;
 import android.support.v7.app.AppCompatActivity;
+import android.support.v7.view.ActionMode;
 import android.support.v7.widget.Toolbar;
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.View;
 import android.widget.ListView;
@@ -45,29 +46,32 @@ import org.mozilla.gecko.Telemetry;
 import org.mozilla.gecko.TelemetryContract;
 import org.mozilla.gecko.menu.GeckoMenu;
 import org.mozilla.gecko.menu.GeckoMenuInflater;
 import org.mozilla.gecko.mozglue.SafeIntent;
 import org.mozilla.gecko.permissions.Permissions;
 import org.mozilla.gecko.prompts.Prompt;
 import org.mozilla.gecko.prompts.PromptListItem;
 import org.mozilla.gecko.prompts.PromptService;
+import org.mozilla.gecko.text.TextSelection;
 import org.mozilla.gecko.util.ActivityUtils;
 import org.mozilla.gecko.util.Clipboard;
 import org.mozilla.gecko.util.ColorUtil;
 import org.mozilla.gecko.util.GeckoBundle;
 import org.mozilla.gecko.util.IntentUtils;
 import org.mozilla.gecko.util.PackageUtil;
 import org.mozilla.gecko.util.ThreadUtils;
+import org.mozilla.gecko.widget.ActionModePresenter;
 import org.mozilla.gecko.widget.GeckoPopupMenu;
 
 import java.util.List;
 
 public class CustomTabsActivity extends AppCompatActivity
-                                implements GeckoMenu.Callback,
+                                implements ActionModePresenter,
+                                           GeckoMenu.Callback,
                                            GeckoView.ContentListener,
                                            GeckoView.NavigationListener,
                                            GeckoView.ProgressListener {
 
     private static final String LOGTAG = "CustomTabsActivity";
 
     private final SparseArrayCompat<PendingIntent> menuItemsIntent = new SparseArrayCompat<>();
     private GeckoPopupMenu popupMenu;
@@ -79,16 +83,19 @@ public class CustomTabsActivity extends 
 
     private MenuItem menuItemControl;
 
     private GeckoView mGeckoView;
     private PromptService mPromptService;
     private DoorHangerPopup mDoorHangerPopup;
     private FormAssistPopup mFormAssistPopup;
 
+    private ActionMode mActionMode;
+    private TextSelection mTextSelection;
+
     private boolean mCanGoBack = false;
     private boolean mCanGoForward = false;
     private boolean mCanStop = false;
     private String mCurrentUrl;
     private String mCurrentTitle;
     private SecurityInformation mSecurityInformation = null;
 
     @Override
@@ -120,29 +127,33 @@ public class CustomTabsActivity extends 
         mGeckoView.setContentListener(this);
 
         mPromptService = new PromptService(this, mGeckoView.getEventDispatcher());
         mDoorHangerPopup = new DoorHangerPopup(this, mGeckoView.getEventDispatcher());
 
         mFormAssistPopup = (FormAssistPopup) findViewById(R.id.form_assist_popup);
         mFormAssistPopup.create(mGeckoView);
 
+        mTextSelection = TextSelection.Factory.create(mGeckoView, this);
+        mTextSelection.create();
+
         final GeckoViewSettings settings = mGeckoView.getSettings();
         settings.setBoolean(GeckoViewSettings.USE_MULTIPROCESS, false);
 
         if (intent != null && !TextUtils.isEmpty(intent.getDataString())) {
             mGeckoView.loadUri(intent.getDataString());
         } else {
             Log.w(LOGTAG, "No intend found for custom tab");
             finish();
         }
     }
 
     @Override
     public void onDestroy() {
+        mTextSelection.destroy();
         mFormAssistPopup.destroy();
         mDoorHangerPopup.destroy();
         mPromptService.destroy();
 
         super.onDestroy();
     }
 
     @Override
@@ -665,9 +676,23 @@ public class CustomTabsActivity extends 
         final String scheme = uri.getScheme();
         // currently we only support http and https to open in Firefox
         if (scheme.equals("http") || scheme.equals("https")) {
             return uri;
         } else {
             return null;
         }
     }
+
+    @Override // ActionModePresenter
+    public void startActionMode(final ActionMode.Callback callback) {
+        endActionMode();
+        mActionMode = startSupportActionMode(callback);
+    }
+
+    @Override // ActionModePresenter
+    public void endActionMode() {
+        if (mActionMode != null) {
+            mActionMode.finish();
+            mActionMode = null;
+        }
+    }
 }
--- a/mobile/android/base/java/org/mozilla/gecko/webapps/WebAppActivity.java
+++ b/mobile/android/base/java/org/mozilla/gecko/webapps/WebAppActivity.java
@@ -15,48 +15,55 @@ import android.content.Intent;
 import android.content.pm.ActivityInfo;
 import android.graphics.Bitmap;
 import android.net.Uri;
 import android.os.Build;
 import android.os.Bundle;
 import android.support.customtabs.CustomTabsIntent;
 import android.support.v7.app.ActionBar;
 import android.support.v7.app.AppCompatActivity;
+import android.support.v7.view.ActionMode;
 import android.support.v7.widget.Toolbar;
 import android.util.Log;
 import android.view.View;
 import android.view.Window;
 import android.view.WindowManager;
 import android.widget.TextView;
 
 import org.mozilla.gecko.ActivityHandlerHelper;
 import org.mozilla.gecko.AppConstants;
-import org.mozilla.gecko.customtabs.CustomTabsActivity;
 import org.mozilla.gecko.DoorHangerPopup;
 import org.mozilla.gecko.GeckoScreenOrientation;
 import org.mozilla.gecko.GeckoView;
 import org.mozilla.gecko.GeckoViewSettings;
+import org.mozilla.gecko.R;
+import org.mozilla.gecko.customtabs.CustomTabsActivity;
 import org.mozilla.gecko.permissions.Permissions;
 import org.mozilla.gecko.prompts.PromptService;
-import org.mozilla.gecko.R;
+import org.mozilla.gecko.text.TextSelection;
 import org.mozilla.gecko.util.ActivityUtils;
 import org.mozilla.gecko.util.ColorUtil;
+import org.mozilla.gecko.widget.ActionModePresenter;
 
 public class WebAppActivity extends AppCompatActivity
-                            implements GeckoView.NavigationListener {
+                            implements ActionModePresenter,
+                                       GeckoView.NavigationListener {
     private static final String LOGTAG = "WebAppActivity";
 
     public static final String MANIFEST_PATH = "MANIFEST_PATH";
     public static final String MANIFEST_URL = "MANIFEST_URL";
     private static final String SAVED_INTENT = "savedIntent";
 
     private GeckoView mGeckoView;
     private PromptService mPromptService;
     private DoorHangerPopup mDoorHangerPopup;
 
+    private ActionMode mActionMode;
+    private TextSelection mTextSelection;
+
     private boolean mIsFullScreenMode;
     private boolean mIsFullScreenContent;
     private boolean mCanGoBack;
 
     private Uri mManifestUrl;
     private Uri mStartUrl;
     private Uri mScope;
 
@@ -88,31 +95,35 @@ public class WebAppActivity extends AppC
             public void onFullScreen(GeckoView view, boolean fullScreen) {
                 updateFullScreenContent(fullScreen);
             }
         });
 
         mPromptService = new PromptService(this, mGeckoView.getEventDispatcher());
         mDoorHangerPopup = new DoorHangerPopup(this, mGeckoView.getEventDispatcher());
 
+        mTextSelection = TextSelection.Factory.create(mGeckoView, this);
+        mTextSelection.create();
+
         final GeckoViewSettings settings = mGeckoView.getSettings();
         settings.setBoolean(GeckoViewSettings.USE_MULTIPROCESS, false);
 
         mManifest = WebAppManifest.fromFile(getIntent().getStringExtra(MANIFEST_URL),
                                             getIntent().getStringExtra(MANIFEST_PATH));
 
         updateFromManifest();
 
         mGeckoView.loadUri(mManifest.getStartUri().toString());
 
         setContentView(mGeckoView);
     }
 
     @Override
     public void onDestroy() {
+        mTextSelection.destroy();
         mDoorHangerPopup.destroy();
         mPromptService.destroy();
 
         super.onDestroy();
     }
 
     @Override
     public void onActivityResult(int requestCode, int resultCode, Intent data) {
@@ -279,9 +290,23 @@ public class WebAppActivity extends AppC
         mIsFullScreenContent = fullScreen;
         updateFullScreen();
     }
 
     private void updateFullScreenMode(boolean fullScreen) {
         mIsFullScreenMode = fullScreen;
         updateFullScreen();
     }
+
+    @Override // ActionModePresenter
+    public void startActionMode(final ActionMode.Callback callback) {
+        endActionMode();
+        mActionMode = startSupportActionMode(callback);
+    }
+
+    @Override // ActionModePresenter
+    public void endActionMode() {
+        if (mActionMode != null) {
+            mActionMode.finish();
+            mActionMode = null;
+        }
+    }
 }