blob: 6a0c074d50036f300201558167defc299a1a9472 [file] [log] [blame]
// Copyright 2016 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.chrome.browser;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
import android.view.Window;
import androidx.test.filters.LargeTest;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.chromium.base.supplier.ObservableSupplier;
import org.chromium.base.task.PostTask;
import org.chromium.base.task.TaskTraits;
import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.chrome.browser.flags.ChromeSwitches;
import org.chromium.chrome.browser.share.ShareDelegate;
import org.chromium.chrome.browser.share.ShareDelegateImpl;
import org.chromium.chrome.browser.share.ShareHelper;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tabmodel.TabModelSelector;
import org.chromium.chrome.browser.ui.RootUiCoordinator;
import org.chromium.chrome.browser.util.ChromeFileProvider;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
import org.chromium.chrome.test.util.browser.tabmodel.MockTabModelSelector;
import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
import org.chromium.content_public.browser.test.util.TestThreadUtils;
import org.chromium.ui.base.WindowAndroid;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.concurrent.ExecutionException;
/**
* Instrumentation tests for Share intents.
*/
@RunWith(ChromeJUnit4ClassRunner.class)
@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
public class ShareIntentTest {
@Rule
public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
private static final String TAG = "ShareIntentTest";
/**
* Mock activity class that overrides the startActivity and checks if the file passed in the
* intent can be opened.
*
* This class is a wrapper around the actual activity of the test, while it also inherits from
* activity and redirects the calls to the methods to the actual activity.
*/
private static class MockChromeActivity extends ChromeTabbedActivity {
private final Object mLock = new Object();
private boolean mCheckCompleted;
private ChromeActivity mActivity;
public MockChromeActivity(ChromeActivity activity) {
mActivity = activity;
mCheckCompleted = false;
}
/**
* Overrides startActivity and notifies check completed when the file from the uri of the
* intent is opened.
*/
@Override
public void startActivity(Intent intent) {
processStartActivityIntent(intent);
}
@Override
public void startActivityForResult(Intent intent, int requestCode) {
processStartActivityIntent(intent);
}
private void processStartActivityIntent(Intent intent) {
final Uri uri = intent.getClipData().getItemAt(0).getUri();
PostTask.postTask(TaskTraits.BEST_EFFORT_MAY_BLOCK, () -> {
ChromeFileProvider provider = new ChromeFileProvider();
ParcelFileDescriptor file = null;
try {
file = provider.openFile(uri, "r");
if (file != null) file.close();
} catch (IOException e) {
assert false : "Error while opening the file";
}
synchronized (mLock) {
mCheckCompleted = true;
mLock.notify();
}
});
}
/**
* Waits till the check for file opening is completed.
*/
public void waitForFileCheck() throws InterruptedException {
synchronized (mLock) {
while (!mCheckCompleted) {
mLock.wait();
}
}
}
@Override
public String getPackageName() {
return mActivity.getPackageName();
}
@Override
public Tab getActivityTab() {
return mActivity.getActivityTab();
}
@Override
public PackageManager getPackageManager() {
return mActivity.getPackageManager();
}
@Override
public Window getWindow() {
return mActivity.getWindow();
}
@Override
public ActivityTabProvider getActivityTabProvider() {
return mActivity.getActivityTabProvider();
}
@Override
public BottomSheetController getBottomSheetController() {
return mActivity.getBottomSheetController();
}
@Override
public TabModelSelector getTabModelSelector() {
// TabModelSelector remains uninitialized for this test. Return a mock instead.
return new MockTabModelSelector(1, 0, null);
}
@Override
public ObservableSupplier<ShareDelegate> getShareDelegateSupplier() {
return mActivity.getShareDelegateSupplier();
}
@Override
public Object getSystemService(String name) {
// Prevents a scenario where InputMethodManager#hideSoftInput()
// gets called before Activity#onCreate() gets called in this test.
return null;
}
}
@Test
@LargeTest
public void testShareIntent() throws ExecutionException, InterruptedException {
MockChromeActivity mockActivity = TestThreadUtils.runOnUiThreadBlocking(() -> {
// Sets a test component as last shared and "shareDirectly" option is set so that
// the share selector menu is not opened. The start activity is overridden, so the
// package and class names do not matter.
return new MockChromeActivity(mActivityTestRule.getActivity());
});
RootUiCoordinator rootUiCoordinator = TestThreadUtils.runOnUiThreadBlocking(() -> {
return new RootUiCoordinator(mockActivity, null,
mockActivity.getShareDelegateSupplier(), mockActivity.getActivityTabProvider(),
null, null, mockActivity.getOverviewModeBehaviorSupplier(), null);
});
ShareHelper.setLastShareComponentName(new ComponentName("test.package", "test.activity"));
// Skips the capture of screenshot and notifies with an empty file.
ShareDelegateImpl.setScreenshotCaptureSkippedForTesting(true);
WindowAndroid window = TestThreadUtils.runOnUiThreadBlocking(() -> {
return new WindowAndroid(mActivityTestRule.getActivity()) {
@Override
public WeakReference<Activity> getActivity() {
return new WeakReference<>(mockActivity);
}
};
});
TestThreadUtils.runOnUiThreadBlocking(
() -> mockActivity.getActivityTab().updateAttachment(window, null));
TestThreadUtils.runOnUiThreadBlocking(
()
-> rootUiCoordinator.onShareMenuItemSelected(
true /* shareDirectly */, false /* isIncognito */));
mockActivity.waitForFileCheck();
ShareHelper.setLastShareComponentName(new ComponentName("", ""));
TestThreadUtils.runOnUiThreadBlocking(() -> {
mockActivity.getActivityTab().updateAttachment(null, null);
window.destroy();
});
}
@Before
public void setUp() throws InterruptedException {
mActivityTestRule.startMainActivityOnBlankPage();
}
@After
public void tearDown() {
ShareDelegateImpl.setScreenshotCaptureSkippedForTesting(false);
}
}