Beispiel #1
0
  /*
  Bug http://crbug/415711
  */
  @MediumTest
  @Feature({"Downloads"})
  public void testDuplicateHttpPostDownload_Overwrite() throws Exception {
    // Download a file.
    loadUrl(TestHttpServerClient.getUrl("chrome/test/data/android/download/post.html"));
    waitForFocus();
    View currentView = getActivity().getActivityTab().getView();
    singleClickView(currentView);
    assertTrue(
        "Failed to finish downloading file for the first time.", waitForChromeDownloadToFinish());

    // Download a file with the same name.
    loadUrl(TestHttpServerClient.getUrl("chrome/test/data/android/download/post.html"));
    waitForFocus();
    currentView = getActivity().getActivityTab().getView();
    singleClickView(currentView);
    assertPollForInfoBarSize(1);
    assertTrue(
        "OVERWRITE button wasn't found", InfoBarUtil.clickPrimaryButton(getInfoBars().get(0)));
    assertTrue(
        "Failed to finish downloading file for the second time.", waitForChromeDownloadToFinish());

    assertTrue("Missing first download", hasDownload("superbo.txt", SUPERBO_CONTENTS));
    assertFalse(
        "Should not have second download", hasDownload("superbo (1).txt", SUPERBO_CONTENTS));
  }
Beispiel #2
0
  /** Test back and forward buttons. */
  @Restriction(RESTRICTION_TYPE_TABLET)
  @MediumTest
  @Feature({"Navigation"})
  public void testNavigateBackAndForwardButtons() throws InterruptedException {
    final String[] urls = {
      TestHttpServerClient.getUrl("chrome/test/data/android/navigate/one.html"),
      TestHttpServerClient.getUrl("chrome/test/data/android/navigate/two.html"),
      TestHttpServerClient.getUrl("chrome/test/data/android/navigate/three.html")
    };

    for (String url : urls) {
      navigateAndObserve(url, url);
    }

    final int repeats = 3;
    for (int i = 0; i < repeats; i++) {
      singleClickView(getActivity().findViewById(R.id.back_button));
      UiUtils.settleDownUI(getInstrumentation());
      assertEquals(
          String.format(
              Locale.US,
              "URL mismatch after pressing back button for the 1st time in repetition %d.",
              i),
          urls[1],
          getActivity().getActivityTab().getUrl());

      singleClickView(getActivity().findViewById(R.id.back_button));
      UiUtils.settleDownUI(getInstrumentation());
      assertEquals(
          String.format(
              Locale.US,
              "URL mismatch after pressing back button for the 2nd time in repetition %d.",
              i),
          urls[0],
          getActivity().getActivityTab().getUrl());

      singleClickView(getActivity().findViewById(R.id.forward_button));
      UiUtils.settleDownUI(getInstrumentation());
      assertEquals(
          String.format(
              Locale.US,
              "URL mismatch after pressing fwd button for the 1st time in repetition %d.",
              i),
          urls[1],
          getActivity().getActivityTab().getUrl());

      singleClickView(getActivity().findViewById(R.id.forward_button));
      UiUtils.settleDownUI(getInstrumentation());
      assertEquals(
          String.format(
              Locale.US,
              "URL mismatch after pressing fwd button for the 2nd time in repetition %d.",
              i),
          urls[2],
          getActivity().getActivityTab().getUrl());
    }
  }
  /**
   * Verifies that the referrer is stripped from username and password fields. Bug:
   * crbug.com/413216 @MediumTest @Feature({"Browser"})
   */
  @FlakyTest
  public void testOpenInNewTabSanitizeReferrer() throws InterruptedException, TimeoutException {
    String url =
        TestHttpServerClient.getUrl(
            "chrome/test/data/android/context_menu_test.html", "user", "pass");
    String expectedReferrer =
        TestHttpServerClient.getUrl("chrome/test/data/android/context_menu_test.html");
    assertTrue(url.contains("pass")); // Sanity check.
    triggerContextMenuLoad(url, "testLink", R.id.contextmenu_open_in_new_tab);

    assertNotNull(mOpenNewTabLoadUrlParams);
    assertEquals(expectedReferrer, mOpenNewTabLoadUrlParams.getReferrer().getUrl());
  }
Beispiel #4
0
  /**
   * Test fallback works as intended and that we can go back to the original URL even when
   * redirected via Java redirection.
   */
  @MediumTest
  @Feature({"Navigation"})
  public void testIntentFallbackRedirection() throws Exception {
    getInstrumentation().waitForIdleSync();
    assertEquals(NEW_TAB_PAGE, getActivity().getActivityTab().getUrl());

    final String redirectionUrl =
        TestHttpServerClient.getUrl("chrome/test/data/android/redirect/about.html");
    final String initialUrl =
        TestHttpServerClient.getUrl(
            "chrome/test/data/android/redirect/js_redirect.cgi?location="
                + URLEncoder.encode(
                    "intent://non_existent/#Intent;scheme=non_existent;"
                        + "S.browser_fallback_url="
                        + redirectionUrl
                        + ";end",
                    "UTF-8"));
    final String targetUrl =
        TestHttpServerClient.getUrl("chrome/test/data/android/redirect/one.html");
    typeInOmniboxAndNavigate(initialUrl);

    // Now intent fallback should be triggered assuming 'non_existent' scheme cannot be handled.
    CriteriaHelper.pollForCriteria(
        new Criteria() {
          @Override
          public boolean isSatisfied() {
            return getActivity().getActivityTab().getUrl().equals(targetUrl);
          }
        });

    // Check if Java redirections were removed from the history.
    // Note that if we try to go back in the test: NavigateToEntry() is called, but
    // DidNavigate() does not get called. But in real cases we can go back to initial page
    // without any problem.
    // TODO(changwan): figure out why we cannot go back on this test.
    int index =
        getActivity()
            .getActivityTab()
            .getWebContents()
            .getNavigationController()
            .getLastCommittedEntryIndex();
    assertEquals(1, index);
    String previousNavigationUrl =
        getActivity()
            .getActivityTab()
            .getWebContents()
            .getNavigationController()
            .getEntryAtIndex(0)
            .getUrl();
    assertEquals(NEW_TAB_PAGE, previousNavigationUrl);
  }
Beispiel #5
0
 //    @Restriction(RESTRICTION_TYPE_TABLET)
 //    @MediumTest
 //    @Feature({"Navigation"})
 //    crbug.com/516018
 @FlakyTest
 public void testNavigateMany() throws InterruptedException {
   final String[] urls = {
     TestHttpServerClient.getUrl("chrome/test/data/android/navigate/one.html"),
     TestHttpServerClient.getUrl("chrome/test/data/android/navigate/two.html"),
     TestHttpServerClient.getUrl("chrome/test/data/android/navigate/three.html")
   };
   final int repeats = 3;
   for (int i = 0; i < repeats; i++) {
     for (int j = 0; j < urls.length; j++) {
       String result = typeInOmniboxAndNavigate(urls[j]);
       assertEquals(expectedLocation(urls[j]), result);
     }
   }
 }
