Commit 5c26c215 authored by Robbie McElrath's avatar Robbie McElrath Committed by Commit Bot

Revert "[WebLayer] Create FragmentHostingRemoteFragmentImpl"

This reverts commit d5f58580.

Reason for revert: A CL this depends on got reverted

Original change's description:
> [WebLayer] Create FragmentHostingRemoteFragmentImpl
>
> This CL removes the fake FragmentActivity from SiteSettingsFragmentImpl
> and MediaRouteDialogFragmentImpl, replacing them with a Context that
> hosts the fragments instead. This is possible now that we've landed
> the bytecode rewriting that changes the return type of
> Fragment.getActivity() from FragmentActivity to Activity.
>
> Bug: 1123216
> Change-Id: I98c2c07eb348d6833ca2e5d976110f7f29b5359e
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2523751
> Commit-Queue: Robbie McElrath <rmcelrath@chromium.org>
> Reviewed-by: Evan Stade <estade@chromium.org>
> Reviewed-by: Scott Violet <sky@chromium.org>
> Reviewed-by: Finnur Thorarinsson <finnur@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#828649}

TBR=sky@chromium.org,finnur@chromium.org,estade@chromium.org,rmcelrath@chromium.org

Change-Id: I2b83becfef2a92bd878bf32ae3aa5b750853a752
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: 1123216
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2547783Reviewed-by: default avatarRobbie McElrath <rmcelrath@chromium.org>
Commit-Queue: Robbie McElrath <rmcelrath@chromium.org>
Cr-Commit-Position: refs/heads/master@{#828839}
parent b613ea78
......@@ -165,7 +165,7 @@ public class AllSiteSettings extends SiteSettingsPreferenceFragment
/** OnClickListener for the clear button. We show an alert dialog to confirm the action */
@Override
public void onClick(View v) {
if (getContext() == null || v != mClearButton) return;
if (getActivity() == null || v != mClearButton) return;
long totalUsage = 0;
boolean includesApps = false;
......@@ -181,10 +181,9 @@ public class AllSiteSettings extends SiteSettingsPreferenceFragment
}
}
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
LayoutInflater inflater =
(LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View dialogView = inflater.inflate(R.layout.clear_data_dialog, null);
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
View dialogView =
getActivity().getLayoutInflater().inflate(R.layout.clear_data_dialog, null);
TextView message = dialogView.findViewById(android.R.id.message);
TextView signedOutText = dialogView.findViewById(R.id.signed_out_text);
TextView offlineText = dialogView.findViewById(R.id.offline_text);
......@@ -193,7 +192,7 @@ public class AllSiteSettings extends SiteSettingsPreferenceFragment
String dialogFormattedText =
getString(includesApps ? R.string.webstorage_clear_data_dialog_message_with_app
: R.string.webstorage_clear_data_dialog_message,
Formatter.formatShortFileSize(getContext(), totalUsage));
Formatter.formatShortFileSize(getActivity(), totalUsage));
message.setText(dialogFormattedText);
builder.setView(dialogView);
builder.setPositiveButton(R.string.storage_clear_dialog_clear_storage_option,
......@@ -247,7 +246,7 @@ public class AllSiteSettings extends SiteSettingsPreferenceFragment
MenuItem help = menu.add(
Menu.NONE, R.id.menu_id_site_settings_help, Menu.NONE, R.string.menu_help);
help.setIcon(VectorDrawableCompat.create(
getResources(), R.drawable.ic_help_and_feedback, getContext().getTheme()));
getResources(), R.drawable.ic_help_and_feedback, getActivity().getTheme()));
}
}
......
......@@ -122,7 +122,7 @@ public class ChosenObjectSettings extends SiteSettingsPreferenceFragment {
MenuItem help = menu.add(
Menu.NONE, R.id.menu_id_site_settings_help, Menu.NONE, R.string.menu_help);
help.setIcon(VectorDrawableCompat.create(
getResources(), R.drawable.ic_help_and_feedback, getContext().getTheme()));
getResources(), R.drawable.ic_help_and_feedback, getActivity().getTheme()));
}
}
......@@ -166,7 +166,7 @@ public class ChosenObjectSettings extends SiteSettingsPreferenceFragment {
// Managed objects cannot be revoked, so finish the activity only if the list did not
// contain managed objects.
if (hasManagedObject) {
ManagedPreferencesUtils.showManagedSettingsCannotBeResetToast(getContext());
ManagedPreferencesUtils.showManagedSettingsCannotBeResetToast(getActivity());
} else {
getActivity().finish();
}
......@@ -240,7 +240,7 @@ public class ChosenObjectSettings extends SiteSettingsPreferenceFragment {
header.setTitle(titleText);
header.setImageView(R.drawable.ic_delete_white_24dp,
R.string.website_settings_revoke_all_permissions_for_device, (View view) -> {
new AlertDialog.Builder(getContext(), R.style.Theme_Chromium_AlertDialog)
new AlertDialog.Builder(getActivity(), R.style.Theme_Chromium_AlertDialog)
.setTitle(R.string.reset)
.setMessage(dialogMsg)
.setPositiveButton(R.string.reset,
......
......@@ -363,7 +363,7 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment
MenuItem help = menu.add(
Menu.NONE, R.id.menu_id_site_settings_help, Menu.NONE, R.string.menu_help);
help.setIcon(VectorDrawableCompat.create(
getResources(), R.drawable.ic_help_and_feedback, getContext().getTheme()));
getResources(), R.drawable.ic_help_and_feedback, getActivity().getTheme()));
}
}
......@@ -588,7 +588,8 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment
String hostname = primaryPattern.equals(SITE_WILDCARD) ? secondaryPattern : primaryPattern;
Toast.makeText(getActivity(),
String.format(getContext().getString(R.string.website_settings_add_site_toast),
String.format(
getActivity().getString(R.string.website_settings_add_site_toast),
hostname),
Toast.LENGTH_SHORT)
.show();
......@@ -790,7 +791,7 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment
extras.putString(EXTRA_TITLE, getActivity().getTitle().toString());
extras.putSerializable(ChosenObjectSettings.EXTRA_OBJECT_INFOS, entry.first);
extras.putSerializable(ChosenObjectSettings.EXTRA_SITES, entry.second);
preference.setIcon(SettingsUtils.getTintedIcon(getContext(),
preference.setIcon(SettingsUtils.getTintedIcon(getActivity(),
ContentSettingsResources.getIcon(mCategory.getContentSettingsType())));
preference.setTitle(entry.first.get(0).getName());
preference.setFragment(ChosenObjectSettings.class.getCanonicalName());
......@@ -1060,7 +1061,7 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment
descriptions[1] =
getString(ContentSettingsResources.getSiteSummary(ContentSettingValues.BLOCK));
return new AlertDialog.Builder(getContext(), R.style.Theme_Chromium_AlertDialog)
return new AlertDialog.Builder(getActivity(), R.style.Theme_Chromium_AlertDialog)
.setPositiveButton(R.string.cancel, null)
.setNegativeButton(R.string.remove,
(dialog, which) -> {
......
......@@ -227,7 +227,7 @@ public class SingleWebsiteSettings extends SiteSettingsPreferenceFragment
@Override
public void onActivityCreated(Bundle savedInstanceState) {
getActivity().setTitle(getContext().getString(R.string.prefs_site_settings));
getActivity().setTitle(R.string.prefs_site_settings);
init();
super.onActivityCreated(savedInstanceState);
}
......@@ -358,7 +358,7 @@ public class SingleWebsiteSettings extends SiteSettingsPreferenceFragment
@ContentSettingValues @Nullable Integer value, boolean enabled) {
Drawable icon = enabled
? SettingsUtils.getTintedIcon(
getContext(), ContentSettingsResources.getIcon(contentSettingsType))
getActivity(), ContentSettingsResources.getIcon(contentSettingsType))
: ContentSettingsResources.getDisabledIcon(contentSettingsType, getResources());
if (getSiteSettingsClient().isPageInfoV2Enabled() && value != null
&& value == ContentSettingValues.BLOCK) {
......@@ -691,8 +691,8 @@ public class SingleWebsiteSettings extends SiteSettingsPreferenceFragment
new ChromeImageViewPreference(getStyledContext());
preference.setKey(CHOOSER_PERMISSION_PREFERENCE_KEY);
preference.setIcon(SettingsUtils.getTintedIcon(
getContext(), ContentSettingsResources.getIcon(info.getContentSettingsType())));
preference.setIcon(SettingsUtils.getTintedIcon(getActivity(),
ContentSettingsResources.getIcon(info.getContentSettingsType())));
preference.setOrder(maxPermissionOrder);
preference.setTitle(info.getName());
preference.setImageView(R.drawable.ic_delete_white_24dp,
......@@ -1076,7 +1076,7 @@ public class SingleWebsiteSettings extends SiteSettingsPreferenceFragment
: R.string.website_reset_confirmation;
int buttonResId = mHideNonPermissionPreferences ? R.string.reset : titleResId;
// Handle the Clear & Reset preference click by showing a confirmation.
new AlertDialog.Builder(getContext(), R.style.Theme_Chromium_AlertDialog)
new AlertDialog.Builder(getActivity(), R.style.Theme_Chromium_AlertDialog)
.setTitle(titleResId)
.setMessage(confirmationResId)
.setPositiveButton(buttonResId,
......@@ -1154,7 +1154,7 @@ public class SingleWebsiteSettings extends SiteSettingsPreferenceFragment
mObjectUserPermissionCount = 0;
if (mObjectPolicyPermissionCount > 0) {
ManagedPreferencesUtils.showManagedSettingsCannotBeResetToast(getContext());
ManagedPreferencesUtils.showManagedSettingsCannotBeResetToast(getActivity());
}
}
}
......@@ -31,7 +31,7 @@ public class SiteSettings
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
SettingsUtils.addPreferencesFromResource(this, R.xml.site_settings_preferences);
getActivity().setTitle(getContext().getString(R.string.prefs_site_settings));
getActivity().setTitle(R.string.prefs_site_settings);
configurePreferences();
updatePreferenceStates();
......@@ -120,7 +120,7 @@ public class SiteSettings
if (p.isEnabled()) {
p.setIcon(SettingsUtils.getTintedIcon(
getContext(), ContentSettingsResources.getIcon(contentType)));
getActivity(), ContentSettingsResources.getIcon(contentType)));
} else {
p.setIcon(ContentSettingsResources.getDisabledIcon(contentType, getResources()));
}
......
......@@ -123,7 +123,6 @@ android_library("java") {
"org/chromium/weblayer_private/ExternalNavigationDelegateImpl.java",
"org/chromium/weblayer_private/FaviconCallbackProxy.java",
"org/chromium/weblayer_private/FragmentAndroidPermissionDelegate.java",
"org/chromium/weblayer_private/FragmentHostingRemoteFragmentImpl.java",
"org/chromium/weblayer_private/FragmentWindowAndroid.java",
"org/chromium/weblayer_private/FullscreenCallbackProxy.java",
"org/chromium/weblayer_private/FullscreenToast.java",
......
// Copyright 2020 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.content.Context;
import android.content.ContextWrapper;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.InflateException;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewStub;
import androidx.appcompat.app.AppCompatDelegate;
import androidx.fragment.app.FragmentController;
import androidx.fragment.app.FragmentHostCallback;
import androidx.fragment.app.FragmentManager;
import org.chromium.weblayer_private.interfaces.IRemoteFragmentClient;
import org.chromium.weblayer_private.interfaces.StrictModeWorkaround;
import java.lang.reflect.Constructor;
/**
* A base class for RemoteFragmentImpls that need to host child Fragments.
*
* Because Fragments created in WebLayer use the AndroidX library from WebLayer's ClassLoader, we
* can't attach Fragments created here directly to the embedder's Fragment tree, and have to create
* a local FragmentController to manage them. This class handles creating the FragmentController,
* and forwards all Fragment lifecycle events from the RemoteFragment in the embedder's Fragment
* tree to child Fragments of this class.
*/
public abstract class FragmentHostingRemoteFragmentImpl extends RemoteFragmentImpl {
// The WebLayer-wrapped context object. This context gets assets and resources from WebLayer,
// not from the embedder. Use this for the most part, especially to resolve WebLayer-specific
// resource IDs.
private Context mContext;
private boolean mStarted;
private FragmentController mFragmentController;
protected static class RemoteFragmentContext
extends ContextWrapper implements LayoutInflater.Factory2 {
private static final Class<?>[] VIEW_CONSTRUCTOR_ARGS =
new Class[] {Context.class, AttributeSet.class};
public RemoteFragmentContext(Context webLayerContext) {
super(webLayerContext);
// Register ourselves as a the LayoutInflater factory so we can handle loading Views.
// See onCreateView for information about why this is needed.
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.M) {
getLayoutInflater().setFactory2(this);
}
}
// This method is needed to work around a LayoutInflater bug in Android <N. Before
// LayoutInflater creates an instance of a View, it needs to look up the class by name to
// get a reference to its Constructor. As an optimization, it caches this name to
// Constructor mapping. This cache causes issues if a class gets loaded multiple times with
// different ClassLoaders. In some UIs, some AndroidX Views get loaded early on with the
// embedding app's ClassLoader, so the Constructor from that ClassLoader's version of the
// class gets cached. When the WebLayer implementation later tries to inflate the same
// class, it instantiates a version from the wrong ClassLoader, which leads to a
// ClassCastException when casting that View to its original class. This was fixed in
// Android N, but to work around it on L & M, we inflate the Views manually here, which
// bypasses LayoutInflater's cache.
@Override
public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
// If the class doesn't have a '.' in its name, it's probably a built-in Android View,
// which are often referenced by just their class names with no package prefix. For
// these classes we can return null to fall back to LayoutInflater's default behavior.
if (name.indexOf('.') == -1) {
return null;
}
Class<? extends View> clazz = null;
try {
clazz = context.getClassLoader().loadClass(name).asSubclass(View.class);
LayoutInflater inflater = getLayoutInflater();
if (inflater.getFilter() != null && !inflater.getFilter().onLoadClass(clazz)) {
throw new InflateException(attrs.getPositionDescription()
+ ": Class not allowed to be inflated " + name);
}
Constructor<? extends View> constructor =
clazz.getConstructor(VIEW_CONSTRUCTOR_ARGS);
constructor.setAccessible(true);
View view = constructor.newInstance(new Object[] {context, attrs});
if (view instanceof ViewStub) {
// Use the same Context when inflating ViewStub later.
ViewStub viewStub = (ViewStub) view;
viewStub.setLayoutInflater(inflater.cloneInContext(context));
}
return view;
} catch (Exception e) {
InflateException ie = new InflateException(attrs.getPositionDescription()
+ ": Error inflating class "
+ (clazz == null ? "<unknown>" : clazz.getName()));
ie.initCause(e);
throw ie;
}
}
@Override
public View onCreateView(String name, Context context, AttributeSet attrs) {
return null;
}
private LayoutInflater getLayoutInflater() {
return (LayoutInflater) getBaseContext().getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
}
}
private static class RemoteFragmentHostCallback extends FragmentHostCallback<Context> {
private final FragmentHostingRemoteFragmentImpl mFragmentImpl;
private RemoteFragmentHostCallback(FragmentHostingRemoteFragmentImpl fragmentImpl) {
super(fragmentImpl.getWebLayerContext(), new Handler(), 0);
mFragmentImpl = fragmentImpl;
}
@Override
public Context onGetHost() {
return mFragmentImpl.getWebLayerContext();
}
@Override
public LayoutInflater onGetLayoutInflater() {
Context context = mFragmentImpl.getWebLayerContext();
return ((LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE))
.cloneInContext(context);
}
@Override
public boolean onHasView() {
return mFragmentImpl.getView() != null;
}
@Override
public View onFindViewById(int id) {
return onHasView() ? mFragmentImpl.getView().findViewById(id) : null;
}
}
protected FragmentHostingRemoteFragmentImpl(IRemoteFragmentClient remoteFragmentClient) {
super(remoteFragmentClient);
}
@Override
public void onAttach(Context embedderContext) {
StrictModeWorkaround.apply();
super.onAttach(embedderContext);
mContext = createRemoteFragmentContext(embedderContext);
mFragmentController =
FragmentController.createController(new RemoteFragmentHostCallback(this));
// Some appcompat functionality depends on Fragments being hosted from within an
// AppCompatActivity, which performs some static initialization. Even if we're running
// within an AppCompatActivity, it will be from the embedder's ClassLoader, so in WebLayer's
// ClassLoader the initialization hasn't occurred. Creating an AppCompatDelegate manually
// here will perform the necessary initialization.
AppCompatDelegate.create(getActivity(), null);
}
@Override
public void onCreate(Bundle savedInstanceState) {
StrictModeWorkaround.apply();
mFragmentController.attachHost(null);
super.onCreate(savedInstanceState);
mFragmentController.dispatchCreate();
}
@Override
public void onDestroyView() {
StrictModeWorkaround.apply();
super.onDestroyView();
mFragmentController.dispatchDestroyView();
}
@Override
public void onDestroy() {
StrictModeWorkaround.apply();
super.onDestroy();
mFragmentController.dispatchDestroy();
}
@Override
public void onDetach() {
StrictModeWorkaround.apply();
super.onDetach();
mContext = null;
}
@Override
public void onStart() {
super.onStart();
if (!mStarted) {
mStarted = true;
mFragmentController.dispatchActivityCreated();
}
mFragmentController.noteStateNotSaved();
mFragmentController.execPendingActions();
mFragmentController.dispatchStart();
}
@Override
public void onStop() {
super.onStop();
mFragmentController.dispatchStop();
}
@Override
public void onResume() {
super.onResume();
mFragmentController.dispatchResume();
}
@Override
public void onPause() {
super.onPause();
mFragmentController.dispatchPause();
}
public FragmentManager getSupportFragmentManager() {
return mFragmentController.getSupportFragmentManager();
}
/**
* Returns the RemoteFragmentContext that should be used in the child Fragment tree.
*
* Implementations will typically wrap embedderContext with ClassLoaderContextWrapperFactory,
* and possibly set a Theme.
*/
protected abstract RemoteFragmentContext createRemoteFragmentContext(Context embedderContext);
protected Context getWebLayerContext() {
return mContext;
}
}
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