Fix incorrect User-Agent selection with free-form windows enabled
DeviceUtilsImpl has two methods to append/remove the user agent switch: addDeviceSpecificUserAgentSwitch - Called on startup - Uses DeviceFormFactor.isTablet() to determine if the current display is tablet-sized updateDeviceSpecificUserAgentSwitch - Called on display changes - Accepts as an argument whether the current display is tablet-sized; the value is actually computed in ChromeActivity using DisplayUtil.getCurrentSmallestScreenWidth(Context) Unfortunately two methods inconsistently determine whether the current display is tablet-sized, for two reasons: 1. When free-form windows are enabled, DeviceFormFactor.isTablet() checks the current *window* size, not the *display* size. This ended up with the user agent switch value depending on the initial window size. 2. When multiple displays are available and multiple Chrome windows are in different displays, DisplayUtil.getCurrentSmallestScreenWidth() may return different results per display. This patch fixes the first issue by: - merging the two methods into one for consistency - updating the method to get the display size, not the window size, when free-form windows are enabled. Bug: 375056831 Change-Id: Id280c1b35eb04b533360a4599eafa25369f7555d Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6176859 Reviewed-by: Shu Yang <shuyng@google.com> Reviewed-by: Yaron Friedman <yfriedman@chromium.org> Reviewed-by: Bo Liu <boliu@chromium.org> Code-Coverage: findit-for-me@appspot.gserviceaccount.com <findit-for-me@appspot.gserviceaccount.com> Commit-Queue: Shuhei Takahashi <nya@chromium.org> Reviewed-by: Luke Halliwell <halliwell@chromium.org> Cr-Commit-Position: refs/heads/main@{#1410081}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
9db9d2fc8f
commit
821cec2595
chrome/android/java/src/org/chromium/chrome/browser
chromecast/browser/android/apk/src/org/chromium/chromecast/shell
content
public
android
java
src
org
chromium
content
content_public
browser
shell
android
shell_apk
src
org
chromium
content_shell_apk
ui/android/java/src/org/chromium/ui/display
@ -2768,13 +2768,14 @@ public abstract class ChromeActivity extends AsyncInitializationActivity
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch between phone and tablet mode and do the tab re-parenting in the meantime.
|
||||
* Also update switch USE_MOBILE_UA depends on whether the device is tablet sized.
|
||||
* Switch between phone and tablet mode and do the tab re-parenting in the meantime. Also update
|
||||
* switch USE_MOBILE_UA depends on whether the device is tablet sized.
|
||||
*
|
||||
* @param isTablet whether the current screen is tablet size.
|
||||
* @return whether screen layout change lead to a recreate.
|
||||
*/
|
||||
private boolean onScreenLayoutSizeChange(boolean isTablet) {
|
||||
DeviceUtils.updateDeviceSpecificUserAgentSwitch(isTablet);
|
||||
DeviceUtils.updateDeviceSpecificUserAgentSwitch(this);
|
||||
|
||||
if (mTabReparentingControllerSupplier.get() != null && !mIsTabReparentingPrepared) {
|
||||
mTabReparentingControllerSupplier.get().prepareTabsForReparenting();
|
||||
|
@ -264,7 +264,7 @@ public class ProcessInitializationHandler {
|
||||
// - Nokia 1 (Android Go): 20-200 ms
|
||||
warmUpSharedPrefs();
|
||||
|
||||
DeviceUtils.addDeviceSpecificUserAgentSwitch();
|
||||
DeviceUtils.updateDeviceSpecificUserAgentSwitch(ContextUtils.getApplicationContext());
|
||||
ApplicationStatus.registerStateListenerForAllActivities(
|
||||
(activity, newState) -> {
|
||||
if (newState == ActivityState.CREATED || newState == ActivityState.DESTROYED) {
|
||||
|
@ -28,7 +28,7 @@ public class CastBrowserHelper {
|
||||
Log.d(TAG, "Performing one-time browser initialization asynchronously");
|
||||
|
||||
CastCommandLineHelper.initCommandLine(intent);
|
||||
DeviceUtils.addDeviceSpecificUserAgentSwitch();
|
||||
DeviceUtils.updateDeviceSpecificUserAgentSwitch(context);
|
||||
LibraryLoader.getInstance().ensureInitialized();
|
||||
|
||||
Log.d(TAG, "Loading BrowserStartupController...");
|
||||
|
@ -474,7 +474,8 @@ public class BrowserStartupControllerImpl implements BrowserStartupController {
|
||||
}
|
||||
|
||||
// TODO(yfriedman): Remove dependency on a command line flag for this.
|
||||
DeviceUtilsImpl.addDeviceSpecificUserAgentSwitch();
|
||||
DeviceUtilsImpl.updateDeviceSpecificUserAgentSwitch(
|
||||
ContextUtils.getApplicationContext());
|
||||
BrowserStartupControllerImplJni.get().setCommandLineFlags(singleProcess);
|
||||
}
|
||||
|
||||
|
@ -4,32 +4,41 @@
|
||||
|
||||
package org.chromium.content.browser;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.chromium.base.CommandLine;
|
||||
import org.chromium.base.StrictModeContext;
|
||||
import org.chromium.build.annotations.NullMarked;
|
||||
import org.chromium.content_public.common.ContentSwitches;
|
||||
import org.chromium.ui.base.DeviceFormFactor;
|
||||
import org.chromium.ui.display.DisplayUtil;
|
||||
|
||||
/** A utility class that has helper methods for device configuration. */
|
||||
@NullMarked
|
||||
public class DeviceUtilsImpl {
|
||||
private DeviceUtilsImpl() {}
|
||||
|
||||
public static void addDeviceSpecificUserAgentSwitch() {
|
||||
/**
|
||||
* Adds/removes the user agent command line switch according to the current display size.
|
||||
*
|
||||
* <p>See {@link
|
||||
* org.chromium.content_public.browser.DeviceUtils#updateDeviceSpecificUserAgentSwitch(Context)}
|
||||
* for details.
|
||||
*/
|
||||
public static void updateDeviceSpecificUserAgentSwitch(Context context) {
|
||||
try (StrictModeContext ignored = StrictModeContext.allowDiskReads()) {
|
||||
if (!DeviceFormFactor.isTablet()) {
|
||||
CommandLine.getInstance().appendSwitch(ContentSwitches.USE_MOBILE_UA);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void updateDeviceSpecificUserAgentSwitch(boolean isTablet) {
|
||||
try (StrictModeContext ignored = StrictModeContext.allowDiskReads()) {
|
||||
if (isTablet) {
|
||||
if (isDisplayTabletSized(context)) {
|
||||
CommandLine.getInstance().removeSwitch(ContentSwitches.USE_MOBILE_UA);
|
||||
} else {
|
||||
CommandLine.getInstance().appendSwitch(ContentSwitches.USE_MOBILE_UA);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isDisplayTabletSized(Context context) {
|
||||
// We do not use DisplayUtil.getCurrentSmallestScreenWidth() because it crashes on obtaining
|
||||
// the WindowManager with an application context when the strict mode is enabled.
|
||||
int smallestWidth = DisplayUtil.getCurrentSmallestScreenWidthAllowingFallback(context);
|
||||
return smallestWidth >= DeviceFormFactor.MINIMUM_TABLET_WIDTH_DP;
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
package org.chromium.content_public.browser;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.ArraySet;
|
||||
import android.view.InputDevice;
|
||||
|
||||
@ -15,14 +16,19 @@ import org.chromium.content.browser.DeviceUtilsImpl;
|
||||
public final class DeviceUtils {
|
||||
private DeviceUtils() {}
|
||||
|
||||
/** Appends the switch specifying which user agent should be used for this device. */
|
||||
public static void addDeviceSpecificUserAgentSwitch() {
|
||||
DeviceUtilsImpl.addDeviceSpecificUserAgentSwitch();
|
||||
}
|
||||
|
||||
/** Appends or removes the switch specifying which user agent should be used for this device. */
|
||||
public static void updateDeviceSpecificUserAgentSwitch(boolean isTablet) {
|
||||
DeviceUtilsImpl.updateDeviceSpecificUserAgentSwitch(isTablet);
|
||||
/**
|
||||
* Adds/removes the user agent command line switch according to the current display size.
|
||||
*
|
||||
* <p>You should pass a Context associated with the current window (e.g. Activity) to check the
|
||||
* correct display. If you pass a Context not associated with a window (e.g. Application), this
|
||||
* method will fall back to the default display. Ideally it should be an error to pass a context
|
||||
* not associated with a window, but at this moment, this method is often called from browser
|
||||
* initialization classes where UI is not ready yet, so we allow the fallback.
|
||||
*
|
||||
* @param context The context used to look up the current window.
|
||||
*/
|
||||
public static void updateDeviceSpecificUserAgentSwitch(Context context) {
|
||||
DeviceUtilsImpl.updateDeviceSpecificUserAgentSwitch(context);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -55,7 +55,7 @@ public class ContentShellActivity extends Activity {
|
||||
}
|
||||
}
|
||||
|
||||
DeviceUtils.addDeviceSpecificUserAgentSwitch();
|
||||
DeviceUtils.updateDeviceSpecificUserAgentSwitch(this);
|
||||
|
||||
LibraryLoader.getInstance().ensureInitialized();
|
||||
|
||||
|
@ -19,6 +19,7 @@ import android.view.WindowInsets;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import org.chromium.base.BuildInfo;
|
||||
import org.chromium.base.ContextUtils;
|
||||
import org.chromium.base.Log;
|
||||
import org.chromium.build.annotations.NullMarked;
|
||||
import org.chromium.build.annotations.Nullable;
|
||||
@ -183,23 +184,30 @@ public abstract class DisplayUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current smallest screen width in dp. This method uses {@link WindowManager} on
|
||||
* Android R and above; otherwise, {@link DisplayUtil#getSmallestWidth(DisplayAndroid)}.
|
||||
* Get current smallest screen width in dp.
|
||||
*
|
||||
* <p>This method uses {@link WindowManager} on Android R and above; otherwise, {@link
|
||||
* DisplayUtil#getSmallestWidth(DisplayAndroid)}.
|
||||
*
|
||||
* <p>This method raises an exception when it gets a context not associated with a display (e.g.
|
||||
* application contexts) and the strict mode is enabled. Use {@link
|
||||
* DisplayUtil#getCurrentSmallestScreenWidthAllowingFallback(Context)} if you want to fall back
|
||||
* to the default display in such cases.
|
||||
*
|
||||
* @param context {@link Context} used to get system service and target display.
|
||||
* @return Smallest screen width in dp.
|
||||
*/
|
||||
public static int getCurrentSmallestScreenWidth(Context context) {
|
||||
DisplayAndroid display = DisplayAndroid.getNonMultiDisplay(context);
|
||||
// Android T does not receive updated width upon foldable unfold from window context.
|
||||
// Continue to rely on context on this case.
|
||||
Context windowManagerContext =
|
||||
(VERSION.SDK_INT >= VERSION_CODES.R && VERSION.SDK_INT < VERSION_CODES.TIRAMISU)
|
||||
? (display.getWindowContext() != null
|
||||
? display.getWindowContext()
|
||||
: context)
|
||||
: context;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
// Android T does not receive updated width upon foldable unfold from window context.
|
||||
// Continue to rely on context on this case.
|
||||
Context windowManagerContext =
|
||||
(VERSION.SDK_INT >= VERSION_CODES.R && VERSION.SDK_INT < VERSION_CODES.TIRAMISU)
|
||||
? (display.getWindowContext() != null
|
||||
? display.getWindowContext()
|
||||
: context)
|
||||
: context;
|
||||
// Context#getSystemService(Context.WINDOW_SERVICE) is preferred over
|
||||
// Activity#getWindowManager, because during #attachBaseContext, #getWindowManager
|
||||
// is not ready yet and always returns null. See crbug.com/1252150.
|
||||
@ -213,6 +221,40 @@ public abstract class DisplayUtil {
|
||||
return DisplayUtil.pxToDp(display, DisplayUtil.getSmallestWidth(display));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current smallest screen width in dp.
|
||||
*
|
||||
* <p>This method is similar to {@link DisplayUtil#getCurrentSmallestScreenWidth(Context)}, but
|
||||
* it accepts contexts not associated with a display (e.g. application contexts). In such cases,
|
||||
* it returns the smallest width of the default display.
|
||||
*
|
||||
* <p>Do not use this method unless you need to fall back to the default display when the
|
||||
* current display is not available. It is undesirable in most cases.
|
||||
*
|
||||
* @param context {@link Context} used to get the current display.
|
||||
* @return Smallest screen width in dp.
|
||||
*/
|
||||
public static int getCurrentSmallestScreenWidthAllowingFallback(Context context) {
|
||||
boolean isUiContext;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
isUiContext = context.isUiContext();
|
||||
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
isUiContext = ContextUtils.activityFromContext(context) != null;
|
||||
} else {
|
||||
// On Android older than R, getCurrentSmallestScreenWidth behaves identically for UI
|
||||
// contexts and non-UI contexts.
|
||||
isUiContext = true;
|
||||
}
|
||||
if (isUiContext) {
|
||||
return getCurrentSmallestScreenWidth(context);
|
||||
}
|
||||
|
||||
// Fall back to the default display. We do not use WindowManager because we can't obtain it
|
||||
// from non-UI contexts.
|
||||
DisplayAndroid display = DisplayAndroid.getNonMultiDisplay(context);
|
||||
return DisplayUtil.pxToDp(display, DisplayUtil.getSmallestWidth(display));
|
||||
}
|
||||
|
||||
/** Change the UI scaling factor on XR devices for testing. */
|
||||
static void setUiScalingFactorForXrForTesting(float scalingFactor) {
|
||||
sUiScalingFactorForXrOverride = scalingFactor;
|
||||
|
Reference in New Issue
Block a user