Beispiel #6
0
  /** Test Opening a link and verify that the desired page is loaded. */
  @MediumTest
  @Feature({"Navigation"})
  public void testOpenLink() throws InterruptedException, TimeoutException {
    String url1 = TestHttpServerClient.getUrl("chrome/test/data/android/google.html");
    String url2 = TestHttpServerClient.getUrl("chrome/test/data/android/about.html");

    navigateAndObserve(url1, url1);
    assertWaitForPageScaleFactorMatch(0.5f);

    Tab tab = getActivity().getActivityTab();

    DOMUtils.clickNode(this, tab.getContentViewCore(), "aboutLink");
    ChromeTabUtils.waitForTabPageLoaded(tab, url2);
    assertEquals("Desired Link not open", url2, getActivity().getActivityTab().getUrl());
  }
Beispiel #7
0
  /**
   * Test re-direct functionality for a web-page.
   *
   * @throws Exception
   */
  @MediumTest
  @Feature({"Navigation"})
  public void testNavigateRedirect() throws Exception {
    final String initialUrl =
        TestHttpServerClient.getUrl("chrome/test/data/android/redirect/about.html");
    final String redirectedUrl =
        TestHttpServerClient.getUrl("chrome/test/data/android/redirect/one.html");
    typeInOmniboxAndNavigate(initialUrl);

    CriteriaHelper.pollForCriteria(
        new Criteria() {
          @Override
          public boolean isSatisfied() {
            return getActivity().getActivityTab().getUrl().equals(redirectedUrl);
          }
        });
  }
Beispiel #8
0
 /** Verify Selection on the Location Bar. */
 @Smoke
 @MediumTest
 @Feature({"Navigation", "Main"})
 public void testNavigate() throws InterruptedException {
   String url = TestHttpServerClient.getUrl("chrome/test/data/android/navigate/simple.html");
   String result = typeInOmniboxAndNavigate(url);
   assertEquals(expectedLocation(url), result);
 }
  /**
   * Verifies that the referrer is not set for "Open in new incognito tab". Bug:
   * crbug.com/413216 @MediumTest @Feature({"Browser"})
   */
  @FlakyTest
  public void testOpenInIncognitoTabNoReferrer() throws InterruptedException, TimeoutException {
    String url = TestHttpServerClient.getUrl("chrome/test/data/android/context_menu_test.html");
    triggerContextMenuLoad(url, "testLink", R.id.contextmenu_open_in_incognito_tab);

    assertNotNull(mOpenNewTabLoadUrlParams);
    assertNull(mOpenNewTabLoadUrlParams.getReferrer());
  }
Beispiel #10
0
 /** Verify Selection on the Location Bar in Landscape Mode */
 @MediumTest
 @Feature({"Navigation"})
 public void testNavigateLandscape() throws InterruptedException {
   // '0' is Landscape Mode. '1' is Portrait.
   getActivity().setRequestedOrientation(0);
   String url = TestHttpServerClient.getUrl("chrome/test/data/android/navigate/simple.html");
   String result = typeInOmniboxAndNavigate(url);
   assertEquals(expectedLocation(url), result);
 }
Beispiel #11
0
  /** Bug http://crbug/253711 @MediumTest @Feature({"Downloads"}) */
  @FlakyTest
  public void testHttpPostDownload() throws Exception {
    loadUrl(TestHttpServerClient.getUrl("chrome/test/data/android/download/post.html"));
    waitForFocus();
    View currentView = getActivity().getActivityTab().getView();

    singleClickView(currentView);
    assertTrue(waitForChromeDownloadToFinish());
    assertTrue(hasDownload("superbo.txt", SUPERBO_CONTENTS));
  }
Beispiel #12
0
  /** Bug http://crbug.com/253711 @MediumTest @Feature({"Downloads"}) */
  @FlakyTest
  public void testHttpGetDownload() throws Exception {
    loadUrl(TestHttpServerClient.getUrl("chrome/test/data/android/download/get.html"));
    waitForFocus();
    View currentView = getActivity().getActivityTab().getView();

    singleClickView(currentView);
    assertTrue(waitForGetDownloadToFinish());
    checkLastDownload("test.gzip");
  }
Beispiel #13
0
  /*
  @MediumTest
  @Feature({"Downloads"})
  Bug http://crbug/253711
  */
  @FlakyTest
  public void testUrlEscaping() throws Exception {
    loadUrl(TestHttpServerClient.getUrl("chrome/test/data/android/download/urlescaping.html"));
    waitForFocus();
    View currentView = getActivity().getActivityTab().getView();

    singleClickView(currentView);
    assertTrue(waitForGetDownloadToFinish());
    checkLastDownload("[large]wallpaper.dm");
  }
Beispiel #14
0
 /** Bug http://crbug/286315 @MediumTest @Feature({"Downloads"}) */
 @FlakyTest
 public void testDangerousDownload() throws Exception {
   loadUrl(TestHttpServerClient.getUrl("chrome/test/data/android/download/dangerous.html"));
   waitForFocus();
   View currentView = getActivity().getActivityTab().getView();
   singleClickView(currentView);
   assertPollForInfoBarSize(1);
   assertTrue("OK button wasn't found", InfoBarUtil.clickPrimaryButton(getInfoBars().get(0)));
   assertTrue(waitForGetDownloadToFinish());
   checkLastDownload("test.apk");
 }
Beispiel #15
0
  /*
  Bug http://crbug/415711
  */
  @MediumTest
  @Feature({"Downloads"})
  public void testDuplicateHttpPostDownload_AllowMultipleInfoBars() throws Exception {
    assertFalse(hasDownload("superbo.txt", SUPERBO_CONTENTS));
    // Download a file.
    loadUrl(TestHttpServerClient.getUrl("chrome/test/data/android/download/post.html"));
    waitForFocus();
    View currentView = getActivity().getActivityTab().getView();
    singleClickView(currentView);
    assertTrue(
        "Failed to finish downloading file for the first time.", waitForChromeDownloadToFinish());

    // Download the file for the second time.
    loadUrl(TestHttpServerClient.getUrl("chrome/test/data/android/download/post.html"));
    waitForFocus();
    currentView = getActivity().getActivityTab().getView();
    singleClickView(currentView);
    assertPollForInfoBarSize(1);

    // Download the file for the third time.
    loadUrl(TestHttpServerClient.getUrl("chrome/test/data/android/download/post.html"));
    waitForFocus();
    currentView = getActivity().getActivityTab().getView();
    singleClickView(currentView);
    assertPollForInfoBarSize(2);

    // Now create two new files by clicking on the infobars.
    assertTrue(
        "CREATE NEW button wasn't found", InfoBarUtil.clickSecondaryButton(getInfoBars().get(0)));
    assertTrue("Failed to finish downloading the second file.", waitForChromeDownloadToFinish());
    assertPollForInfoBarSize(1);
    assertTrue(
        "CREATE NEW button wasn't found", InfoBarUtil.clickSecondaryButton(getInfoBars().get(0)));
    assertTrue("Failed to finish downloading the third file.", waitForChromeDownloadToFinish());

    assertTrue("Missing first download", hasDownload("superbo.txt", SUPERBO_CONTENTS));
    assertTrue("Missing second download", hasDownload("superbo (1).txt", SUPERBO_CONTENTS));
    assertTrue("Missing third download", hasDownload("superbo (2).txt", SUPERBO_CONTENTS));
  }
