1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.documentsui.picker; 18 19 import static junit.framework.Assert.assertTrue; 20 21 import static org.junit.Assert.assertEquals; 22 import static org.junit.Assert.assertNotNull; 23 24 import android.app.Activity; 25 import android.content.ClipData; 26 import android.content.Intent; 27 import android.net.Uri; 28 import android.os.AsyncTask; 29 import android.provider.DocumentsContract; 30 import android.provider.DocumentsContract.Path; 31 import android.support.test.filters.MediumTest; 32 import android.support.test.runner.AndroidJUnit4; 33 34 import com.android.documentsui.AbstractActionHandler; 35 import com.android.documentsui.R; 36 import com.android.documentsui.base.DocumentStack; 37 import com.android.documentsui.base.RootInfo; 38 import com.android.documentsui.base.Shared; 39 import com.android.documentsui.base.State; 40 import com.android.documentsui.base.State.ActionType; 41 import com.android.documentsui.testing.DocumentStackAsserts; 42 import com.android.documentsui.testing.TestEnv; 43 import com.android.documentsui.testing.TestProvidersAccess; 44 import com.android.documentsui.testing.TestLastAccessedStorage; 45 import com.android.documentsui.testing.TestResolveInfo; 46 47 import org.junit.AfterClass; 48 import org.junit.Before; 49 import org.junit.Test; 50 import org.junit.runner.RunWith; 51 52 import java.util.Arrays; 53 54 @RunWith(AndroidJUnit4.class) 55 @MediumTest 56 public class ActionHandlerTest { 57 58 private TestEnv mEnv; 59 private TestActivity mActivity; 60 private ActionHandler<TestActivity> mHandler; 61 private TestLastAccessedStorage mLastAccessed; 62 63 @Before 64 public void setUp() { 65 mEnv = TestEnv.create(); 66 mActivity = TestActivity.create(mEnv); 67 mEnv.providers.configurePm(mActivity.packageMgr); 68 mLastAccessed = new TestLastAccessedStorage(); 69 70 mHandler = new ActionHandler<>( 71 mActivity, 72 mEnv.state, 73 mEnv.providers, 74 mEnv.docs, 75 mEnv.searchViewManager, 76 mEnv::lookupExecutor, 77 mEnv.injector, 78 mLastAccessed 79 ); 80 81 mEnv.dialogs.confirmNext(); 82 83 mEnv.selectionMgr.select("1"); 84 85 AsyncTask.setDefaultExecutor(mEnv.mExecutor); 86 } 87 88 @AfterClass 89 public static void tearDownOnce() { 90 AsyncTask.setDefaultExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 91 } 92 93 @Test 94 public void testInitLocation_RestoresIfStackIsLoaded() throws Exception { 95 mEnv.state.stack.changeRoot(TestProvidersAccess.DOWNLOADS); 96 mEnv.state.stack.push(TestEnv.FOLDER_0); 97 98 mHandler.initLocation(mActivity.getIntent()); 99 mActivity.restoreRootAndDirectory.assertCalled(); 100 } 101 102 @Test 103 public void testInitLocation_LoadsRootDocIfStackOnlyHasRoot() throws Exception { 104 mEnv.state.stack.changeRoot(TestProvidersAccess.HAMMY); 105 106 mHandler.initLocation(mActivity.getIntent()); 107 assertRootPicked(TestProvidersAccess.HAMMY.getUri()); 108 } 109 110 @Test 111 public void testInitLocation_CopyDestination_DefaultsToDownloads() throws Exception { 112 mActivity.resources.bools.put(R.bool.show_documents_root, false); 113 114 Intent intent = mActivity.getIntent(); 115 intent.setAction(Shared.ACTION_PICK_COPY_DESTINATION); 116 mHandler.initLocation(mActivity.getIntent()); 117 assertRootPicked(TestProvidersAccess.DOWNLOADS.getUri()); 118 } 119 120 @Test 121 public void testInitLocation_CopyDestination_DocumentsRootEnabled() throws Exception { 122 mActivity.resources.bools.put(R.bool.show_documents_root, true); 123 mActivity.resources.strings.put(R.string.default_root_uri, TestProvidersAccess.HOME.getUri().toString()); 124 125 Intent intent = mActivity.getIntent(); 126 intent.setAction(Shared.ACTION_PICK_COPY_DESTINATION); 127 mHandler.initLocation(intent); 128 assertRootPicked(TestProvidersAccess.HOME.getUri()); 129 } 130 131 @Test 132 public void testInitLocation_LaunchToDocuments() throws Exception { 133 if (!mEnv.features.isLaunchToDocumentEnabled()) { 134 return; 135 } 136 137 mEnv.docs.nextIsDocumentsUri = true; 138 mEnv.docs.nextPath = new Path( 139 TestProvidersAccess.HOME.rootId, 140 Arrays.asList( 141 TestEnv.FOLDER_0.documentId, 142 TestEnv.FOLDER_1.documentId, 143 TestEnv.FILE_GIF.documentId)); 144 mEnv.docs.nextDocuments = 145 Arrays.asList(TestEnv.FOLDER_0, TestEnv.FOLDER_1, TestEnv.FILE_GIF); 146 147 mActivity.refreshCurrentRootAndDirectory.assertNotCalled(); 148 Intent intent = mActivity.getIntent(); 149 intent.setAction(Intent.ACTION_GET_CONTENT); 150 intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, TestEnv.FILE_GIF.derivedUri); 151 mHandler.initLocation(intent); 152 153 mEnv.beforeAsserts(); 154 155 DocumentStackAsserts.assertEqualsTo(mEnv.state.stack, TestProvidersAccess.HOME, 156 Arrays.asList(TestEnv.FOLDER_0, TestEnv.FOLDER_1)); 157 mActivity.refreshCurrentRootAndDirectory.assertCalled(); 158 } 159 160 @Test 161 public void testInitLocation_RestoresLastAccessedStack() throws Exception { 162 final DocumentStack stack = 163 new DocumentStack(TestProvidersAccess.HAMMY, TestEnv.FOLDER_0, TestEnv.FOLDER_1); 164 mLastAccessed.setLastAccessed(mActivity, stack); 165 166 mHandler.initLocation(mActivity.getIntent()); 167 168 mEnv.beforeAsserts(); 169 assertEquals(stack, mEnv.state.stack); 170 mActivity.refreshCurrentRootAndDirectory.assertCalled(); 171 } 172 173 @Test 174 public void testInitLocation_DefaultToRecents_ActionGetContent() throws Exception { 175 testInitLocationDefaultToRecentsOnAction(State.ACTION_GET_CONTENT); 176 } 177 178 @Test 179 public void testInitLocation_DefaultToRecents_ActionOpen() throws Exception { 180 testInitLocationDefaultToRecentsOnAction(State.ACTION_OPEN); 181 } 182 183 @Test 184 public void testInitLocation_DefaultToRecents_ActionOpenTree() throws Exception { 185 testInitLocationDefaultToRecentsOnAction(State.ACTION_OPEN_TREE); 186 } 187 188 @Test 189 public void testInitLocation_DefaultsToDownloads_ActionCreate() throws Exception { 190 mEnv.state.action = State.ACTION_CREATE; 191 mActivity.resources.bools.put(R.bool.show_documents_root, false); 192 193 mActivity.refreshCurrentRootAndDirectory.assertNotCalled(); 194 195 mHandler.initLocation(mActivity.getIntent()); 196 197 assertRootPicked(TestProvidersAccess.DOWNLOADS.getUri()); 198 } 199 200 @Test 201 public void testOpenContainerDocument() { 202 mHandler.openContainerDocument(TestEnv.FOLDER_0); 203 204 assertEquals(TestEnv.FOLDER_0, mEnv.state.stack.peek()); 205 206 mActivity.refreshCurrentRootAndDirectory.assertCalled(); 207 } 208 209 @Test 210 public void testPickDocument_SetsCorrectResultAndFinishes_ActionPickCopyDestination() 211 throws Exception { 212 213 mEnv.state.action = State.ACTION_PICK_COPY_DESTINATION; 214 mEnv.state.stack.changeRoot(TestProvidersAccess.HOME); 215 mEnv.state.stack.push(TestEnv.FOLDER_1); 216 mEnv.state.stack.push(TestEnv.FOLDER_2); 217 218 mActivity.finishedHandler.assertNotCalled(); 219 220 mHandler.pickDocument(TestEnv.FOLDER_2); 221 222 mEnv.beforeAsserts(); 223 224 assertLastAccessedStackUpdated(); 225 226 assertEquals(Activity.RESULT_OK, (long) mActivity.setResult.getLastValue().first); 227 final Intent result = mActivity.setResult.getLastValue().second; 228 assertPermission(result, Intent.FLAG_GRANT_READ_URI_PERMISSION, false); 229 assertPermission(result, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, false); 230 assertPermission(result, Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION, false); 231 assertPermission(result, Intent.FLAG_GRANT_PREFIX_URI_PERMISSION, false); 232 assertContent(result, TestEnv.FOLDER_2.derivedUri); 233 234 mActivity.finishedHandler.assertCalled(); 235 } 236 237 @Test 238 public void testPickDocument_SetsCorrectResultAndFinishes_ActionOpenTree() throws Exception { 239 mEnv.state.action = State.ACTION_OPEN_TREE; 240 mEnv.state.stack.changeRoot(TestProvidersAccess.HOME); 241 mEnv.state.stack.push(TestEnv.FOLDER_1); 242 mEnv.state.stack.push(TestEnv.FOLDER_2); 243 244 mActivity.finishedHandler.assertNotCalled(); 245 246 mHandler.pickDocument(TestEnv.FOLDER_2); 247 248 mEnv.beforeAsserts(); 249 250 assertLastAccessedStackUpdated(); 251 252 assertEquals(Activity.RESULT_OK, (long) mActivity.setResult.getLastValue().first); 253 final Intent result = mActivity.setResult.getLastValue().second; 254 assertPermission(result, Intent.FLAG_GRANT_READ_URI_PERMISSION, true); 255 assertPermission(result, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, true); 256 assertPermission(result, Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION, true); 257 assertPermission(result, Intent.FLAG_GRANT_PREFIX_URI_PERMISSION, true); 258 assertContent(result, DocumentsContract.buildTreeDocumentUri( 259 TestProvidersAccess.HOME.authority, TestEnv.FOLDER_2.documentId)); 260 261 mActivity.finishedHandler.assertCalled(); 262 } 263 264 @Test 265 public void testSaveDocument_SetsCorrectResultAndFinishes() throws Exception { 266 mEnv.state.action = State.ACTION_CREATE; 267 mEnv.state.stack.changeRoot(TestProvidersAccess.HOME); 268 mEnv.state.stack.push(TestEnv.FOLDER_1); 269 270 final String mimeType = "audio/aac"; 271 final String displayName = "foobar.m4a"; 272 273 mHandler.saveDocument(mimeType, displayName, (boolean inProgress) -> {}); 274 275 mEnv.beforeAsserts(); 276 277 mEnv.docs.assertCreatedDocument(TestEnv.FOLDER_1, mimeType, displayName); 278 final Uri docUri = mEnv.docs.getLastCreatedDocumentUri(); 279 280 assertLastAccessedStackUpdated(); 281 282 assertEquals(Activity.RESULT_OK, (long) mActivity.setResult.getLastValue().first); 283 final Intent result = mActivity.setResult.getLastValue().second; 284 assertPermission(result, Intent.FLAG_GRANT_READ_URI_PERMISSION, true); 285 assertPermission(result, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, true); 286 assertPermission(result, Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION, true); 287 assertPermission(result, Intent.FLAG_GRANT_PREFIX_URI_PERMISSION, false); 288 assertContent(result, docUri); 289 290 mActivity.finishedHandler.assertCalled(); 291 } 292 293 @Test 294 public void testSaveDocument_ConfirmsOverwrite() { 295 if (!mEnv.features.isOverwriteConfirmationEnabled()) { 296 return; 297 } 298 299 mEnv.state.action = State.ACTION_CREATE; 300 mEnv.state.stack.changeRoot(TestProvidersAccess.HOME); 301 mEnv.state.stack.push(TestEnv.FOLDER_1); 302 303 mHandler.saveDocument(null, TestEnv.FILE_JPG); 304 305 mEnv.dialogs.assertOverwriteConfirmed(TestEnv.FILE_JPG); 306 } 307 308 @Test 309 public void testFinishPicking_SetsCorrectResultAndFinishes_ActionGetContent() throws Exception { 310 mEnv.state.action = State.ACTION_GET_CONTENT; 311 mEnv.state.stack.changeRoot(TestProvidersAccess.HOME); 312 mEnv.state.stack.push(TestEnv.FOLDER_1); 313 314 mActivity.finishedHandler.assertNotCalled(); 315 316 mHandler.finishPicking(TestEnv.FILE_JPG.derivedUri); 317 318 mEnv.beforeAsserts(); 319 320 assertLastAccessedStackUpdated(); 321 322 assertEquals(Activity.RESULT_OK, (long) mActivity.setResult.getLastValue().first); 323 final Intent result = mActivity.setResult.getLastValue().second; 324 assertPermission(result, Intent.FLAG_GRANT_READ_URI_PERMISSION, true); 325 assertPermission(result, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, false); 326 assertPermission(result, Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION, false); 327 assertPermission(result, Intent.FLAG_GRANT_PREFIX_URI_PERMISSION, false); 328 assertContent(result, TestEnv.FILE_JPG.derivedUri); 329 330 mActivity.finishedHandler.assertCalled(); 331 } 332 333 @Test 334 public void testFinishPicking_SetsCorrectResultAndFinishes_ActionGetContent_MultipleSelection() 335 throws Exception { 336 mEnv.state.action = State.ACTION_GET_CONTENT; 337 mEnv.state.stack.changeRoot(TestProvidersAccess.HOME); 338 mEnv.state.stack.push(TestEnv.FOLDER_1); 339 mEnv.state.acceptMimes = new String[] { "image/*" }; 340 341 mActivity.finishedHandler.assertNotCalled(); 342 343 mHandler.finishPicking(TestEnv.FILE_JPG.derivedUri, TestEnv.FILE_GIF.derivedUri); 344 345 mEnv.beforeAsserts(); 346 347 assertLastAccessedStackUpdated(); 348 349 assertEquals(Activity.RESULT_OK, (long) mActivity.setResult.getLastValue().first); 350 final Intent result = mActivity.setResult.getLastValue().second; 351 assertPermission(result, Intent.FLAG_GRANT_READ_URI_PERMISSION, true); 352 assertPermission(result, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, false); 353 assertPermission(result, Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION, false); 354 assertPermission(result, Intent.FLAG_GRANT_PREFIX_URI_PERMISSION, false); 355 assertContent(result, TestEnv.FILE_JPG.derivedUri, TestEnv.FILE_GIF.derivedUri); 356 357 mActivity.finishedHandler.assertCalled(); 358 } 359 360 @Test 361 public void testFinishPicking_SetsCorrectResultAndFinishes_ActionOpen() throws Exception { 362 mEnv.state.action = State.ACTION_OPEN; 363 mEnv.state.stack.changeRoot(TestProvidersAccess.HOME); 364 mEnv.state.stack.push(TestEnv.FOLDER_1); 365 366 mActivity.finishedHandler.assertNotCalled(); 367 368 mHandler.finishPicking(TestEnv.FILE_JPG.derivedUri); 369 370 mEnv.beforeAsserts(); 371 372 assertLastAccessedStackUpdated(); 373 374 assertEquals(Activity.RESULT_OK, (long) mActivity.setResult.getLastValue().first); 375 final Intent result = mActivity.setResult.getLastValue().second; 376 assertPermission(result, Intent.FLAG_GRANT_READ_URI_PERMISSION, true); 377 assertPermission(result, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, true); 378 assertPermission(result, Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION, true); 379 assertPermission(result, Intent.FLAG_GRANT_PREFIX_URI_PERMISSION, false); 380 assertContent(result, TestEnv.FILE_JPG.derivedUri); 381 382 mActivity.finishedHandler.assertCalled(); 383 } 384 385 @Test 386 public void testFinishPicking_SetsCorrectResultAndFinishes_ActionOpen_MultipleSelection() 387 throws Exception { 388 mEnv.state.action = State.ACTION_OPEN; 389 mEnv.state.stack.changeRoot(TestProvidersAccess.HOME); 390 mEnv.state.stack.push(TestEnv.FOLDER_1); 391 mEnv.state.acceptMimes = new String[] { "image/*" }; 392 393 mActivity.finishedHandler.assertNotCalled(); 394 395 mHandler.finishPicking(TestEnv.FILE_JPG.derivedUri, TestEnv.FILE_GIF.derivedUri); 396 397 mEnv.beforeAsserts(); 398 399 assertLastAccessedStackUpdated(); 400 401 assertEquals(Activity.RESULT_OK, (long) mActivity.setResult.getLastValue().first); 402 final Intent result = mActivity.setResult.getLastValue().second; 403 assertPermission(result, Intent.FLAG_GRANT_READ_URI_PERMISSION, true); 404 assertPermission(result, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, true); 405 assertPermission(result, Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION, true); 406 assertPermission(result, Intent.FLAG_GRANT_PREFIX_URI_PERMISSION, false); 407 assertContent(result, TestEnv.FILE_JPG.derivedUri, TestEnv.FILE_GIF.derivedUri); 408 409 mActivity.finishedHandler.assertCalled(); 410 } 411 412 @Test 413 public void testFinishPicking_SetsCorrectResultAndFinishes_ActionCreate() throws Exception { 414 mEnv.state.action = State.ACTION_CREATE; 415 mEnv.state.stack.changeRoot(TestProvidersAccess.HOME); 416 mEnv.state.stack.push(TestEnv.FOLDER_1); 417 418 mActivity.finishedHandler.assertNotCalled(); 419 420 mHandler.finishPicking(TestEnv.FILE_JPG.derivedUri); 421 422 mEnv.beforeAsserts(); 423 424 assertLastAccessedStackUpdated(); 425 426 assertEquals(Activity.RESULT_OK, (long) mActivity.setResult.getLastValue().first); 427 final Intent result = mActivity.setResult.getLastValue().second; 428 assertPermission(result, Intent.FLAG_GRANT_READ_URI_PERMISSION, true); 429 assertPermission(result, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, true); 430 assertPermission(result, Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION, true); 431 assertPermission(result, Intent.FLAG_GRANT_PREFIX_URI_PERMISSION, false); 432 assertContent(result, TestEnv.FILE_JPG.derivedUri); 433 434 mActivity.finishedHandler.assertCalled(); 435 } 436 437 @Test 438 public void testOnAppPickedResult_OnOK() throws Exception { 439 Intent intent = new Intent(); 440 mHandler.onActivityResult(AbstractActionHandler.CODE_FORWARD, Activity.RESULT_OK, intent); 441 mActivity.finishedHandler.assertCalled(); 442 mActivity.setResult.assertCalled(); 443 444 assertEquals(Activity.RESULT_OK, (long) mActivity.setResult.getLastValue().first); 445 assertEquals(intent, mActivity.setResult.getLastValue().second); 446 } 447 448 @Test 449 public void testOnAppPickedResult_OnNotOK() throws Exception { 450 Intent intent = new Intent(); 451 mHandler.onActivityResult(0, Activity.RESULT_OK, intent); 452 mActivity.finishedHandler.assertNotCalled(); 453 mActivity.setResult.assertNotCalled(); 454 455 mHandler.onActivityResult(AbstractActionHandler.CODE_FORWARD, Activity.RESULT_CANCELED, 456 intent); 457 mActivity.finishedHandler.assertNotCalled(); 458 mActivity.setResult.assertNotCalled(); 459 } 460 461 @Test 462 public void testOpenAppRoot() throws Exception { 463 mHandler.openRoot(TestResolveInfo.create()); 464 assertEquals((long) mActivity.startActivityForResult.getLastValue().second, 465 AbstractActionHandler.CODE_FORWARD); 466 assertNotNull(mActivity.startActivityForResult.getLastValue().first); 467 } 468 469 private void testInitLocationDefaultToRecentsOnAction(@ActionType int action) 470 throws Exception { 471 mEnv.state.action = action; 472 473 mActivity.refreshCurrentRootAndDirectory.assertNotCalled(); 474 475 mHandler.initLocation(mActivity.getIntent()); 476 477 mEnv.beforeAsserts(); 478 assertEquals(TestProvidersAccess.RECENTS, mEnv.state.stack.getRoot()); 479 mActivity.refreshCurrentRootAndDirectory.assertCalled(); 480 } 481 482 private void assertRootPicked(Uri expectedUri) throws Exception { 483 mEnv.beforeAsserts(); 484 485 mActivity.rootPicked.assertCalled(); 486 RootInfo root = mActivity.rootPicked.getLastValue(); 487 assertNotNull(root); 488 assertEquals(expectedUri, root.getUri()); 489 } 490 491 private void assertLastAccessedStackUpdated() { 492 assertEquals(mEnv.state.stack, mLastAccessed.getLastAccessed( 493 mActivity, mEnv.providers, mEnv.state)); 494 } 495 496 private void assertPermission(Intent intent, int permission, boolean granted) { 497 int flags = intent.getFlags(); 498 499 if (granted) { 500 assertEquals(permission, flags & permission); 501 } else { 502 assertEquals(0, flags & permission); 503 } 504 } 505 506 private void assertContent(Intent intent, Uri... contents) { 507 if (contents.length == 1) { 508 assertEquals(contents[0], intent.getData()); 509 } else { 510 ClipData clipData = intent.getClipData(); 511 512 assertNotNull(clipData); 513 for (int i = 0; i < mEnv.state.acceptMimes.length; ++i) { 514 assertEquals(mEnv.state.acceptMimes[i], clipData.getDescription().getMimeType(i)); 515 } 516 for (int i = 0; i < contents.length; ++i) { 517 assertEquals(contents[i], clipData.getItemAt(i).getUri()); 518 } 519 } 520 } 521 } 522