mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
[Android] Check for text to paste before trying to retrieve data from URI (flutter/engine#48166)
Adds a check to retrieve explicit text from Clipboard items via [`getText`](https://developer.android.com/reference/android/content/ClipData.Item#getText()) before attempting to retrieve data if the Clipboard item (`ClipData.Item`) has an associated URI. Also adds more error handling for edge cases concerning URIs (the URI not having the content scheme or being null). Fixes https://github.com/flutter/flutter/issues/74320. Some content providers will not send URIs containing the `text/*` pattern or have the content scheme (`content://`), but ultimately we should expect Clipboard items to either fall **not** into one of those categories or have an explicit textual value available via `getText`. In case this is not true, though, checks for non-content URIs and null URIs are added, as well :) Tested on a Samsung tablet with pasting from MS Word, MS Excel, and Samsung Notes. [C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
This commit is contained in:
parent
3ffeaa87b6
commit
7965fd759e
@ -13,6 +13,7 @@ import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.AssetFileDescriptor;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.view.HapticFeedbackConstants;
|
||||
import android.view.SoundEffectConstants;
|
||||
@ -520,21 +521,46 @@ public class PlatformPlugin {
|
||||
|
||||
if (!clipboard.hasPrimaryClip()) return null;
|
||||
|
||||
CharSequence charSequence = null;
|
||||
CharSequence itemText = null;
|
||||
try {
|
||||
ClipData clip = clipboard.getPrimaryClip();
|
||||
if (clip == null) return null;
|
||||
if (format == null || format == PlatformChannel.ClipboardContentFormat.PLAIN_TEXT) {
|
||||
ClipData.Item item = clip.getItemAt(0);
|
||||
AssetFileDescriptor assetFileDescriptor = null;
|
||||
if (item.getUri() != null)
|
||||
assetFileDescriptor =
|
||||
activity
|
||||
.getContentResolver()
|
||||
.openTypedAssetFileDescriptor(item.getUri(), "text/*", null);
|
||||
charSequence = item.coerceToText(activity);
|
||||
if (assetFileDescriptor != null) assetFileDescriptor.close();
|
||||
return charSequence;
|
||||
// First, try getting clipboard data as text; no further processing
|
||||
// required if so.
|
||||
itemText = item.getText();
|
||||
if (itemText == null) {
|
||||
// Clipboard data does not contain text, so check whether or not it
|
||||
// contains a URI to extract text from.
|
||||
Uri itemUri = item.getUri();
|
||||
|
||||
if (itemUri == null) {
|
||||
Log.w(
|
||||
TAG, "Clipboard item contained no textual content nor a URI to retrieve it from.");
|
||||
return null;
|
||||
}
|
||||
|
||||
// Will only try to extract text from URI if it has the content scheme.
|
||||
String uriScheme = itemUri.getScheme();
|
||||
|
||||
if (!uriScheme.equals("content")) {
|
||||
Log.w(
|
||||
TAG,
|
||||
"Clipboard item contains a Uri with scheme '" + uriScheme + "'that is unhandled.");
|
||||
return null;
|
||||
}
|
||||
|
||||
AssetFileDescriptor assetFileDescriptor =
|
||||
activity.getContentResolver().openTypedAssetFileDescriptor(itemUri, "text/*", null);
|
||||
|
||||
// Safely return clipboard data coerced into text; will return either
|
||||
// itemText or text retrieved from its URI.
|
||||
itemText = item.coerceToText(activity);
|
||||
if (assetFileDescriptor != null) assetFileDescriptor.close();
|
||||
}
|
||||
|
||||
return itemText;
|
||||
}
|
||||
} catch (SecurityException e) {
|
||||
Log.w(
|
||||
@ -545,10 +571,11 @@ public class PlatformPlugin {
|
||||
e);
|
||||
return null;
|
||||
} catch (FileNotFoundException e) {
|
||||
Log.w(TAG, "Clipboard text was unable to be received from content URI.");
|
||||
return null;
|
||||
} catch (IOException e) {
|
||||
Log.w(TAG, "Failed to close AssetFileDescriptor while accessing clipboard data.", e);
|
||||
return charSequence;
|
||||
Log.w(TAG, "Failed to close AssetFileDescriptor while trying to read text from URI.", e);
|
||||
return itemText;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@ -13,10 +13,7 @@ import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.any;
|
||||
import static org.mockito.Mockito.anyBoolean;
|
||||
import static org.mockito.Mockito.anyString;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.mockStatic;
|
||||
import static org.mockito.Mockito.never;
|
||||
@ -27,7 +24,6 @@ import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipDescription;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
@ -63,17 +59,26 @@ import org.robolectric.shadows.ShadowLooper;
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class PlatformPluginTest {
|
||||
private final Context ctx = ApplicationProvider.getApplicationContext();
|
||||
private final PlatformChannel mockPlatformChannel = mock(PlatformChannel.class);
|
||||
|
||||
private ClipboardManager clipboardManager;
|
||||
private ClipboardContentFormat clipboardFormat;
|
||||
|
||||
public void setUpForTextClipboardTests(Activity mockActivity) {
|
||||
clipboardManager = spy(ctx.getSystemService(ClipboardManager.class));
|
||||
when(mockActivity.getSystemService(Context.CLIPBOARD_SERVICE)).thenReturn(clipboardManager);
|
||||
clipboardFormat = ClipboardContentFormat.PLAIN_TEXT;
|
||||
}
|
||||
|
||||
@Config(sdk = Build.VERSION_CODES.KITKAT)
|
||||
@Test
|
||||
public void itIgnoresNewHapticEventsOnOldAndroidPlatforms() {
|
||||
View fakeDecorView = mock(View.class);
|
||||
Window fakeWindow = mock(Window.class);
|
||||
Activity mockActivity = mock(Activity.class);
|
||||
when(fakeWindow.getDecorView()).thenReturn(fakeDecorView);
|
||||
Activity fakeActivity = mock(Activity.class);
|
||||
when(fakeActivity.getWindow()).thenReturn(fakeWindow);
|
||||
PlatformChannel fakePlatformChannel = mock(PlatformChannel.class);
|
||||
PlatformPlugin platformPlugin = new PlatformPlugin(fakeActivity, fakePlatformChannel);
|
||||
when(mockActivity.getWindow()).thenReturn(fakeWindow);
|
||||
PlatformPlugin platformPlugin = new PlatformPlugin(mockActivity, mockPlatformChannel);
|
||||
|
||||
// HEAVY_IMPACT haptic response is only available on "M" (23) and later.
|
||||
platformPlugin.vibrateHapticFeedback(PlatformChannel.HapticFeedbackType.HEAVY_IMPACT);
|
||||
@ -82,53 +87,141 @@ public class PlatformPluginTest {
|
||||
platformPlugin.vibrateHapticFeedback(PlatformChannel.HapticFeedbackType.SELECTION_CLICK);
|
||||
}
|
||||
|
||||
@Config(sdk = Build.VERSION_CODES.Q)
|
||||
@Test
|
||||
public void platformPlugin_getClipboardData() throws IOException {
|
||||
ClipboardManager clipboardManager = ctx.getSystemService(ClipboardManager.class);
|
||||
|
||||
public void platformPlugin_getClipboardDataIsNonNullWhenPlainTextCopied() throws IOException {
|
||||
View fakeDecorView = mock(View.class);
|
||||
Window fakeWindow = mock(Window.class);
|
||||
Activity mockActivity = mock(Activity.class);
|
||||
when(fakeWindow.getDecorView()).thenReturn(fakeDecorView);
|
||||
Activity fakeActivity = mock(Activity.class);
|
||||
when(fakeActivity.getWindow()).thenReturn(fakeWindow);
|
||||
when(fakeActivity.getSystemService(Context.CLIPBOARD_SERVICE)).thenReturn(clipboardManager);
|
||||
PlatformChannel fakePlatformChannel = mock(PlatformChannel.class);
|
||||
PlatformPlugin platformPlugin = new PlatformPlugin(fakeActivity, fakePlatformChannel);
|
||||
when(mockActivity.getWindow()).thenReturn(fakeWindow);
|
||||
PlatformPlugin platformPlugin = new PlatformPlugin(mockActivity, mockPlatformChannel);
|
||||
setUpForTextClipboardTests(mockActivity);
|
||||
|
||||
// Successfully get the contents of the primary clip when they contain text.
|
||||
ClipboardContentFormat clipboardFormat = ClipboardContentFormat.PLAIN_TEXT;
|
||||
assertNull(platformPlugin.mPlatformMessageHandler.getClipboardData(clipboardFormat));
|
||||
// Primary clip contains non-text media.
|
||||
ClipData clip = ClipData.newPlainText("label", "Text");
|
||||
assertNull(platformPlugin.mPlatformMessageHandler.getClipboardData(clipboardFormat));
|
||||
clipboardManager.setPrimaryClip(clip);
|
||||
assertNotNull(platformPlugin.mPlatformMessageHandler.getClipboardData(clipboardFormat));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void platformPlugin_getClipboardDataIsNonNullWhenIOExceptionThrown() throws IOException {
|
||||
View fakeDecorView = mock(View.class);
|
||||
Window fakeWindow = mock(Window.class);
|
||||
Activity mockActivity = mock(Activity.class);
|
||||
when(fakeWindow.getDecorView()).thenReturn(fakeDecorView);
|
||||
when(mockActivity.getWindow()).thenReturn(fakeWindow);
|
||||
PlatformPlugin platformPlugin = new PlatformPlugin(mockActivity, mockPlatformChannel);
|
||||
setUpForTextClipboardTests(mockActivity);
|
||||
ContentResolver contentResolver = mock(ContentResolver.class);
|
||||
ClipData.Item mockItem = mock(ClipData.Item.class);
|
||||
Uri mockUri = mock(Uri.class);
|
||||
AssetFileDescriptor mockAssetFileDescriptor = mock(AssetFileDescriptor.class);
|
||||
|
||||
when(mockActivity.getContentResolver()).thenReturn(contentResolver);
|
||||
when(mockUri.getScheme()).thenReturn("content");
|
||||
when(mockItem.getText()).thenReturn(null);
|
||||
when(mockItem.getUri()).thenReturn(mockUri);
|
||||
when(contentResolver.openTypedAssetFileDescriptor(any(Uri.class), any(), any()))
|
||||
.thenReturn(mockAssetFileDescriptor);
|
||||
when(mockItem.coerceToText(mockActivity)).thenReturn("something non-null");
|
||||
doThrow(new IOException()).when(mockAssetFileDescriptor).close();
|
||||
|
||||
ClipData clip = new ClipData("label", new String[0], mockItem);
|
||||
|
||||
assertNull(platformPlugin.mPlatformMessageHandler.getClipboardData(clipboardFormat));
|
||||
clipboardManager.setPrimaryClip(clip);
|
||||
assertNotNull(platformPlugin.mPlatformMessageHandler.getClipboardData(clipboardFormat));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void platformPlugin_getClipboardDataIsNonNullWhenContentUriWithTextProvided()
|
||||
throws IOException {
|
||||
View fakeDecorView = mock(View.class);
|
||||
Window fakeWindow = mock(Window.class);
|
||||
Activity mockActivity = mock(Activity.class);
|
||||
when(fakeWindow.getDecorView()).thenReturn(fakeDecorView);
|
||||
when(mockActivity.getWindow()).thenReturn(fakeWindow);
|
||||
PlatformPlugin platformPlugin = new PlatformPlugin(mockActivity, mockPlatformChannel);
|
||||
setUpForTextClipboardTests(mockActivity);
|
||||
ContentResolver contentResolver = mock(ContentResolver.class);
|
||||
ClipData.Item mockItem = mock(ClipData.Item.class);
|
||||
Uri mockUri = mock(Uri.class);
|
||||
|
||||
when(mockActivity.getContentResolver()).thenReturn(contentResolver);
|
||||
when(mockUri.getScheme()).thenReturn("content");
|
||||
when(mockItem.getText()).thenReturn(null);
|
||||
when(mockItem.getUri()).thenReturn(mockUri);
|
||||
when(contentResolver.openTypedAssetFileDescriptor(any(Uri.class), any(), any()))
|
||||
.thenReturn(mock(AssetFileDescriptor.class));
|
||||
when(mockItem.coerceToText(mockActivity)).thenReturn("something non-null");
|
||||
|
||||
ClipData clip = new ClipData("label", new String[0], mockItem);
|
||||
|
||||
assertNull(platformPlugin.mPlatformMessageHandler.getClipboardData(clipboardFormat));
|
||||
clipboardManager.setPrimaryClip(clip);
|
||||
assertNotNull(platformPlugin.mPlatformMessageHandler.getClipboardData(clipboardFormat));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void platformPlugin_getClipboardDataIsNullWhenContentUriProvidedContainsNoText()
|
||||
throws IOException {
|
||||
View fakeDecorView = mock(View.class);
|
||||
Window fakeWindow = mock(Window.class);
|
||||
Activity mockActivity = mock(Activity.class);
|
||||
when(fakeWindow.getDecorView()).thenReturn(fakeDecorView);
|
||||
when(mockActivity.getWindow()).thenReturn(fakeWindow);
|
||||
PlatformPlugin platformPlugin = new PlatformPlugin(mockActivity, mockPlatformChannel);
|
||||
setUpForTextClipboardTests(mockActivity);
|
||||
ContentResolver contentResolver = ctx.getContentResolver();
|
||||
|
||||
when(mockActivity.getContentResolver()).thenReturn(contentResolver);
|
||||
|
||||
// Return null when the primary clip contains non-text media.
|
||||
ContentResolver contentResolver = spy(ctx.getContentResolver());
|
||||
when(fakeActivity.getContentResolver()).thenReturn(contentResolver);
|
||||
Uri uri = Uri.parse("content://media/external_primary/images/media/");
|
||||
clip = ClipData.newUri(contentResolver, "URI", uri);
|
||||
ClipData clip = ClipData.newUri(contentResolver, "URI", uri);
|
||||
|
||||
clipboardManager.setPrimaryClip(clip);
|
||||
assertNull(platformPlugin.mPlatformMessageHandler.getClipboardData(clipboardFormat));
|
||||
}
|
||||
|
||||
// Still return text when the AssetFileDescriptor throws an IOException.
|
||||
when(fakeActivity.getContentResolver()).thenReturn(contentResolver);
|
||||
ClipDescription clipDescription =
|
||||
new ClipDescription(
|
||||
"label",
|
||||
new String[] {
|
||||
ClipDescription.MIMETYPE_TEXT_PLAIN, ClipDescription.MIMETYPE_TEXT_URILIST
|
||||
});
|
||||
ClipData.Item clipDataItem = new ClipData.Item("Text", null, uri);
|
||||
ClipData clipData = new ClipData(clipDescription, clipDataItem);
|
||||
clipboardManager.setPrimaryClip(clipData);
|
||||
AssetFileDescriptor fakeAssetFileDescriptor = mock(AssetFileDescriptor.class);
|
||||
doReturn(fakeAssetFileDescriptor)
|
||||
.when(contentResolver)
|
||||
.openTypedAssetFileDescriptor(eq(uri), anyString(), eq(null));
|
||||
doThrow(new IOException()).when(fakeAssetFileDescriptor).close();
|
||||
assertNotNull(platformPlugin.mPlatformMessageHandler.getClipboardData(clipboardFormat));
|
||||
verify(fakeAssetFileDescriptor).close();
|
||||
@Test
|
||||
public void platformPlugin_getClipboardDataIsNullWhenNonContentUriProvided() throws IOException {
|
||||
View fakeDecorView = mock(View.class);
|
||||
Window fakeWindow = mock(Window.class);
|
||||
Activity mockActivity = mock(Activity.class);
|
||||
when(fakeWindow.getDecorView()).thenReturn(fakeDecorView);
|
||||
when(mockActivity.getWindow()).thenReturn(fakeWindow);
|
||||
PlatformPlugin platformPlugin = new PlatformPlugin(mockActivity, mockPlatformChannel);
|
||||
setUpForTextClipboardTests(mockActivity);
|
||||
ContentResolver contentResolver = ctx.getContentResolver();
|
||||
|
||||
when(mockActivity.getContentResolver()).thenReturn(contentResolver);
|
||||
|
||||
Uri uri = Uri.parse("file:///");
|
||||
ClipData clip = ClipData.newUri(contentResolver, "URI", uri);
|
||||
|
||||
clipboardManager.setPrimaryClip(clip);
|
||||
assertNull(platformPlugin.mPlatformMessageHandler.getClipboardData(clipboardFormat));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void platformPlugin_getClipboardDataIsNullWhenItemHasNoTextNorUri() throws IOException {
|
||||
View fakeDecorView = mock(View.class);
|
||||
Window fakeWindow = mock(Window.class);
|
||||
Activity mockActivity = mock(Activity.class);
|
||||
when(fakeWindow.getDecorView()).thenReturn(fakeDecorView);
|
||||
when(mockActivity.getWindow()).thenReturn(fakeWindow);
|
||||
PlatformPlugin platformPlugin = new PlatformPlugin(mockActivity, mockPlatformChannel);
|
||||
setUpForTextClipboardTests(mockActivity);
|
||||
ClipData.Item mockItem = mock(ClipData.Item.class);
|
||||
|
||||
when(mockItem.getText()).thenReturn(null);
|
||||
when(mockItem.getUri()).thenReturn(null);
|
||||
|
||||
ClipData clip = new ClipData("label", new String[0], mockItem);
|
||||
|
||||
clipboardManager.setPrimaryClip(clip);
|
||||
assertNull(platformPlugin.mPlatformMessageHandler.getClipboardData(clipboardFormat));
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@ -136,16 +229,13 @@ public class PlatformPluginTest {
|
||||
@Config(sdk = Build.VERSION_CODES.P)
|
||||
@Test
|
||||
public void platformPlugin_hasStrings() {
|
||||
ClipboardManager clipboardManager = spy(ctx.getSystemService(ClipboardManager.class));
|
||||
|
||||
View fakeDecorView = mock(View.class);
|
||||
Window fakeWindow = mock(Window.class);
|
||||
Activity mockActivity = mock(Activity.class);
|
||||
when(fakeWindow.getDecorView()).thenReturn(fakeDecorView);
|
||||
Activity fakeActivity = mock(Activity.class);
|
||||
when(fakeActivity.getWindow()).thenReturn(fakeWindow);
|
||||
when(fakeActivity.getSystemService(Context.CLIPBOARD_SERVICE)).thenReturn(clipboardManager);
|
||||
PlatformChannel fakePlatformChannel = mock(PlatformChannel.class);
|
||||
PlatformPlugin platformPlugin = new PlatformPlugin(fakeActivity, fakePlatformChannel);
|
||||
when(mockActivity.getWindow()).thenReturn(fakeWindow);
|
||||
PlatformPlugin platformPlugin = new PlatformPlugin(mockActivity, mockPlatformChannel);
|
||||
setUpForTextClipboardTests(mockActivity);
|
||||
|
||||
// Plain text
|
||||
ClipData clip = ClipData.newPlainText("label", "Text");
|
||||
@ -192,11 +282,10 @@ public class PlatformPluginTest {
|
||||
public void setNavigationBarDividerColor() {
|
||||
View fakeDecorView = mock(View.class);
|
||||
Window fakeWindow = mock(Window.class);
|
||||
Activity mockActivity = mock(Activity.class);
|
||||
when(fakeWindow.getDecorView()).thenReturn(fakeDecorView);
|
||||
Activity fakeActivity = mock(Activity.class);
|
||||
when(fakeActivity.getWindow()).thenReturn(fakeWindow);
|
||||
PlatformChannel fakePlatformChannel = mock(PlatformChannel.class);
|
||||
PlatformPlugin platformPlugin = new PlatformPlugin(fakeActivity, fakePlatformChannel);
|
||||
when(mockActivity.getWindow()).thenReturn(fakeWindow);
|
||||
PlatformPlugin platformPlugin = new PlatformPlugin(mockActivity, mockPlatformChannel);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 28) {
|
||||
// Default style test
|
||||
@ -265,16 +354,16 @@ public class PlatformPluginTest {
|
||||
@Config(sdk = Build.VERSION_CODES.R)
|
||||
@Test
|
||||
public void setNavigationBarIconBrightness() {
|
||||
View fakeDecorView = mock(View.class);
|
||||
Window fakeWindow = mock(Window.class);
|
||||
Activity mockActivity = mock(Activity.class);
|
||||
when(fakeWindow.getDecorView()).thenReturn(fakeDecorView);
|
||||
when(mockActivity.getWindow()).thenReturn(fakeWindow);
|
||||
PlatformPlugin platformPlugin = new PlatformPlugin(mockActivity, mockPlatformChannel);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 30) {
|
||||
View fakeDecorView = mock(View.class);
|
||||
WindowInsetsController fakeWindowInsetsController = mock(WindowInsetsController.class);
|
||||
Window fakeWindow = mock(Window.class);
|
||||
when(fakeWindow.getDecorView()).thenReturn(fakeDecorView);
|
||||
when(fakeWindow.getInsetsController()).thenReturn(fakeWindowInsetsController);
|
||||
Activity fakeActivity = mock(Activity.class);
|
||||
when(fakeActivity.getWindow()).thenReturn(fakeWindow);
|
||||
PlatformChannel fakePlatformChannel = mock(PlatformChannel.class);
|
||||
PlatformPlugin platformPlugin = new PlatformPlugin(fakeActivity, fakePlatformChannel);
|
||||
|
||||
SystemChromeStyle style =
|
||||
new SystemChromeStyle(
|
||||
@ -312,16 +401,16 @@ public class PlatformPluginTest {
|
||||
@Config(sdk = Build.VERSION_CODES.R)
|
||||
@Test
|
||||
public void setStatusBarIconBrightness() {
|
||||
View fakeDecorView = mock(View.class);
|
||||
Window fakeWindow = mock(Window.class);
|
||||
Activity mockActivity = mock(Activity.class);
|
||||
when(fakeWindow.getDecorView()).thenReturn(fakeDecorView);
|
||||
when(mockActivity.getWindow()).thenReturn(fakeWindow);
|
||||
PlatformPlugin platformPlugin = new PlatformPlugin(mockActivity, mockPlatformChannel);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 30) {
|
||||
View fakeDecorView = mock(View.class);
|
||||
WindowInsetsController fakeWindowInsetsController = mock(WindowInsetsController.class);
|
||||
Window fakeWindow = mock(Window.class);
|
||||
when(fakeWindow.getDecorView()).thenReturn(fakeDecorView);
|
||||
when(fakeWindow.getInsetsController()).thenReturn(fakeWindowInsetsController);
|
||||
Activity fakeActivity = mock(Activity.class);
|
||||
when(fakeActivity.getWindow()).thenReturn(fakeWindow);
|
||||
PlatformChannel fakePlatformChannel = mock(PlatformChannel.class);
|
||||
PlatformPlugin platformPlugin = new PlatformPlugin(fakeActivity, fakePlatformChannel);
|
||||
|
||||
SystemChromeStyle style =
|
||||
new SystemChromeStyle(
|
||||
@ -361,11 +450,10 @@ public class PlatformPluginTest {
|
||||
public void setSystemUiMode() {
|
||||
View fakeDecorView = mock(View.class);
|
||||
Window fakeWindow = mock(Window.class);
|
||||
Activity mockActivity = mock(Activity.class);
|
||||
when(fakeWindow.getDecorView()).thenReturn(fakeDecorView);
|
||||
Activity fakeActivity = mock(Activity.class);
|
||||
when(fakeActivity.getWindow()).thenReturn(fakeWindow);
|
||||
PlatformChannel fakePlatformChannel = mock(PlatformChannel.class);
|
||||
PlatformPlugin platformPlugin = new PlatformPlugin(fakeActivity, fakePlatformChannel);
|
||||
when(mockActivity.getWindow()).thenReturn(fakeWindow);
|
||||
PlatformPlugin platformPlugin = new PlatformPlugin(mockActivity, mockPlatformChannel);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 28) {
|
||||
platformPlugin.mPlatformMessageHandler.showSystemUiMode(
|
||||
@ -420,8 +508,7 @@ public class PlatformPluginTest {
|
||||
controller.setup();
|
||||
Activity fakeActivity = controller.get();
|
||||
|
||||
PlatformChannel fakePlatformChannel = mock(PlatformChannel.class);
|
||||
PlatformPlugin platformPlugin = new PlatformPlugin(fakeActivity, fakePlatformChannel);
|
||||
PlatformPlugin platformPlugin = new PlatformPlugin(fakeActivity, mockPlatformChannel);
|
||||
|
||||
// Subscribe to system UI visibility events.
|
||||
platformPlugin.mPlatformMessageHandler.setSystemUiChangeListener();
|
||||
@ -434,13 +521,13 @@ public class PlatformPluginTest {
|
||||
|
||||
// No events should have been sent to the platform channel yet. They are scheduled for
|
||||
// the next frame.
|
||||
verify(fakePlatformChannel, never()).systemChromeChanged(anyBoolean());
|
||||
verify(mockPlatformChannel, never()).systemChromeChanged(anyBoolean());
|
||||
|
||||
// Simulate the next frame.
|
||||
ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
|
||||
|
||||
// Now the platform channel should receive the event.
|
||||
verify(fakePlatformChannel).systemChromeChanged(false);
|
||||
verify(mockPlatformChannel).systemChromeChanged(false);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@ -450,9 +537,7 @@ public class PlatformPluginTest {
|
||||
ActivityController<Activity> controller = Robolectric.buildActivity(Activity.class);
|
||||
controller.setup();
|
||||
Activity fakeActivity = controller.get();
|
||||
|
||||
PlatformChannel fakePlatformChannel = mock(PlatformChannel.class);
|
||||
PlatformPlugin platformPlugin = new PlatformPlugin(fakeActivity, fakePlatformChannel);
|
||||
PlatformPlugin platformPlugin = new PlatformPlugin(fakeActivity, mockPlatformChannel);
|
||||
|
||||
// Subscribe to system Ui visibility events.
|
||||
platformPlugin.mPlatformMessageHandler.setSystemUiChangeListener();
|
||||
@ -462,13 +547,13 @@ public class PlatformPluginTest {
|
||||
|
||||
// No events should have been sent to the platform channel yet. They are scheduled for
|
||||
// the next frame.
|
||||
verify(fakePlatformChannel, never()).systemChromeChanged(anyBoolean());
|
||||
verify(mockPlatformChannel, never()).systemChromeChanged(anyBoolean());
|
||||
|
||||
// Simulate the next frame.
|
||||
ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
|
||||
|
||||
// Now the platform channel should receive the event.
|
||||
verify(fakePlatformChannel).systemChromeChanged(true);
|
||||
verify(mockPlatformChannel).systemChromeChanged(true);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@ -478,11 +563,10 @@ public class PlatformPluginTest {
|
||||
public void doNotEnableEdgeToEdgeOnOlderSdk() {
|
||||
View fakeDecorView = mock(View.class);
|
||||
Window fakeWindow = mock(Window.class);
|
||||
Activity mockActivity = mock(Activity.class);
|
||||
when(fakeWindow.getDecorView()).thenReturn(fakeDecorView);
|
||||
Activity fakeActivity = mock(Activity.class);
|
||||
when(fakeActivity.getWindow()).thenReturn(fakeWindow);
|
||||
PlatformChannel fakePlatformChannel = mock(PlatformChannel.class);
|
||||
PlatformPlugin platformPlugin = new PlatformPlugin(fakeActivity, fakePlatformChannel);
|
||||
when(mockActivity.getWindow()).thenReturn(fakeWindow);
|
||||
PlatformPlugin platformPlugin = new PlatformPlugin(mockActivity, mockPlatformChannel);
|
||||
|
||||
platformPlugin.mPlatformMessageHandler.showSystemUiMode(
|
||||
PlatformChannel.SystemUiMode.EDGE_TO_EDGE);
|
||||
@ -500,11 +584,10 @@ public class PlatformPluginTest {
|
||||
public void verifyWindowFlagsSetToStyleOverlays() {
|
||||
View fakeDecorView = mock(View.class);
|
||||
Window fakeWindow = mock(Window.class);
|
||||
Activity mockActivity = mock(Activity.class);
|
||||
when(fakeWindow.getDecorView()).thenReturn(fakeDecorView);
|
||||
Activity fakeActivity = mock(Activity.class);
|
||||
when(fakeActivity.getWindow()).thenReturn(fakeWindow);
|
||||
PlatformChannel fakePlatformChannel = mock(PlatformChannel.class);
|
||||
PlatformPlugin platformPlugin = new PlatformPlugin(fakeActivity, fakePlatformChannel);
|
||||
when(mockActivity.getWindow()).thenReturn(fakeWindow);
|
||||
PlatformPlugin platformPlugin = new PlatformPlugin(mockActivity, mockPlatformChannel);
|
||||
|
||||
SystemChromeStyle style =
|
||||
new SystemChromeStyle(
|
||||
@ -521,7 +604,6 @@ public class PlatformPluginTest {
|
||||
@Test
|
||||
public void setFrameworkHandlesBackFlutterActivity() {
|
||||
Activity mockActivity = mock(Activity.class);
|
||||
PlatformChannel mockPlatformChannel = mock(PlatformChannel.class);
|
||||
PlatformPluginDelegate mockPlatformPluginDelegate = mock(PlatformPluginDelegate.class);
|
||||
PlatformPlugin platformPlugin =
|
||||
new PlatformPlugin(mockActivity, mockPlatformChannel, mockPlatformPluginDelegate);
|
||||
@ -534,12 +616,12 @@ public class PlatformPluginTest {
|
||||
@Test
|
||||
public void popSystemNavigatorFlutterActivity() {
|
||||
Activity mockActivity = mock(Activity.class);
|
||||
PlatformChannel mockPlatformChannel = mock(PlatformChannel.class);
|
||||
PlatformPluginDelegate mockPlatformPluginDelegate = mock(PlatformPluginDelegate.class);
|
||||
when(mockPlatformPluginDelegate.popSystemNavigator()).thenReturn(false);
|
||||
PlatformPlugin platformPlugin =
|
||||
new PlatformPlugin(mockActivity, mockPlatformChannel, mockPlatformPluginDelegate);
|
||||
|
||||
when(mockPlatformPluginDelegate.popSystemNavigator()).thenReturn(false);
|
||||
|
||||
platformPlugin.mPlatformMessageHandler.popSystemNavigator();
|
||||
|
||||
verify(mockPlatformPluginDelegate, times(1)).popSystemNavigator();
|
||||
@ -549,12 +631,12 @@ public class PlatformPluginTest {
|
||||
@Test
|
||||
public void doesNotDoAnythingByDefaultIfPopSystemNavigatorOverridden() {
|
||||
Activity mockActivity = mock(Activity.class);
|
||||
PlatformChannel mockPlatformChannel = mock(PlatformChannel.class);
|
||||
PlatformPluginDelegate mockPlatformPluginDelegate = mock(PlatformPluginDelegate.class);
|
||||
when(mockPlatformPluginDelegate.popSystemNavigator()).thenReturn(true);
|
||||
PlatformPlugin platformPlugin =
|
||||
new PlatformPlugin(mockActivity, mockPlatformChannel, mockPlatformPluginDelegate);
|
||||
|
||||
when(mockPlatformPluginDelegate.popSystemNavigator()).thenReturn(true);
|
||||
|
||||
platformPlugin.mPlatformMessageHandler.popSystemNavigator();
|
||||
|
||||
verify(mockPlatformPluginDelegate, times(1)).popSystemNavigator();
|
||||
@ -579,7 +661,6 @@ public class PlatformPluginTest {
|
||||
};
|
||||
activity.getOnBackPressedDispatcher().addCallback(backCallback);
|
||||
|
||||
PlatformChannel mockPlatformChannel = mock(PlatformChannel.class);
|
||||
PlatformPluginDelegate mockPlatformPluginDelegate = mock(PlatformPluginDelegate.class);
|
||||
when(mockPlatformPluginDelegate.popSystemNavigator()).thenReturn(false);
|
||||
PlatformPlugin platformPlugin =
|
||||
@ -598,7 +679,6 @@ public class PlatformPluginTest {
|
||||
@Test
|
||||
public void doesNotDoAnythingByDefaultIfFragmentPopSystemNavigatorOverridden() {
|
||||
FragmentActivity activity = spy(Robolectric.setupActivity(FragmentActivity.class));
|
||||
PlatformChannel mockPlatformChannel = mock(PlatformChannel.class);
|
||||
PlatformPluginDelegate mockPlatformPluginDelegate = mock(PlatformPluginDelegate.class);
|
||||
when(mockPlatformPluginDelegate.popSystemNavigator()).thenReturn(true);
|
||||
PlatformPlugin platformPlugin =
|
||||
@ -614,7 +694,6 @@ public class PlatformPluginTest {
|
||||
@Test
|
||||
public void setRequestedOrientationFlutterFragment() {
|
||||
FragmentActivity mockFragmentActivity = mock(FragmentActivity.class);
|
||||
PlatformChannel mockPlatformChannel = mock(PlatformChannel.class);
|
||||
PlatformPluginDelegate mockPlatformPluginDelegate = mock(PlatformPluginDelegate.class);
|
||||
when(mockPlatformPluginDelegate.popSystemNavigator()).thenReturn(false);
|
||||
PlatformPlugin platformPlugin =
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user