Beispiel #16
0
  /** Verify New Tab Open and Navigate. */
  @MediumTest
  @Feature({"Navigation"})
  public void testOpenAndNavigate() throws InterruptedException {
    final String url = TestHttpServerClient.getUrl("chrome/test/data/android/navigate/simple.html");
    navigateAndObserve(url, url);

    final int tabCount = getActivity().getCurrentTabModel().getCount();
    ChromeTabUtils.newTabFromMenu(getInstrumentation(), getActivity());
    UiUtils.settleDownUI(getInstrumentation());

    assertEquals(
        "Wrong number of tabs", tabCount + 1, getActivity().getCurrentTabModel().getCount());
    String result = typeInOmniboxAndNavigate(url);
    assertEquals(expectedLocation(url), result);
  }
Beispiel #17
0
  /** Bug http://crbug/253711 Bug http://crbug/415711 @MediumTest @Feature({"Downloads"}) */
  @FlakyTest
  public void testDuplicateHttpPostDownload_CreateNew() throws Exception {
    // Download a file.
    loadUrl(TestHttpServerClient.getUrl("chrome/test/data/android/download/post.html"));
    waitForFocus();
    View currentView = getActivity().getActivityTab().getView();
    singleClickView(currentView);
    assertTrue(
        "Failed to finish downloading file for the first time.", waitForChromeDownloadToFinish());

    // Download a file with the same name.
    loadUrl(TestHttpServerClient.getUrl("chrome/test/data/android/download/post.html"));
    waitForFocus();
    currentView = getActivity().getActivityTab().getView();
    singleClickView(currentView);
    assertPollForInfoBarSize(1);
    assertTrue(
        "CREATE NEW button wasn't found", InfoBarUtil.clickSecondaryButton(getInfoBars().get(0)));
    assertTrue(
        "Failed to finish downloading file for the second time.", waitForChromeDownloadToFinish());

    assertTrue("Missing first download", hasDownload("superbo.txt", SUPERBO_CONTENTS));
    assertTrue("Missing second download", hasDownload("superbo (1).txt", SUPERBO_CONTENTS));
  }
Beispiel #18
0
  /**
   * Test Opening a link and verify that TabObserver#onPageLoadStarted gives the old and new URL.
   */
  @MediumTest
  @Feature({"Navigation"})
  public void testTabObserverOnPageLoadStarted() throws InterruptedException, TimeoutException {
    final String url1 = TestHttpServerClient.getUrl("chrome/test/data/android/google.html");
    final String url2 = TestHttpServerClient.getUrl("chrome/test/data/android/about.html");

    navigateAndObserve(url1, url1);
    assertWaitForPageScaleFactorMatch(0.5f);

    TabObserver onPageLoadStartedObserver =
        new EmptyTabObserver() {
          @Override
          public void onPageLoadStarted(Tab tab, String newUrl) {
            tab.removeObserver(this);
            assertEquals(url1, tab.getUrl());
            assertEquals(url2, newUrl);
          }
        };
    Tab tab = getActivity().getActivityTab();
    tab.addObserver(onPageLoadStartedObserver);
    DOMUtils.clickNode(this, tab.getContentViewCore(), "aboutLink");
    ChromeTabUtils.waitForTabPageLoaded(tab, url2);
    assertEquals("Desired Link not open", url2, getActivity().getActivityTab().getUrl());
  }
Beispiel #19
0
  /** Bug 5431234 @MediumTest @Feature({"Downloads"}) */
  @FlakyTest
  public void testCloseEmptyDownloadTab() throws Exception {
    loadUrl(TestHttpServerClient.getUrl("chrome/test/data/android/download/get.html"));
    waitForFocus();
    int initialTabCount = getActivity().getCurrentTabModel().getCount();
    View currentView = getActivity().getActivityTab().getView();
    TouchCommon.longPressView(currentView);

    getInstrumentation()
        .invokeContextMenuAction(getActivity(), R.id.contextmenu_open_in_new_tab, 0);
    assertTrue(waitForGetDownloadToFinish());
    checkLastDownload("test.gzip");

    assertEquals(
        "Did not close new blank tab for download",
        initialTabCount,
        getActivity().getCurrentTabModel().getCount());
  }
Beispiel #20
0
  /*
  Bug http://crbug/481758
  */
  @CommandLineFlags.Add(ChromeSwitches.DISABLE_DOCUMENT_MODE)
  @MediumTest
  @Feature({"Downloads"})
  public void testDuplicateHttpPostDownload_OpenNewTabAndReplace() throws Exception {
    final String url = TestHttpServerClient.getUrl("chrome/test/data/android/download/get.html");

    // Create the file in advance so that duplicate download infobar can show up.
    File dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
    assertTrue(dir.isDirectory());
    final File file = new File(dir, "test.gzip");
    if (!file.exists()) {
      assertTrue(file.createNewFile());
    }

    // Open in a new tab again.
    loadUrl(url);
    waitForFocus();

    View currentView = getActivity().getActivityTab().getView();
    TouchCommon.longPressView(currentView);
    getInstrumentation()
        .invokeContextMenuAction(getActivity(), R.id.contextmenu_open_in_new_tab, 0);
    waitForNewTabToStabilize(2);

    goToLastTab();
    assertPollForInfoBarSize(1);

    // Now create two new files by clicking on the infobars.
    assertTrue(
        "OVERWRITE button wasn't found", InfoBarUtil.clickPrimaryButton(getInfoBars().get(0)));

    // Try to wait for download to finish. This will fail if there is no external Internet
    // connection. Android's DownloadManager will abort download request when there is
    // no Internet connection, even though we are connecting to a local host.
    waitForGetDownloadToFinish();
  }
/** Unit tests for {@link OfflinePageBridge}. */
public class OfflinePageBridgeTest extends ChromeActivityTestCaseBase<ChromeActivity> {
  private static final String TEST_PAGE =
      TestHttpServerClient.getUrl("chrome/test/data/android/about.html");
  private static final int TIMEOUT_MS = 5000;
  private static final BookmarkId BOOKMARK_ID = new BookmarkId(1234, BookmarkType.NORMAL);

  private OfflinePageBridge mOfflinePageBridge;

  public OfflinePageBridgeTest() {
    super(ChromeActivity.class);
  }

  @Override
  protected void setUp() throws Exception {
    super.setUp();
    final Semaphore semaphore = new Semaphore(0);
    ThreadUtils.runOnUiThreadBlocking(
        new Runnable() {
          @Override
          public void run() {
            Profile profile = Profile.getLastUsedProfile();
            mOfflinePageBridge = new OfflinePageBridge(profile);
            if (mOfflinePageBridge.isOfflinePageModelLoaded()) {
              semaphore.release();
            } else {
              mOfflinePageBridge.addObserver(
                  new OfflinePageModelObserver() {
                    @Override
                    public void offlinePageModelLoaded() {
                      semaphore.release();
                      mOfflinePageBridge.removeObserver(this);
                    }
                  });
            }
          }
        });
    assertTrue(semaphore.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS));
  }

  @Override
  public void startMainActivity() throws InterruptedException {
    startMainActivityOnBlankPage();
  }

  @MediumTest
  public void testLoadOfflinePagesWhenEmpty() throws Exception {
    List<OfflinePageItem> offlinePages = getAllPages();
    assertEquals("Offline pages count incorrect.", 0, offlinePages.size());
  }

  @MediumTest
  public void testAddOfflinePageAndLoad() throws Exception {
    loadUrl(TEST_PAGE);
    savePage(SavePageResult.SUCCESS, TEST_PAGE);
    List<OfflinePageItem> allPages = getAllPages();
    OfflinePageItem offlinePage = allPages.get(0);
    assertEquals("Offline pages count incorrect.", 1, allPages.size());
    assertEquals("Offline page item url incorrect.", TEST_PAGE, offlinePage.getUrl());
    assertEquals(
        "Offline page item bookmark ID incorrect.", BOOKMARK_ID, offlinePage.getBookmarkId());
    assertTrue(
        "Offline page item offline file url doesn't start properly.",
        offlinePage.getOfflineUrl().startsWith("file:///"));
    assertTrue(
        "Offline page item offline file doesn't have the right name.",
        offlinePage.getOfflineUrl().endsWith(".mhtml"));
    assertTrue(
        "Offline page item offline file doesn't have the right name.",
        offlinePage.getOfflineUrl().contains("About"));
    // BUG(518758): Depending on the bot the result will be either 626 or 627.
    long size = offlinePage.getFileSize();
    assertTrue("Offline page item size is incorrect: " + size, size == 626 || size == 627);
  }

  @MediumTest
  public void testMarkPageAccessed() throws Exception {
    loadUrl(TEST_PAGE);
    savePage(SavePageResult.SUCCESS, TEST_PAGE);
    OfflinePageItem offlinePage = mOfflinePageBridge.getPageByBookmarkId(BOOKMARK_ID);
    assertNotNull("Offline page should be available, but it is not.", offlinePage);
    assertEquals("Offline page access count should be 0.", 0, offlinePage.getAccessCount());

    markPageAccessed(BOOKMARK_ID, 1);
  }

  @MediumTest
  public void testGetPageByBookmarkId() throws Exception {
    loadUrl(TEST_PAGE);
    savePage(SavePageResult.SUCCESS, TEST_PAGE);
    OfflinePageItem offlinePage = mOfflinePageBridge.getPageByBookmarkId(BOOKMARK_ID);
    assertEquals("Offline page item url incorrect.", TEST_PAGE, offlinePage.getUrl());
    assertEquals(
        "Offline page item bookmark ID incorrect.", BOOKMARK_ID, offlinePage.getBookmarkId());
    assertTrue(
        "Offline page item offline file url doesn't start properly.",
        offlinePage.getOfflineUrl().startsWith("file:///"));
    assertTrue(
        "Offline page item offline file doesn't have the right name.",
        offlinePage.getOfflineUrl().endsWith(".mhtml"));
    assertTrue(
        "Offline page item offline file doesn't have the right name.",
        offlinePage.getOfflineUrl().contains("About"));

    assertNull(
        "Offline page is not supposed to exist",
        mOfflinePageBridge.getPageByBookmarkId(new BookmarkId(-42, BookmarkType.NORMAL)));
  }

  @MediumTest
  public void testDeleteOfflinePage() throws Exception {
    deletePage(BOOKMARK_ID, DeletePageResult.NOT_FOUND);
    loadUrl(TEST_PAGE);
    savePage(SavePageResult.SUCCESS, TEST_PAGE);
    assertNotNull(
        "Offline page should be available, but it is not.",
        mOfflinePageBridge.getPageByBookmarkId(BOOKMARK_ID));
    deletePage(BOOKMARK_ID, DeletePageResult.SUCCESS);
    assertNull(
        "Offline page should be gone, but it is available.",
        mOfflinePageBridge.getPageByBookmarkId(BOOKMARK_ID));
  }

  private void savePage(final int expectedResult, final String expectedUrl)
      throws InterruptedException {
    final Semaphore semaphore = new Semaphore(0);
    ThreadUtils.runOnUiThreadBlocking(
        new Runnable() {
          @Override
          public void run() {
            assertNotNull("Tab is null", getActivity().getActivityTab());
            assertEquals(
                "URL does not match requested.",
                TEST_PAGE,
                getActivity().getActivityTab().getUrl());
            assertNotNull("WebContents is null", getActivity().getActivityTab().getWebContents());

            mOfflinePageBridge.savePage(
                getActivity().getActivityTab().getWebContents(),
                BOOKMARK_ID,
                getActivity().getWindowAndroid(),
                new SavePageCallback() {
                  @Override
                  public void onSavePageDone(int savePageResult, String url) {
                    assertEquals("Requested and returned URLs differ.", expectedUrl, url);
                    assertEquals("Save result incorrect.", expectedResult, savePageResult);
                    semaphore.release();
                  }
                });
          }
        });
    assertTrue(semaphore.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS));
  }

  private void markPageAccessed(final BookmarkId bookmarkId, final int expectedAccessCount)
      throws InterruptedException {
    ThreadUtils.runOnUiThreadBlocking(
        new Runnable() {
          @Override
          public void run() {
            mOfflinePageBridge.markPageAccessed(bookmarkId);
          }
        });
    assertTrue(
        CriteriaHelper.pollForUIThreadCriteria(
            new Criteria() {
              @Override
              public boolean isSatisfied() {
                OfflinePageItem offlinePage = mOfflinePageBridge.getPageByBookmarkId(bookmarkId);
                return offlinePage.getAccessCount() == expectedAccessCount;
              }
            }));
  }

  private void deletePage(BookmarkId bookmarkId, final int expectedResult)
      throws InterruptedException {
    final Semaphore semaphore = new Semaphore(0);
    ThreadUtils.runOnUiThreadBlocking(
        new Runnable() {
          @Override
          public void run() {
            mOfflinePageBridge.deletePage(
                BOOKMARK_ID,
                getActivity().getWindowAndroid(),
                new DeletePageCallback() {
                  @Override
                  public void onDeletePageDone(int deletePageResult) {
                    assertEquals("Delete result incorrect.", expectedResult, deletePageResult);
                    semaphore.release();
                  }
                });
          }
        });
    assertTrue(semaphore.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS));
  }

  private List<OfflinePageItem> getAllPages() throws InterruptedException {
    final Semaphore semaphore = new Semaphore(0);
    final List<OfflinePageItem> result = new ArrayList<OfflinePageItem>();
    ThreadUtils.runOnUiThreadBlocking(
        new Runnable() {
          @Override
          public void run() {
            result.clear();
            for (OfflinePageItem item : mOfflinePageBridge.getAllPages()) {
              result.add(item);
            }

            semaphore.release();
          }
        });
    assertTrue(semaphore.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS));
    return result;
  }
}
  /**
   * Verifies that a renderer that crashes in foreground has the correct visibility when recreated.
   */
  @LargeTest
  @Feature({"ProcessManagement"})
  public void testCrashInForeground() throws InterruptedException {
    // Create a tab in foreground and wait until it is loaded.
    final Tab tab =
        ThreadUtils.runOnUiThreadBlockingNoException(
            new Callable<Tab>() {
              @Override
              public Tab call() throws Exception {
                TabCreator tabCreator = getActivity().getCurrentTabCreator();
                return tabCreator.createNewTab(
                    new LoadUrlParams(TestHttpServerClient.getUrl(FILE_PATH)),
                    TabLaunchType.FROM_KEYBOARD,
                    null);
              }
            });
    ChromeTabUtils.waitForTabPageLoaded(tab, TestHttpServerClient.getUrl(FILE_PATH));
    getInstrumentation().waitForIdleSync();

    // Kill the renderer and wait for the crash to be noted by the browser process.
    assertTrue(
        ChildProcessLauncher.crashProcessForTesting(
            tab.getContentViewCore().getCurrentRenderProcessId()));

    assertTrue(
        "Renderer crash wasn't noticed by the browser.",
        CriteriaHelper.pollForCriteria(
            new Criteria() {
              @Override
              public boolean isSatisfied() {
                return tab.getContentViewCore().getCurrentRenderProcessId() == 0;
              }
            }));

    // Reload the tab, respawning the renderer.
    getInstrumentation()
        .runOnMainSync(
            new Runnable() {
              @Override
              public void run() {
                tab.reload();
              }
            });

    // Wait until the process is spawned and its visibility is determined.
    assertTrue(
        "Process for the crashed tab was not respawned.",
        CriteriaHelper.pollForCriteria(
            new Criteria() {
              @Override
              public boolean isSatisfied() {
                return tab.getContentViewCore().getCurrentRenderProcessId() != 0;
              }
            }));

    assertTrue(
        "isInForeground() was not called for the process.",
        CriteriaHelper.pollForCriteria(
            new Criteria() {
              @Override
              public boolean isSatisfied() {
                return mBindingManager.setInForegroundWasCalled(
                    tab.getContentViewCore().getCurrentRenderProcessId());
              }
            }));

    getInstrumentation()
        .runOnMainSync(
            new Runnable() {
              @Override
              public void run() {
                // Verify the visibility of the renderer.
                assertTrue(
                    mBindingManager.isInForeground(
                        tab.getContentViewCore().getCurrentRenderProcessId()));
              }
            });
  }
/** Tests the app banners. */
@CommandLineFlags.Add(ChromeSwitches.ENABLE_APP_INSTALL_ALERTS)
public class AppBannerManagerTest extends ChromeTabbedActivityTestBase {
  private static final String NATIVE_APP_URL =
      TestHttpServerClient.getUrl("chrome/test/data/banners/play_app_test_page.html");

  private static final String NATIVE_ICON_URL =
      TestHttpServerClient.getUrl("chrome/test/data/banners/launcher-icon-4x.png");

  private static final String NATIVE_APP_TITLE = "Mock app title";

  private static final String NATIVE_APP_PACKAGE = "123456";

  private static final String NATIVE_APP_INSTALL_TEXT = "Install this";

  private static final String NATIVE_APP_REFERRER = "chrome_inline";

  private static final String NATIVE_APP_URL_WITH_MANIFEST_URL =
      TestHttpServerClient.getUrl("chrome/test/data/banners/play_app_url_test_page.html");

  private static final String WEB_APP_URL =
      TestHttpServerClient.getUrl("chrome/test/data/banners/manifest_test_page.html");

  private static final String WEB_APP_TITLE = "Manifest test app";

  private static final String INSTALL_ACTION = "INSTALL_ACTION";

  private static class MockAppDetailsDelegate extends AppDetailsDelegate {
    private Observer mObserver;
    private AppData mAppData;
    private int mNumRetrieved;
    private Intent mInstallIntent;
    private String mReferrer;

    @Override
    protected void getAppDetailsAsynchronously(
        Observer observer, String url, String packageName, String referrer, int iconSize) {
      mNumRetrieved += 1;
      mObserver = observer;
      mReferrer = referrer;
      mInstallIntent = new Intent(INSTALL_ACTION);

      mAppData = new AppData(url, packageName);
      mAppData.setPackageInfo(
          NATIVE_APP_TITLE, NATIVE_ICON_URL, 4.5f, NATIVE_APP_INSTALL_TEXT, null, mInstallIntent);
      ThreadUtils.runOnUiThread(
          new Runnable() {
            @Override
            public void run() {
              mObserver.onAppDetailsRetrieved(mAppData);
            }
          });
    }

    @Override
    public void destroy() {}
  }

  private static class TestPackageManager extends MockPackageManager {
    public boolean isInstalled = false;

    @Override
    public List<PackageInfo> getInstalledPackages(int flags) {
      List<PackageInfo> packages = new ArrayList<PackageInfo>();

      if (isInstalled) {
        PackageInfo info = new PackageInfo();
        info.packageName = NATIVE_APP_PACKAGE;
        packages.add(info);
      }

      return packages;
    }
  }

  private static class InfobarListener implements InfoBarContainer.InfoBarAnimationListener {
    private boolean mDoneAnimating;

    @Override
    public void notifyAnimationFinished(int animationType) {
      if (animationType == AnimationHelper.ANIMATION_TYPE_SHOW) mDoneAnimating = true;
    }
  }

  private MockAppDetailsDelegate mDetailsDelegate;
  private TestPackageManager mPackageManager;

  @Override
  public void startMainActivity() throws InterruptedException {
    startMainActivityOnBlankPage();
  }

  @Override
  protected void setUp() throws Exception {
    mPackageManager = new TestPackageManager();
    AppBannerManager.setIsEnabledForTesting(true);
    AppBannerInfoBarDelegateAndroid.setPackageManagerForTesting(mPackageManager);

    super.setUp();

    // Must be set after native has loaded.
    mDetailsDelegate = new MockAppDetailsDelegate();
    ThreadUtils.runOnUiThreadBlocking(
        new Runnable() {
          @Override
          public void run() {
            AppBannerManager.setAppDetailsDelegate(mDetailsDelegate);
          }
        });

    AppBannerManager.disableSecureSchemeCheckForTesting();

    // Navigations in this test are all of type ui::PAGE_TRANSITION_LINK, i.e. indirect.
    // Force indirect navigations to be worth the same as direct for testing.
    AppBannerManager.forceEngagementWeightsForTesting(1, 1);
  }

  private boolean waitUntilNoInfoBarsExist() throws Exception {
    return CriteriaHelper.pollForUIThreadCriteria(
        new Criteria() {
          @Override
          public boolean isSatisfied() {
            InfoBarContainer container = getActivity().getActivityTab().getInfoBarContainer();
            return container.getInfoBars().size() == 0;
          }
        });
  }

  private boolean waitUntilAppDetailsRetrieved(final int numExpected) throws Exception {
    return CriteriaHelper.pollForUIThreadCriteria(
        new Criteria() {
          @Override
          public boolean isSatisfied() {
            AppBannerManager manager =
                getActivity().getActivityTab().getAppBannerManagerForTesting();
            return mDetailsDelegate.mNumRetrieved == numExpected
                && !manager.isFetcherActiveForTesting();
          }
        });
  }

