Commit fa615b5f authored by Clark DuVall's avatar Clark DuVall Committed by Commit Bot

[WebLayer] Factor out common superclass for (Activity|Fragment)WindowAndroid

Since this superclass is mostly concerned with handling intents, the
best name I could come up with is IntentWindowAndroid.

Bug: 1017274
Change-Id: Iaadba0d7adbea13dc11bbaf88af1029d7dc4ebbe
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1876729
Commit-Queue: Clark DuVall <cduvall@chromium.org>
Reviewed-by: default avatarBo <boliu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#708836}
parent cc9424bf
...@@ -243,6 +243,7 @@ android_library("ui_full_java") { ...@@ -243,6 +243,7 @@ android_library("ui_full_java") {
"java/src/org/chromium/ui/base/ActivityAndroidPermissionDelegate.java", "java/src/org/chromium/ui/base/ActivityAndroidPermissionDelegate.java",
"java/src/org/chromium/ui/base/ActivityKeyboardVisibilityDelegate.java", "java/src/org/chromium/ui/base/ActivityKeyboardVisibilityDelegate.java",
"java/src/org/chromium/ui/base/ActivityWindowAndroid.java", "java/src/org/chromium/ui/base/ActivityWindowAndroid.java",
"java/src/org/chromium/ui/base/IntentWindowAndroid.java",
"java/src/org/chromium/ui/base/AndroidPermissionDelegate.java", "java/src/org/chromium/ui/base/AndroidPermissionDelegate.java",
"java/src/org/chromium/ui/base/Clipboard.java", "java/src/org/chromium/ui/base/Clipboard.java",
"java/src/org/chromium/ui/base/DeviceFormFactor.java", "java/src/org/chromium/ui/base/DeviceFormFactor.java",
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
package org.chromium.ui.base; package org.chromium.ui.base;
import android.app.Activity; import android.app.Activity;
import android.app.PendingIntent;
import android.content.ActivityNotFoundException; import android.content.ActivityNotFoundException;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
...@@ -14,7 +13,6 @@ import android.content.IntentSender.SendIntentException; ...@@ -14,7 +13,6 @@ import android.content.IntentSender.SendIntentException;
import org.chromium.base.ActivityState; import org.chromium.base.ActivityState;
import org.chromium.base.ApplicationStatus; import org.chromium.base.ApplicationStatus;
import org.chromium.base.Callback;
import org.chromium.base.ContextUtils; import org.chromium.base.ContextUtils;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
...@@ -25,13 +23,7 @@ import java.lang.ref.WeakReference; ...@@ -25,13 +23,7 @@ import java.lang.ref.WeakReference;
* Only instantiate this class when you need the implemented features. * Only instantiate this class when you need the implemented features.
*/ */
public class ActivityWindowAndroid public class ActivityWindowAndroid
extends WindowAndroid implements ApplicationStatus.ActivityStateListener { extends IntentWindowAndroid implements ApplicationStatus.ActivityStateListener {
// Constants used for intent request code bounding.
private static final int REQUEST_CODE_PREFIX = 1000;
private static final int REQUEST_CODE_RANGE_SIZE = 100;
private int mNextRequestCode;
private boolean mListenToActivityState; private boolean mListenToActivityState;
/** /**
...@@ -77,8 +69,8 @@ public class ActivityWindowAndroid ...@@ -77,8 +69,8 @@ public class ActivityWindowAndroid
return (ActivityKeyboardVisibilityDelegate) super.getKeyboardDelegate(); return (ActivityKeyboardVisibilityDelegate) super.getKeyboardDelegate();
} }
/** Uses the provided intent sender to start the intent. */ @Override
protected boolean startIntentSenderForResult(IntentSender intentSender, int requestCode) { protected final boolean startIntentSenderForResult(IntentSender intentSender, int requestCode) {
Activity activity = getActivity().get(); Activity activity = getActivity().get();
if (activity == null) return false; if (activity == null) return false;
...@@ -91,20 +83,7 @@ public class ActivityWindowAndroid ...@@ -91,20 +83,7 @@ public class ActivityWindowAndroid
} }
@Override @Override
public int showCancelableIntent( protected final boolean startActivityForResult(Intent intent, int requestCode) {
PendingIntent intent, IntentCallback callback, Integer errorId) {
int requestCode = generateNextRequestCode();
if (!startIntentSenderForResult(intent.getIntentSender(), requestCode)) {
return START_INTENT_FAILURE;
}
storeCallbackData(requestCode, callback, errorId);
return requestCode;
}
/** Starts an activity for the provided intent. */
protected boolean startActivityForResult(Intent intent, int requestCode) {
Activity activity = getActivity().get(); Activity activity = getActivity().get();
if (activity == null) return false; if (activity == null) return false;
...@@ -116,63 +95,6 @@ public class ActivityWindowAndroid ...@@ -116,63 +95,6 @@ public class ActivityWindowAndroid
return true; return true;
} }
@Override
public int showCancelableIntent(Intent intent, IntentCallback callback, Integer errorId) {
int requestCode = generateNextRequestCode();
if (!startActivityForResult(intent, requestCode)) {
return START_INTENT_FAILURE;
}
storeCallbackData(requestCode, callback, errorId);
return requestCode;
}
@Override
public int showCancelableIntent(Callback<Integer> intentTrigger, IntentCallback callback,
Integer errorId) {
Activity activity = getActivity().get();
if (activity == null) return START_INTENT_FAILURE;
int requestCode = generateNextRequestCode();
intentTrigger.onResult(requestCode);
storeCallbackData(requestCode, callback, errorId);
return requestCode;
}
@Override
public void cancelIntent(int requestCode) {
Activity activity = getActivity().get();
if (activity == null) return;
activity.finishActivity(requestCode);
}
/**
* Responds to the intent result if the intent was created by the native window.
* @param requestCode Request code of the requested intent.
* @param resultCode Result code of the requested intent.
* @param data The data returned by the intent.
* @return Boolean value of whether the intent was started by the native window.
*/
public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
IntentCallback callback = mOutstandingIntents.get(requestCode);
mOutstandingIntents.delete(requestCode);
String errorMessage = mIntentErrors.remove(requestCode);
if (callback != null) {
callback.onIntentCompleted(this, resultCode, data);
return true;
} else {
if (errorMessage != null) {
showCallbackNonExistentError(errorMessage);
return true;
}
}
return false;
}
@Override @Override
public WeakReference<Activity> getActivity() { public WeakReference<Activity> getActivity() {
return new WeakReference<>(ContextUtils.activityFromContext(getContext().get())); return new WeakReference<>(ContextUtils.activityFromContext(getContext().get()));
...@@ -197,16 +119,4 @@ public class ActivityWindowAndroid ...@@ -197,16 +119,4 @@ public class ActivityWindowAndroid
return mListenToActivityState ? ApplicationStatus.getStateForActivity(getActivity().get()) return mListenToActivityState ? ApplicationStatus.getStateForActivity(getActivity().get())
: super.getActivityState(); : super.getActivityState();
} }
private int generateNextRequestCode() {
int requestCode = REQUEST_CODE_PREFIX + mNextRequestCode;
mNextRequestCode = (mNextRequestCode + 1) % REQUEST_CODE_RANGE_SIZE;
return requestCode;
}
private void storeCallbackData(int requestCode, IntentCallback callback, Integer errorId) {
mOutstandingIntents.put(requestCode, callback);
mIntentErrors.put(requestCode,
errorId == null ? null : ContextUtils.getApplicationContext().getString(errorId));
}
} }
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.ui.base;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
import android.util.SparseArray;
import org.chromium.base.Callback;
import org.chromium.base.ContextUtils;
/**
* Base class for WindowAndroid implementations that need to send intents.
*/
public abstract class IntentWindowAndroid extends WindowAndroid {
// Constants used for intent request code bounding.
private static final int REQUEST_CODE_PREFIX = 1000;
private static final int REQUEST_CODE_RANGE_SIZE = 100;
private int mNextRequestCode;
private SparseArray<IntentCallback> mOutstandingIntents;
public IntentWindowAndroid(Context context) {
super(context);
mOutstandingIntents = new SparseArray<>();
}
/**
* Uses the provided intent sender to start the intent.
* @see Activity#startIntentSenderForResult
*/
protected abstract boolean startIntentSenderForResult(
IntentSender intentSender, int requestCode);
@Override
public int showCancelableIntent(
PendingIntent intent, IntentCallback callback, Integer errorId) {
int requestCode = generateNextRequestCode();
if (!startIntentSenderForResult(intent.getIntentSender(), requestCode)) {
return START_INTENT_FAILURE;
}
storeCallbackData(requestCode, callback, errorId);
return requestCode;
}
/**
* Starts an activity for the provided intent.
* @see Activity#startActivityForResult
*/
protected abstract boolean startActivityForResult(Intent intent, int requestCode);
@Override
public int showCancelableIntent(Intent intent, IntentCallback callback, Integer errorId) {
int requestCode = generateNextRequestCode();
if (!startActivityForResult(intent, requestCode)) {
return START_INTENT_FAILURE;
}
storeCallbackData(requestCode, callback, errorId);
return requestCode;
}
@Override
public int showCancelableIntent(
Callback<Integer> intentTrigger, IntentCallback callback, Integer errorId) {
Activity activity = getActivity().get();
if (activity == null) return START_INTENT_FAILURE;
int requestCode = generateNextRequestCode();
intentTrigger.onResult(requestCode);
storeCallbackData(requestCode, callback, errorId);
return requestCode;
}
@Override
public void cancelIntent(int requestCode) {
Activity activity = getActivity().get();
if (activity == null) return;
activity.finishActivity(requestCode);
}
@Override
public boolean removeIntentCallback(IntentCallback callback) {
int requestCode = mOutstandingIntents.indexOfValue(callback);
if (requestCode < 0) return false;
mOutstandingIntents.remove(requestCode);
mIntentErrors.remove(requestCode);
return true;
}
/**
* Responds to the intent result if the intent was created by the native window.
* @param requestCode Request code of the requested intent.
* @param resultCode Result code of the requested intent.
* @param data The data returned by the intent.
* @return Boolean value of whether the intent was started by the native window.
*/
public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
IntentCallback callback = mOutstandingIntents.get(requestCode);
mOutstandingIntents.delete(requestCode);
String errorMessage = mIntentErrors.remove(requestCode);
if (callback != null) {
callback.onIntentCompleted(this, resultCode, data);
return true;
} else {
if (errorMessage != null) {
showCallbackNonExistentError(errorMessage);
return true;
}
}
return false;
}
private int generateNextRequestCode() {
int requestCode = REQUEST_CODE_PREFIX + mNextRequestCode;
mNextRequestCode = (mNextRequestCode + 1) % REQUEST_CODE_RANGE_SIZE;
return requestCode;
}
private void storeCallbackData(int requestCode, IntentCallback callback, Integer errorId) {
mOutstandingIntents.put(requestCode, callback);
mIntentErrors.put(requestCode,
errorId == null ? null : ContextUtils.getApplicationContext().getString(errorId));
}
}
...@@ -18,7 +18,6 @@ import android.os.Build; ...@@ -18,7 +18,6 @@ import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.IBinder; import android.os.IBinder;
import android.os.Process; import android.os.Process;
import android.util.SparseArray;
import android.util.TypedValue; import android.util.TypedValue;
import android.view.Display; import android.view.Display;
import android.view.View; import android.view.View;
...@@ -106,7 +105,6 @@ public class WindowAndroid implements AndroidPermissionDelegate, DisplayAndroidO ...@@ -106,7 +105,6 @@ public class WindowAndroid implements AndroidPermissionDelegate, DisplayAndroidO
private boolean mWindowisWideColorGamut; private boolean mWindowisWideColorGamut;
protected SparseArray<IntentCallback> mOutstandingIntents;
// We use a weak reference here to prevent this from leaking in WebView. // We use a weak reference here to prevent this from leaking in WebView.
private WeakReference<Context> mContextRef; private WeakReference<Context> mContextRef;
...@@ -254,7 +252,6 @@ public class WindowAndroid implements AndroidPermissionDelegate, DisplayAndroidO ...@@ -254,7 +252,6 @@ public class WindowAndroid implements AndroidPermissionDelegate, DisplayAndroidO
// context does not have the same lifetime guarantees as an application context so we can't // context does not have the same lifetime guarantees as an application context so we can't
// hold a strong reference to it. // hold a strong reference to it.
mContextRef = new WeakReference<>(context); mContextRef = new WeakReference<>(context);
mOutstandingIntents = new SparseArray<>();
mIntentErrors = new HashMap<>(); mIntentErrors = new HashMap<>();
mDisplayAndroid = display; mDisplayAndroid = display;
mDisplayAndroid.addObserver(this); mDisplayAndroid.addObserver(this);
...@@ -390,11 +387,7 @@ public class WindowAndroid implements AndroidPermissionDelegate, DisplayAndroidO ...@@ -390,11 +387,7 @@ public class WindowAndroid implements AndroidPermissionDelegate, DisplayAndroidO
* @return True if the callback was removed, false if it was not found. * @return True if the callback was removed, false if it was not found.
*/ */
public boolean removeIntentCallback(IntentCallback callback) { public boolean removeIntentCallback(IntentCallback callback) {
int requestCode = mOutstandingIntents.indexOfValue(callback); return false;
if (requestCode < 0) return false;
mOutstandingIntents.remove(requestCode);
mIntentErrors.remove(requestCode);
return true;
} }
/** /**
......
...@@ -28,6 +28,7 @@ android_library("java") { ...@@ -28,6 +28,7 @@ android_library("java") {
"org/chromium/weblayer_private/NavigationControllerImpl.java", "org/chromium/weblayer_private/NavigationControllerImpl.java",
"org/chromium/weblayer_private/NavigationImpl.java", "org/chromium/weblayer_private/NavigationImpl.java",
"org/chromium/weblayer_private/ProfileImpl.java", "org/chromium/weblayer_private/ProfileImpl.java",
"org/chromium/weblayer_private/FragmentWindowAndroid.java",
"org/chromium/weblayer_private/ProfileManager.java", "org/chromium/weblayer_private/ProfileManager.java",
"org/chromium/weblayer_private/TopControlsContainerView.java", "org/chromium/weblayer_private/TopControlsContainerView.java",
"org/chromium/weblayer_private/WebLayerImpl.java", "org/chromium/weblayer_private/WebLayerImpl.java",
......
...@@ -9,7 +9,6 @@ import android.content.Intent; ...@@ -9,7 +9,6 @@ import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.view.View; import android.view.View;
import org.chromium.ui.base.ActivityWindowAndroid;
import org.chromium.weblayer_private.aidl.IBrowserFragmentController; import org.chromium.weblayer_private.aidl.IBrowserFragmentController;
import org.chromium.weblayer_private.aidl.IObjectWrapper; import org.chromium.weblayer_private.aidl.IObjectWrapper;
import org.chromium.weblayer_private.aidl.IProfile; import org.chromium.weblayer_private.aidl.IProfile;
...@@ -20,14 +19,14 @@ import org.chromium.weblayer_private.aidl.IProfile; ...@@ -20,14 +19,14 @@ import org.chromium.weblayer_private.aidl.IProfile;
public class BrowserFragmentControllerImpl extends IBrowserFragmentController.Stub { public class BrowserFragmentControllerImpl extends IBrowserFragmentController.Stub {
private final ProfileImpl mProfile; private final ProfileImpl mProfile;
private BrowserControllerImpl mTabController; private BrowserControllerImpl mTabController;
private ActivityWindowAndroid mWindowAndroid; private FragmentWindowAndroid mWindowAndroid;
public BrowserFragmentControllerImpl(ProfileImpl profile, Bundle savedInstanceState) { public BrowserFragmentControllerImpl(ProfileImpl profile, Bundle savedInstanceState) {
mProfile = profile; mProfile = profile;
// Restore tabs etc from savedInstanceState here. // Restore tabs etc from savedInstanceState here.
} }
public void onFragmentAttached(Context context, ActivityWindowAndroid windowAndroid) { public void onFragmentAttached(Context context, FragmentWindowAndroid windowAndroid) {
mTabController = new BrowserControllerImpl(context, mProfile, windowAndroid); mTabController = new BrowserControllerImpl(context, mProfile, windowAndroid);
mWindowAndroid = windowAndroid; mWindowAndroid = windowAndroid;
} }
......
...@@ -6,11 +6,9 @@ package org.chromium.weblayer_private; ...@@ -6,11 +6,9 @@ package org.chromium.weblayer_private;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentSender;
import android.os.Bundle; import android.os.Bundle;
import android.view.View; import android.view.View;
import org.chromium.ui.base.ActivityWindowAndroid;
import org.chromium.weblayer_private.aidl.BrowserFragmentArgs; import org.chromium.weblayer_private.aidl.BrowserFragmentArgs;
import org.chromium.weblayer_private.aidl.IBrowserFragment; import org.chromium.weblayer_private.aidl.IBrowserFragment;
import org.chromium.weblayer_private.aidl.IBrowserFragmentController; import org.chromium.weblayer_private.aidl.IBrowserFragmentController;
...@@ -24,29 +22,6 @@ public class BrowserFragmentImpl extends RemoteFragmentImpl { ...@@ -24,29 +22,6 @@ public class BrowserFragmentImpl extends RemoteFragmentImpl {
private BrowserFragmentControllerImpl mController; private BrowserFragmentControllerImpl mController;
private Context mContext; private Context mContext;
// TODO(cduvall): Factor out the logic we need from ActivityWindowAndroid so we do not inherit
// directly from it.
private static class FragmentWindowAndroid extends ActivityWindowAndroid {
private BrowserFragmentImpl mFragment;
FragmentWindowAndroid(Context context, BrowserFragmentImpl fragment) {
// Use false to disable listening to activity state.
super(context, false);
mFragment = fragment;
}
@Override
protected boolean startIntentSenderForResult(IntentSender intentSender, int requestCode) {
return mFragment.startIntentSenderForResult(
intentSender, requestCode, new Intent(), 0, 0, 0, null);
}
@Override
protected boolean startActivityForResult(Intent intent, int requestCode) {
return mFragment.startActivityForResult(intent, requestCode, null);
}
}
public BrowserFragmentImpl(ProfileManager profileManager, IRemoteFragmentClient client, public BrowserFragmentImpl(ProfileManager profileManager, IRemoteFragmentClient client,
Bundle fragmentArgs) { Bundle fragmentArgs) {
super(client); super(client);
......
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.weblayer_private;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
import org.chromium.ui.base.ActivityAndroidPermissionDelegate;
import org.chromium.ui.base.ActivityKeyboardVisibilityDelegate;
import org.chromium.ui.base.IntentWindowAndroid;
import java.lang.ref.WeakReference;
/**
* Implements intent sending for a fragment based window. This should be created when
* onAttach() is called on the fragment, and destroyed when onDetach() is called.
*/
public class FragmentWindowAndroid extends IntentWindowAndroid {
private BrowserFragmentImpl mFragment;
FragmentWindowAndroid(Context context, BrowserFragmentImpl fragment) {
super(context);
mFragment = fragment;
setKeyboardDelegate(new ActivityKeyboardVisibilityDelegate(getActivity()));
setAndroidPermissionDelegate(new ActivityAndroidPermissionDelegate(getActivity()));
}
@Override
protected final boolean startIntentSenderForResult(IntentSender intentSender, int requestCode) {
return mFragment.startIntentSenderForResult(
intentSender, requestCode, new Intent(), 0, 0, 0, null);
}
@Override
protected final boolean startActivityForResult(Intent intent, int requestCode) {
return mFragment.startActivityForResult(intent, requestCode, null);
}
@Override
public final WeakReference<Activity> getActivity() {
return new WeakReference<>(mFragment.getActivity());
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment