blob: abbdc747d0d19c2503f807bc8465040420586a89 [file] [log] [blame]
// Copyright 2013 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.test.util.browser.contextmenu;
import android.app.Activity;
import android.app.Instrumentation;
import android.text.TextUtils;
import android.view.ContextMenu;
import android.view.MenuItem;
import org.junit.Assert;
import org.chromium.base.test.util.CallbackHelper;
import org.chromium.chrome.browser.tab.EmptyTabObserver;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.content.browser.test.util.Criteria;
import org.chromium.content.browser.test.util.CriteriaHelper;
import org.chromium.content.browser.test.util.DOMUtils;
import java.util.concurrent.TimeoutException;
/**
* A utility class to help open and interact with context menus triggered by a WebContents.
*/
public class ContextMenuUtils {
/**
* Callback helper that also provides access to the last display ContextMenu.
*/
private static class OnContextMenuShownHelper extends CallbackHelper {
private ContextMenu mContextMenu;
public void notifyCalled(ContextMenu menu) {
mContextMenu = menu;
notifyCalled();
}
public ContextMenu getContextMenu() {
assert getCallCount() > 0;
return mContextMenu;
}
}
/**
* Opens a context menu.
* @param tab The tab to open a context menu for.
* @param openerDOMNodeId The DOM node to long press to open the context menu for.
* @return The {@link ContextMenu} that was opened.
* @throws InterruptedException
* @throws TimeoutException
*/
public static ContextMenu openContextMenu(Tab tab, String openerDOMNodeId)
throws InterruptedException, TimeoutException {
String jsCode = "document.getElementById('" + openerDOMNodeId + "')";
return openContextMenuByJs(tab, jsCode);
}
/**
* Opens a context menu.
* @param tab The tab to open a context menu for.
* @param jsCode The javascript to get the DOM node to long press to
* open the context menu for.
* @return The {@link ContextMenu} that was opened.
* @throws InterruptedException
* @throws TimeoutException
*/
public static ContextMenu openContextMenuByJs(Tab tab, String jsCode)
throws InterruptedException, TimeoutException {
final OnContextMenuShownHelper helper = new OnContextMenuShownHelper();
tab.addObserver(new EmptyTabObserver() {
@Override
public void onContextMenuShown(Tab tab, ContextMenu menu) {
helper.notifyCalled(menu);
tab.removeObserver(this);
}
});
int callCount = helper.getCallCount();
DOMUtils.longPressNodeByJs(tab.getContentViewCore(), jsCode);
helper.waitForCallback(callCount);
return helper.getContextMenu();
}
/**
* Opens and selects an item from a context menu.
* @param tab The tab to open a context menu for.
* @param openerDOMNodeId The DOM node to long press to open the context menu for.
* @param itemId The context menu item ID to select.
* @throws InterruptedException
* @throws TimeoutException
*/
public static void selectContextMenuItem(Instrumentation instrumentation, Activity activity,
Tab tab, String openerDOMNodeId, final int itemId)
throws InterruptedException, TimeoutException {
String jsCode = "document.getElementById('" + openerDOMNodeId + "')";
selectContextMenuItemByJs(instrumentation, activity, tab, jsCode, itemId);
}
/**
* Long presses to open and selects an item from a context menu.
* @param tab The tab to open a context menu for.
* @param jsCode The javascript to get the DOM node to long press
* to open the context menu for.
* @param itemId The context menu item ID to select.
* @throws InterruptedException
* @throws TimeoutException
*/
public static void selectContextMenuItemByJs(Instrumentation instrumentation, Activity activity,
Tab tab, String jsCode, final int itemId)
throws InterruptedException, TimeoutException {
ContextMenu menu = openContextMenuByJs(tab, jsCode);
Assert.assertNotNull("Failed to open context menu", menu);
selectOpenContextMenuItem(instrumentation, activity, menu, itemId);
}
/**
* Opens and selects an item from a context menu.
* @param tab The tab to open a context menu for.
* @param openerDOMNodeId The DOM node to long press to open the context menu for.
* @param itemTitle The title of the context menu item to select.
* @throws InterruptedException
* @throws TimeoutException
*/
public static void selectContextMenuItemByTitle(Instrumentation instrumentation,
Activity activity, Tab tab, String openerDOMNodeId, String itemTitle)
throws InterruptedException, TimeoutException {
ContextMenu menu = openContextMenu(tab, openerDOMNodeId);
Assert.assertNotNull("Failed to open context menu", menu);
Integer itemId = null;
for (int i = 0; i < menu.size(); i++) {
MenuItem item = menu.getItem(i);
if (TextUtils.equals(item.getTitle(), itemTitle)) {
itemId = item.getItemId();
break;
}
}
Assert.assertNotNull("Couldn't find context menu item for '" + itemTitle + "'", itemId);
selectOpenContextMenuItem(instrumentation, activity, menu, itemId);
}
private static void selectOpenContextMenuItem(Instrumentation instrumentation,
final Activity activity, final ContextMenu menu, final int itemId) {
MenuItem item = menu.findItem(itemId);
Assert.assertNotNull("Could not find '" + itemId + "' in menu", item);
Assert.assertTrue("'" + itemId + "' is not visible", item.isVisible());
Assert.assertTrue("'" + itemId + "' is not enabled", item.isEnabled());
instrumentation.runOnMainSync(new Runnable() {
@Override
public void run() {
boolean activated = menu.performIdentifierAction(itemId, 0);
Assert.assertTrue("Failed to activate '" + itemId + "' in menu", activated);
}
});
CriteriaHelper.pollInstrumentationThread(new Criteria("Activity did not regain focus.") {
@Override
public boolean isSatisfied() {
return activity.hasWindowFocus();
}
});
}
}