  private boolean waitUntilAppBannerInfoBarAppears(final String title) throws Exception {
    return CriteriaHelper.pollForUIThreadCriteria(
        new Criteria() {
          @Override
          public boolean isSatisfied() {
            InfoBarContainer container = getActivity().getActivityTab().getInfoBarContainer();
            ArrayList<InfoBar> infobars = container.getInfoBars();
            if (infobars.size() != 1) return false;
            if (!(infobars.get(0) instanceof AppBannerInfoBarAndroid)) return false;

            TextView textView =
                (TextView) infobars.get(0).getContentWrapper().findViewById(R.id.app_name);
            if (textView == null) return false;
            return TextUtils.equals(textView.getText(), title);
          }
        });
  }

  private void runFullNativeInstallPathway(String url, String expectedReferrer) throws Exception {
    // Visit a site that requests a banner.
    assertTrue(
        CriteriaHelper.pollForUIThreadCriteria(
            new TabLoadObserver(getActivity().getActivityTab(), url)));
    assertTrue(waitUntilAppDetailsRetrieved(1));
    assertEquals(mDetailsDelegate.mReferrer, expectedReferrer);
    assertTrue(waitUntilNoInfoBarsExist());

    // Indicate a day has passed, then revisit the page to get the banner to appear.
    InfoBarContainer container = getActivity().getActivityTab().getInfoBarContainer();
    final InfobarListener listener = new InfobarListener();
    container.setAnimationListener(listener);
    AppBannerManager.setTimeDeltaForTesting(1);
    assertTrue(
        CriteriaHelper.pollForUIThreadCriteria(
            new TabLoadObserver(getActivity().getActivityTab(), url)));
    assertTrue(waitUntilAppDetailsRetrieved(2));
    assertTrue(waitUntilAppBannerInfoBarAppears(NATIVE_APP_TITLE));
    assertTrue(
        CriteriaHelper.pollForUIThreadCriteria(
            new Criteria() {
              @Override
              public boolean isSatisfied() {
                return listener.mDoneAnimating;
              }
            }));

    // Check that the button asks if the user wants to install the app.
    InfoBar infobar = container.getInfoBars().get(0);
    final Button button = (Button) infobar.getContentWrapper().findViewById(R.id.button_primary);
    assertEquals(NATIVE_APP_INSTALL_TEXT, button.getText());

    // Click the button to trigger the install.
    final ActivityMonitor activityMonitor =
        new ActivityMonitor(
            new IntentFilter(INSTALL_ACTION), new ActivityResult(Activity.RESULT_OK, null), true);
    getInstrumentation().addMonitor(activityMonitor);
    TouchCommon.singleClickView(button);

    // Wait for the infobar to register that the app is installing.
    final String installingText =
        getInstrumentation().getTargetContext().getString(R.string.app_banner_installing);
    assertTrue(
        CriteriaHelper.pollForCriteria(
            new Criteria() {
              @Override
              public boolean isSatisfied() {
                return getInstrumentation().checkMonitorHit(activityMonitor, 1)
                    && TextUtils.equals(button.getText(), installingText);
              }
            }));

    // Say that the package is installed.  Infobar should say that the app is ready to open.
    mPackageManager.isInstalled = true;
    final String openText =
        getInstrumentation().getTargetContext().getString(R.string.app_banner_open);
    assertTrue(
        CriteriaHelper.pollForCriteria(
            new Criteria() {
              @Override
              public boolean isSatisfied() {
                return TextUtils.equals(button.getText(), openText);
              }
            }));
  }

  @SmallTest
  @Feature({"AppBanners"})
  public void testFullNativeInstallPathwayFromId() throws Exception {
    runFullNativeInstallPathway(NATIVE_APP_URL, "");
  }

  @SmallTest
  @Feature({"AppBanners"})
  public void testFullNativeInstallPathwayFromUrl() throws Exception {
    runFullNativeInstallPathway(NATIVE_APP_URL_WITH_MANIFEST_URL, NATIVE_APP_REFERRER);
  }

  @MediumTest
  @Feature({"AppBanners"})
  public void testBannerAppearsThenDoesNotAppearAgainForMonths() throws Exception {
    // Visit a site that requests a banner.
    assertTrue(
        CriteriaHelper.pollForUIThreadCriteria(
            new TabLoadObserver(getActivity().getActivityTab(), NATIVE_APP_URL)));
    assertTrue(waitUntilAppDetailsRetrieved(1));
    assertTrue(waitUntilNoInfoBarsExist());

    // Indicate a day has passed, then revisit the page.
    AppBannerManager.setTimeDeltaForTesting(1);
    assertTrue(
        CriteriaHelper.pollForUIThreadCriteria(
            new TabLoadObserver(getActivity().getActivityTab(), NATIVE_APP_URL)));
    assertTrue(waitUntilAppDetailsRetrieved(2));
    assertTrue(waitUntilAppBannerInfoBarAppears(NATIVE_APP_TITLE));

    // Revisit the page to make the banner go away, but don't explicitly dismiss it.
    // This hides the banner for a few months.
    assertTrue(
        CriteriaHelper.pollForUIThreadCriteria(
            new TabLoadObserver(getActivity().getActivityTab(), NATIVE_APP_URL)));
    assertTrue(waitUntilAppDetailsRetrieved(3));
    assertTrue(waitUntilNoInfoBarsExist());

    // Wait a month until revisiting the page.
    AppBannerManager.setTimeDeltaForTesting(31);
    assertTrue(
        CriteriaHelper.pollForUIThreadCriteria(
            new TabLoadObserver(getActivity().getActivityTab(), NATIVE_APP_URL)));
    assertTrue(waitUntilAppDetailsRetrieved(4));
    assertTrue(waitUntilNoInfoBarsExist());

    AppBannerManager.setTimeDeltaForTesting(32);
    assertTrue(
        CriteriaHelper.pollForUIThreadCriteria(
            new TabLoadObserver(getActivity().getActivityTab(), NATIVE_APP_URL)));
    assertTrue(waitUntilAppDetailsRetrieved(5));
    assertTrue(waitUntilNoInfoBarsExist());

    // Wait two months until revisiting the page, which should pop up the banner.
    AppBannerManager.setTimeDeltaForTesting(61);
    assertTrue(
        CriteriaHelper.pollForUIThreadCriteria(
            new TabLoadObserver(getActivity().getActivityTab(), NATIVE_APP_URL)));
    assertTrue(waitUntilAppDetailsRetrieved(6));
    assertTrue(waitUntilNoInfoBarsExist());

    AppBannerManager.setTimeDeltaForTesting(62);
    assertTrue(
        CriteriaHelper.pollForUIThreadCriteria(
            new TabLoadObserver(getActivity().getActivityTab(), NATIVE_APP_URL)));
    assertTrue(waitUntilAppDetailsRetrieved(7));
    assertTrue(waitUntilAppBannerInfoBarAppears(NATIVE_APP_TITLE));
  }

