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") {
"java/src/org/chromium/ui/base/ActivityAndroidPermissionDelegate.java",
"java/src/org/chromium/ui/base/ActivityKeyboardVisibilityDelegate.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/Clipboard.java",
"java/src/org/chromium/ui/base/DeviceFormFactor.java",
......
......@@ -5,7 +5,6 @@
package org.chromium.ui.base;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
......@@ -14,7 +13,6 @@ import android.content.IntentSender.SendIntentException;
import org.chromium.base.ActivityState;
import org.chromium.base.ApplicationStatus;
import org.chromium.base.Callback;
import org.chromium.base.ContextUtils;
import java.lang.ref.WeakReference;
......@@ -25,13 +23,7 @@ import java.lang.ref.WeakReference;
* Only instantiate this class when you need the implemented features.
*/
public class ActivityWindowAndroid
extends WindowAndroid 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;
extends IntentWindowAndroid implements ApplicationStatus.ActivityStateListener {
private boolean mListenToActivityState;
/**
......@@ -77,8 +69,8 @@ public class ActivityWindowAndroid
return (ActivityKeyboardVisibilityDelegate) super.getKeyboardDelegate();
}
/** Uses the provided intent sender to start the intent. */
protected boolean startIntentSenderForResult(IntentSender intentSender, int requestCode) {
@Override
protected final boolean startIntentSenderForResult(IntentSender intentSender, int requestCode) {
Activity activity = getActivity().get();
if (activity == null) return false;
......@@ -91,20 +83,7 @@ public class ActivityWindowAndroid
}
@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. */
protected boolean startActivityForResult(Intent intent, int requestCode) {
protected final boolean startActivityForResult(Intent intent, int requestCode) {
Activity activity = getActivity().get();
if (activity == null) return false;
......@@ -116,63 +95,6 @@ public class ActivityWindowAndroid
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
public WeakReference<Activity> getActivity() {
return new WeakReference<>(ContextUtils.activityFromContext(getContext().get()));
......@@ -197,16 +119,4 @@ public class ActivityWindowAndroid
return mListenToActivityState ? ApplicationStatus.getStateForActivity(getActivity().get())
: 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;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Process;
import android.util.SparseArray;
import android.util.TypedValue;
import android.view.Display;
import android.view.View;
......@@ -106,7 +105,6 @@ public class WindowAndroid implements AndroidPermissionDelegate, DisplayAndroidO
private boolean mWindowisWideColorGamut;
protected SparseArray<IntentCallback> mOutstandingIntents;
// We use a weak reference here to prevent this from leaking in WebView.
private WeakReference<Context> mContextRef;
......@@ -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
// hold a strong reference to it.
mContextRef = new WeakReference<>(context);
mOutstandingIntents = new SparseArray<>();
mIntentErrors = new HashMap<>();
mDisplayAndroid = display;
mDisplayAndroid.addObserver(this);
......@@ -390,11 +387,7 @@ public class WindowAndroid implements AndroidPermissionDelegate, DisplayAndroidO
* @return True if the callback was removed, false if it was not found.
*/
public boolean removeIntentCallback(IntentCallback callback) {
int requestCode = mOutstandingIntents.indexOfValue(callback);
if (requestCode < 0) return false;
mOutstandingIntents.remove(requestCode);
mIntentErrors.remove(requestCode);
return true;
return false;
}
/**
......
......@@ -28,6 +28,7 @@ android_library("java") {
"org/chromium/weblayer_private/NavigationControllerImpl.java",
"org/chromium/weblayer_private/NavigationImpl.java",
"org/chromium/weblayer_private/ProfileImpl.java",
"org/chromium/weblayer_private/FragmentWindowAndroid.java",
"org/chromium/weblayer_private/ProfileManager.java",
"org/chromium/weblayer_private/TopControlsContainerView.java",
"org/chromium/weblayer_private/WebLayerImpl.java",
......
......@@ -9,7 +9,6 @@ import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import org.chromium.ui.base.ActivityWindowAndroid;
import org.chromium.weblayer_private.aidl.IBrowserFragmentController;
import org.chromium.weblayer_private.aidl.IObjectWrapper;
import org.chromium.weblayer_private.aidl.IProfile;
......@@ -20,14 +19,14 @@ import org.chromium.weblayer_private.aidl.IProfile;
public class BrowserFragmentControllerImpl extends IBrowserFragmentController.Stub {
private final ProfileImpl mProfile;
private BrowserControllerImpl mTabController;
private ActivityWindowAndroid mWindowAndroid;
private FragmentWindowAndroid mWindowAndroid;
public BrowserFragmentControllerImpl(ProfileImpl profile, Bundle savedInstanceState) {
mProfile = profile;
// 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);
mWindowAndroid = windowAndroid;
}
......
......@@ -6,11 +6,9 @@ package org.chromium.weblayer_private;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
import android.os.Bundle;
import android.view.View;
import org.chromium.ui.base.ActivityWindowAndroid;
import org.chromium.weblayer_private.aidl.BrowserFragmentArgs;
import org.chromium.weblayer_private.aidl.IBrowserFragment;
import org.chromium.weblayer_private.aidl.IBrowserFragmentController;
......@@ -24,29 +22,6 @@ public class BrowserFragmentImpl extends RemoteFragmentImpl {
private BrowserFragmentControllerImpl mController;
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,
Bundle fragmentArgs) {
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