  @MediumTest
  @Feature({"AppBanners"})
  public void testBlockedBannerDoesNotAppearAgainForMonths() throws Exception {
    // Visit a site that requests a banner.
    assertTrue(
        CriteriaHelper.pollForUIThreadCriteria(
            new TabLoadObserver(getActivity().getActivityTab(), NATIVE_APP_URL)));
    assertTrue(waitUntilAppDetailsRetrieved(1));
    assertTrue(waitUntilNoInfoBarsExist());

    // Indicate a day has passed, then revisit the page.
    InfoBarContainer container = getActivity().getActivityTab().getInfoBarContainer();
    final InfobarListener listener = new InfobarListener();
    container.setAnimationListener(listener);
    AppBannerManager.setTimeDeltaForTesting(1);
    assertTrue(
        CriteriaHelper.pollForUIThreadCriteria(
            new TabLoadObserver(getActivity().getActivityTab(), NATIVE_APP_URL)));
    assertTrue(waitUntilAppDetailsRetrieved(2));
    assertTrue(waitUntilAppBannerInfoBarAppears(NATIVE_APP_TITLE));

    // Explicitly dismiss the banner.
    assertTrue(
        CriteriaHelper.pollForUIThreadCriteria(
            new Criteria() {
              @Override
              public boolean isSatisfied() {
                return listener.mDoneAnimating;
              }
            }));
    ArrayList<InfoBar> infobars = container.getInfoBars();
    View close = infobars.get(0).getContentWrapper().findViewById(R.id.infobar_close_button);
    TouchCommon.singleClickView(close);
    assertTrue(waitUntilNoInfoBarsExist());

    // Waiting two months shouldn't be long enough.
    AppBannerManager.setTimeDeltaForTesting(61);
    assertTrue(
        CriteriaHelper.pollForUIThreadCriteria(
            new TabLoadObserver(getActivity().getActivityTab(), NATIVE_APP_URL)));
    assertTrue(waitUntilAppDetailsRetrieved(3));
    assertTrue(waitUntilNoInfoBarsExist());

    AppBannerManager.setTimeDeltaForTesting(62);
    assertTrue(
        CriteriaHelper.pollForUIThreadCriteria(
            new TabLoadObserver(getActivity().getActivityTab(), NATIVE_APP_URL)));
    assertTrue(waitUntilAppDetailsRetrieved(4));
    assertTrue(waitUntilNoInfoBarsExist());

    // Waiting three months should allow banners to reappear.
    AppBannerManager.setTimeDeltaForTesting(91);
    assertTrue(
        CriteriaHelper.pollForUIThreadCriteria(
            new TabLoadObserver(getActivity().getActivityTab(), NATIVE_APP_URL)));
    assertTrue(waitUntilAppDetailsRetrieved(5));
    assertTrue(waitUntilNoInfoBarsExist());

    AppBannerManager.setTimeDeltaForTesting(92);
    assertTrue(
        CriteriaHelper.pollForUIThreadCriteria(
            new TabLoadObserver(getActivity().getActivityTab(), NATIVE_APP_URL)));
    assertTrue(waitUntilAppDetailsRetrieved(6));
    assertTrue(waitUntilAppBannerInfoBarAppears(NATIVE_APP_TITLE));
  }

  @MediumTest
  @Feature({"AppBanners"})
  public void testBitmapFetchersCanOverlapWithoutCrashing() throws Exception {
    // Visit a site that requests a banner rapidly and repeatedly.
    for (int i = 1; i <= 10; i++) {
      assertTrue(
          CriteriaHelper.pollForUIThreadCriteria(
              new TabLoadObserver(getActivity().getActivityTab(), NATIVE_APP_URL)));

      final Integer iteration = Integer.valueOf(i);
      assertTrue(
          CriteriaHelper.pollForUIThreadCriteria(
              new Criteria() {
                @Override
                public boolean isSatisfied() {
                  return mDetailsDelegate.mNumRetrieved == iteration;
                }
              }));
    }
  }

  @SmallTest
  @Feature({"AppBanners"})
  public void testWebAppBannerAppears() throws Exception {
    // Create a Tab that doesn't have the AppBannerManager enabled.  This prevents race
    // conditions between service worker activation and AppBannerManager getting triggered.
    // This race condition is a known problem, which is why the specs include wiggle room for
    // how many times a site must be visited.
    AppBannerManager.setIsEnabledForTesting(false);
    loadUrlInNewTab("about:blank");

    // Visit a site that can have a banner, then wait until the service worker is activated.
    assertTrue(
        CriteriaHelper.pollForUIThreadCriteria(
            new TabLoadObserver(getActivity().getActivityTab(), WEB_APP_URL)));
    assertTrue(
        CriteriaHelper.pollForUIThreadCriteria(
            new Criteria() {
              @Override
              public boolean isSatisfied() {
                String url = getActivity().getActivityTab().getUrl();
                Uri uri = Uri.parse(url);
                return TextUtils.equals(uri.getFragment(), "sw_activated");
              }
            }));
    AppBannerManager.setIsEnabledForTesting(true);

    // Revisit the site in a new tab, which will have the AppBannerManager enabled.
    loadUrlInNewTab("about:blank");
    assertTrue(
        CriteriaHelper.pollForUIThreadCriteria(
            new TabLoadObserver(getActivity().getActivityTab(), WEB_APP_URL)));

    assertTrue(
        CriteriaHelper.pollForUIThreadCriteria(
            new Criteria() {
              @Override
              public boolean isSatisfied() {
                AppBannerManager manager =
                    getActivity().getActivityTab().getAppBannerManagerForTesting();
                return !manager.isFetcherActiveForTesting();
              }
            }));
    assertTrue(waitUntilNoInfoBarsExist());

    // Indicate a day has passed, then revisit the page to show the banner.
    AppBannerManager.setTimeDeltaForTesting(1);
    assertTrue(
        CriteriaHelper.pollForUIThreadCriteria(
            new TabLoadObserver(getActivity().getActivityTab(), WEB_APP_URL)));
    assertTrue(
        CriteriaHelper.pollForUIThreadCriteria(
            new Criteria() {
              @Override
              public boolean isSatisfied() {
                AppBannerManager manager =
                    getActivity().getActivityTab().getAppBannerManagerForTesting();
                return !manager.isFetcherActiveForTesting();
              }
            }));
    assertTrue(waitUntilAppBannerInfoBarAppears(WEB_APP_TITLE));
  }
}
  /**
   * Verifies that the .setProcessInForeground() signal is called correctly when a tab that crashed
   * in background is restored in foreground. This is a regression test for http://crbug.com/399521.
   */
  @LargeTest
  @Feature({"ProcessManagement"})
  public void testCrashInBackground() throws InterruptedException {
    // Create two tabs and wait until they are loaded, so that their renderers are around.
    final Tab[] tabs = new Tab[2];
    getInstrumentation()
        .runOnMainSync(
            new Runnable() {
              @Override
              public void run() {
                // Foreground tab.
                TabCreator tabCreator = getActivity().getCurrentTabCreator();
                tabs[0] =
                    tabCreator.createNewTab(
                        new LoadUrlParams(TestHttpServerClient.getUrl(FILE_PATH)),
                        TabLaunchType.FROM_KEYBOARD,
                        null);
                // Background tab.
                tabs[1] =
                    tabCreator.createNewTab(
                        new LoadUrlParams(TestHttpServerClient.getUrl(FILE_PATH)),
                        TabLaunchType.FROM_LONGPRESS_BACKGROUND,
                        null);
                // On Svelte devices the background tab would not be loaded automatically, so
                // trigger the load manually.
                tabs[1].show(TabSelectionType.FROM_USER);
                tabs[1].hide();
              }
            });
    ChromeTabUtils.waitForTabPageLoaded(tabs[0], TestHttpServerClient.getUrl(FILE_PATH));
    ChromeTabUtils.waitForTabPageLoaded(tabs[1], TestHttpServerClient.getUrl(FILE_PATH));

    // Wait for the new tab animations on phones to finish.
    if (!DeviceFormFactor.isTablet(getActivity()) && getActivity() instanceof ChromeActivity) {
      final ChromeActivity activity = (ChromeActivity) getActivity();
      assertTrue(
          "Did not finish animation",
          CriteriaHelper.pollForUIThreadCriteria(
              new Criteria() {
                @Override
                public boolean isSatisfied() {
                  Layout layout =
                      activity.getCompositorViewHolder().getLayoutManager().getActiveLayout();
                  return !layout.isLayoutAnimating();
                }
              }));
    }
    getInstrumentation().waitForIdleSync();

    getInstrumentation()
        .runOnMainSync(
            new Runnable() {
              @Override
              public void run() {
                // Make sure that the renderers were spawned.
                assertTrue(tabs[0].getContentViewCore().getCurrentRenderProcessId() > 0);
                assertTrue(tabs[1].getContentViewCore().getCurrentRenderProcessId() > 0);

                // Verify that the renderer of the foreground tab was signalled as visible.
                assertTrue(
                    mBindingManager.isInForeground(
                        tabs[0].getContentViewCore().getCurrentRenderProcessId()));
                // Verify that the renderer of the tab loaded in background was signalled as not
                // visible.
                assertTrue(
                    mBindingManager.isInBackground(
                        tabs[1].getContentViewCore().getCurrentRenderProcessId()));
              }
            });

    // Kill the renderer and wait for the crash to be noted by the browser process.
    assertTrue(
        ChildProcessLauncher.crashProcessForTesting(
            tabs[1].getContentViewCore().getCurrentRenderProcessId()));

    assertTrue(
        "Renderer crash wasn't noticed by the browser.",
        CriteriaHelper.pollForCriteria(
            new Criteria() {
              @Override
              public boolean isSatisfied() {
                return tabs[1].getContentViewCore().getCurrentRenderProcessId() == 0;
              }
            }));

    // Switch to the tab that crashed in background.
    getInstrumentation()
        .runOnMainSync(
            new Runnable() {
              @Override
              public void run() {
                TabModelUtils.setIndex(getActivity().getCurrentTabModel(), indexOf(tabs[1]));
              }
            });

    // Wait until the process is spawned and its visibility is determined.
    assertTrue(
        "Process for the crashed tab was not respawned.",
        CriteriaHelper.pollForCriteria(
            new Criteria() {
              @Override
              public boolean isSatisfied() {
                return tabs[1].getContentViewCore().getCurrentRenderProcessId() != 0;
              }
            }));

    assertTrue(
        "isInForeground() was not called for the process.",
        CriteriaHelper.pollForCriteria(
            new Criteria() {
              @Override
              public boolean isSatisfied() {
                return mBindingManager.setInForegroundWasCalled(
                    tabs[1].getContentViewCore().getCurrentRenderProcessId());
              }
            }));

    getInstrumentation()
        .runOnMainSync(
            new Runnable() {
              @Override
              public void run() {
                // Verify the visibility of the renderers.
                assertTrue(
                    mBindingManager.isInBackground(
                        tabs[0].getContentViewCore().getCurrentRenderProcessId()));
                assertTrue(
                    mBindingManager.isInForeground(
                        tabs[1].getContentViewCore().getCurrentRenderProcessId()));
              }
            });
  }
  /**
   * Ensures correctness of the visibilityDetermined() calls, that should be always preceded by
   * setInForeground().
   *
   * <p>Bug: https://crbug.com/474543 @LargeTest @Feature({"ProcessManagement"})
   */
  @FlakyTest
  public void testVisibilityDetermined() throws InterruptedException {
    // Create a tab in foreground and wait until it is loaded.
    final Tab fgTab =
        ThreadUtils.runOnUiThreadBlockingNoException(
            new Callable<Tab>() {
              @Override
              public Tab call() {
                TabCreator tabCreator = getActivity().getCurrentTabCreator();
                return tabCreator.createNewTab(
                    new LoadUrlParams(TestHttpServerClient.getUrl(FILE_PATH)),
                    TabLaunchType.FROM_KEYBOARD,
                    null);
              }
            });
    ChromeTabUtils.waitForTabPageLoaded(fgTab, TestHttpServerClient.getUrl(FILE_PATH));
    int initialNavigationPid = fgTab.getContentViewCore().getCurrentRenderProcessId();
    // Ensure the following calls happened:
    //  - FG - setInForeground(true) - when the tab is created in the foreground
    //  - DETERMINED - visibilityDetermined() - after the initial navigation is committed
    assertEquals("FG;DETERMINED;", mBindingManager.getVisibilityCalls(initialNavigationPid));

    // Navigate to about:version which requires a different renderer.
    getInstrumentation()
        .runOnMainSync(
            new Runnable() {
              @Override
              public void run() {
                fgTab.loadUrl(new LoadUrlParams(ABOUT_VERSION_PATH));
              }
            });
    ChromeTabUtils.waitForTabPageLoaded(fgTab, ABOUT_VERSION_PATH);
    int secondNavigationPid = fgTab.getContentViewCore().getCurrentRenderProcessId();
    assertTrue(secondNavigationPid != initialNavigationPid);
    // Ensure the following calls happened:
    //  - BG - setInForeground(false) - when the renderer is created for uncommited frame
    //  - FG - setInForeground(true) - when the frame is swapped in on commit
    //  - DETERMINED - visibilityDetermined() - after the navigation is committed
    assertEquals("BG;FG;DETERMINED;", mBindingManager.getVisibilityCalls(secondNavigationPid));

    // Open a tab in the background and load it.
    final Tab bgTab =
        ThreadUtils.runOnUiThreadBlockingNoException(
            new Callable<Tab>() {
              @Override
              public Tab call() {
                TabCreator tabCreator = getActivity().getCurrentTabCreator();
                Tab tab =
                    tabCreator.createNewTab(
                        new LoadUrlParams(TestHttpServerClient.getUrl(FILE_PATH)),
                        TabLaunchType.FROM_LONGPRESS_BACKGROUND,
                        null);
                // On Svelte devices the background tab would not be loaded automatically,
                // so trigger the load manually.
                tab.show(TabSelectionType.FROM_USER);
                tab.hide();
                return tab;
              }
            });
    ChromeTabUtils.waitForTabPageLoaded(bgTab, TestHttpServerClient.getUrl(FILE_PATH));
    int bgNavigationPid = bgTab.getContentViewCore().getCurrentRenderProcessId();
    // Ensure the following calls happened:
    //  - BG - setInForeground(false) - when tab is created in the background
    //  - DETERMINED - visibilityDetermined() - after the navigation is committed
    assertEquals("BG;DETERMINED;", mBindingManager.getVisibilityCalls(bgNavigationPid));
  }