Commit f91aeaa5 authored by Colin Blundell's avatar Colin Blundell Committed by Commit Bot

Reland "[WebLayer] Add ability to override translate target language"

This is an unchanged reland of 3481a5a7 .
The test failure that caused this CL to be reverted
(https://ci.chromium.org/p/chromium/builders/ci/android-pie-x86-rel/2212)
looks like unrelated pre-existing flake; for example, this run
from September 7 has the same failure:
https://ci.chromium.org/p/chromium/builders/ci/android-pie-x86-rel/2123 .

I will separately handle marking that test flaky.

TBR=jam@chromium.org

Original change's description:
> [WebLayer] Add ability to override translate target language
>
> This CL adds the ability to override the target language used by the
> translate feature on a per-Tab basis. This is analogous to the
> functionality of CCT's TRANSLATE_LANGUAGE intent extra. Once the
> override is set, all translate infobars in the given Tab will appear
> with the specified language as the target language. Calling
> Tab#setTranslateTargetLanguage() with an empty string clears the
> override and causes behavior to revert to normal.
>
> Note that even with the override set the translate infobar will not
> appear for pages that are in the user's locale. This is internal
> behavior of Chromium's translate component and is common to CCT and
> WebLayer.
>
> I marked the added method as since 86 as this CL will be targeted for
> cherrypicking to 86.
>
> Bug: 1116394
> Change-Id: Ic4f08c16a64a3f0ceebed5feab7cdc9401001279
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2397716
> Reviewed-by: John Abd-El-Malek <jam@chromium.org>
> Reviewed-by: Clark DuVall <cduvall@chromium.org>
> Commit-Queue: Colin Blundell <blundell@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#806633}

Bug: 1116394
Change-Id: If8d8058584a260171c83687c2dfcf6732a33846c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2410478Reviewed-by: default avatarColin Blundell <blundell@chromium.org>
Commit-Queue: Colin Blundell <blundell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#806966}
parent 676a1310
......@@ -19,6 +19,7 @@ import org.junit.runner.RunWith;
import org.chromium.content_public.browser.test.util.Criteria;
import org.chromium.content_public.browser.test.util.CriteriaHelper;
import org.chromium.content_public.browser.test.util.TestThreadUtils;
import org.chromium.weblayer.Tab;
import org.chromium.weblayer.TestWebLayer;
import org.chromium.weblayer.shell.InstrumentationActivity;
......@@ -56,9 +57,10 @@ public class TranslateTest {
@Test
@SmallTest
public void testShowTranslateUi() {
public void testShowTranslateUi() throws Exception {
mActivityTestRule.navigateAndWait(mActivityTestRule.getTestDataURL("fr_test.html"));
waitForInfoBarToShow();
Assert.assertEquals("English", getInfoBarTargetLanguage());
EventUtils.simulateTouchCenterOfView(findViewByStringId("id/infobar_close_button"));
waitForInfoBarToHide();
......@@ -68,6 +70,49 @@ public class TranslateTest {
waitForInfoBarToShow();
}
@Test
@SmallTest
public void testOverridingOfTargetLanguage() throws Exception {
// Sanity-check that by default the infobar appears with the target language of the user's
// locale.
mActivityTestRule.navigateAndWait(mActivityTestRule.getTestDataURL("french_page.html"));
waitForInfoBarToShow();
Assert.assertEquals("English", getInfoBarTargetLanguage());
EventUtils.simulateTouchCenterOfView(findViewByStringId("id/infobar_close_button"));
waitForInfoBarToHide();
// Verify overriding of the target language.
Tab tab = mActivityTestRule.getActivity().getTab();
TestThreadUtils.runOnUiThreadBlocking(() -> { tab.setTranslateTargetLanguage("de"); });
mActivityTestRule.navigateAndWait(mActivityTestRule.getTestDataURL("french_page.html"));
waitForInfoBarToShow();
Assert.assertEquals("German", getInfoBarTargetLanguage());
EventUtils.simulateTouchCenterOfView(findViewByStringId("id/infobar_close_button"));
waitForInfoBarToHide();
// Check that the setting persists in the Tab by navigating to another page in French via a
// link click.
mActivityTestRule.executeScriptSync(
"document.onclick = function() {document.getElementById('link_to_french_page2').click()}",
true /* useSeparateIsolate */);
EventUtils.simulateTouchCenterOfView(
mActivityTestRule.getActivity().getWindow().getDecorView());
waitForInfoBarToShow();
Assert.assertEquals("German", getInfoBarTargetLanguage());
EventUtils.simulateTouchCenterOfView(findViewByStringId("id/infobar_close_button"));
waitForInfoBarToHide();
// Check that setting an empty string as the predefined target language causes behavior to
// revert to default.
TestThreadUtils.runOnUiThreadBlocking(() -> { tab.setTranslateTargetLanguage(""); });
mActivityTestRule.navigateAndWait(mActivityTestRule.getTestDataURL("french_page.html"));
waitForInfoBarToShow();
Assert.assertEquals("English", getInfoBarTargetLanguage());
}
private View findViewByStringId(String id) {
return mActivity.findViewById(ResourceUtil.getIdentifier(mRemoteContext, id));
}
......@@ -85,4 +130,12 @@ public class TranslateTest {
Matchers.nullValue());
});
}
private String getInfoBarTargetLanguage() throws Exception {
TestWebLayer testWebLayer = TestWebLayer.getTestWebLayer(mActivity.getApplicationContext());
return TestThreadUtils.runOnUiThreadBlocking(() -> {
return testWebLayer.getTranslateInfoBarTargetLanguage(
mActivity.getBrowser().getActiveTab());
});
}
}
......@@ -38,6 +38,7 @@ import org.chromium.components.external_intents.InterceptNavigationDelegateImpl;
import org.chromium.components.find_in_page.FindInPageBridge;
import org.chromium.components.find_in_page.FindMatchRectsDetails;
import org.chromium.components.find_in_page.FindResultBar;
import org.chromium.components.infobars.InfoBar;
import org.chromium.components.url_formatter.UrlFormatter;
import org.chromium.content_public.browser.LoadUrlParams;
import org.chromium.content_public.browser.NavigationHandle;
......@@ -557,6 +558,11 @@ public final class TabImpl extends ITab.Stub implements LoginPrompt.Observer {
return proxy;
}
@Override
public void setTranslateTargetLanguage(String targetLanguage) {
TabImplJni.get().setTranslateTargetLanguage(mNativeTab, targetLanguage);
}
public void removeFaviconCallbackProxy(FaviconCallbackProxy proxy) {
mFaviconCallbackProxies.remove(proxy);
}
......@@ -1042,6 +1048,16 @@ public final class TabImpl extends ITab.Stub implements LoginPrompt.Observer {
return mInfoBarContainer.getContainerViewForTesting().isAllowedToAutoHide();
}
@VisibleForTesting
public String getTranslateInfoBarTargetLanguageForTesting() {
if (!mInfoBarContainer.hasInfoBars()) return null;
ArrayList<InfoBar> infobars = mInfoBarContainer.getInfoBarsForTesting();
TranslateCompactInfoBar translateInfoBar = (TranslateCompactInfoBar) infobars.get(0);
return translateInfoBar.getTargetLanguageForTesting();
}
@NativeMethods
interface Natives {
TabImpl fromWebContents(WebContents webContents);
......@@ -1070,5 +1086,6 @@ public final class TabImpl extends ITab.Stub implements LoginPrompt.Observer {
void unregisterWebMessageCallback(long nativeTabImpl, String jsObjectName);
boolean canTranslate(long nativeTabImpl);
void showTranslateUi(long nativeTabImpl);
void setTranslateTargetLanguage(long nativeTabImpl, String targetLanguage);
}
}
......@@ -471,6 +471,13 @@ public class TranslateCompactInfoBar extends InfoBar
return this.isTabSelectedForTesting(TARGET_TAB_INDEX);
}
/**
* Returns the name of the target language. This is only used for automation testing.
*/
public String getTargetLanguageForTesting() {
return mOptions.targetLanguageName();
}
private void createAndShowSnackbar(int actionId) {
// NOTE: WebLayer doesn't have snackbars, so the relevant action is just taken directly.
// TODO(blundell): If WebLayer ends up staying with this implementation long-term, update
......
......@@ -71,4 +71,5 @@ interface ITab {
// Added in 86
void setGoogleAccountsCallbackClient(IGoogleAccountsCallbackClient client) = 23;
IFaviconFetcher createFaviconFetcher(IFaviconFetcherClient client) = 24;
void setTranslateTargetLanguage(in String targetLanguage) = 25;
}
......@@ -179,4 +179,10 @@ public final class TestWebLayerImpl extends ITestWebLayer.Stub {
TextView urlBarTextView = (TextView) textView;
return urlBarTextView.getText().toString();
}
@Override
public String getTranslateInfoBarTargetLanguage(ITab tab) {
TabImpl tabImpl = (TabImpl) tab;
return tabImpl.getTranslateInfoBarTargetLanguageForTesting();
}
}
......@@ -46,4 +46,8 @@ interface ITestWebLayer {
boolean canInfoBarContainerScroll(in ITab tab) = 14;
String getDisplayedUrl(IObjectWrapper /* View */ urlBarView) = 15;
// Returns the target language of the currently-showing translate infobar, or null if no translate
// infobar is currently showing.
String getTranslateInfoBarTargetLanguage(in ITab tab) = 16;
}
......@@ -94,6 +94,7 @@
#include "components/embedder_support/android/contextmenu/context_menu_builder.h"
#include "components/embedder_support/android/delegate/color_chooser_android.h"
#include "components/javascript_dialogs/tab_modal_dialog_manager.h" // nogncheck
#include "components/translate/core/browser/translate_manager.h"
#include "ui/android/view_android.h"
#include "ui/gfx/android/java_bitmap.h"
#include "weblayer/browser/browser_controls_container_view.h"
......@@ -103,6 +104,7 @@
#include "weblayer/browser/java/jni/TabImpl_jni.h"
#include "weblayer/browser/javascript_tab_modal_dialog_manager_delegate_android.h"
#include "weblayer/browser/js_communication/web_message_host_factory_proxy.h"
#include "weblayer/browser/translate_client_impl.h"
#include "weblayer/browser/weblayer_factory_impl_android.h"
#include "weblayer/browser/webrtc/media_stream_manager.h"
#endif
......@@ -805,6 +807,16 @@ void TabImpl::ShowTranslateUi(JNIEnv* env) {
TranslateClientImpl::FromWebContents(web_contents())
->ManualTranslateWhenReady();
}
void TabImpl::SetTranslateTargetLanguage(
JNIEnv* env,
const base::android::JavaParamRef<jstring>& translate_target_lang) {
translate::TranslateManager* translate_manager =
TranslateClientImpl::FromWebContents(web_contents())
->GetTranslateManager();
translate_manager->SetPredefinedTargetLanguage(
base::android::ConvertJavaStringToUTF8(env, translate_target_lang));
}
#endif // OS_ANDROID
content::WebContents* TabImpl::OpenURLFromTab(
......
......@@ -198,6 +198,9 @@ class TabImpl : public Tab,
const base::android::JavaParamRef<jstring>& js_object_name);
jboolean CanTranslate(JNIEnv* env);
void ShowTranslateUi(JNIEnv* env);
void SetTranslateTargetLanguage(
JNIEnv* env,
const base::android::JavaParamRef<jstring>& translate_target_lang);
#endif
ErrorPageDelegate* error_page_delegate() { return error_page_delegate_; }
......
......@@ -189,6 +189,27 @@ public class Tab {
return new FaviconFetcher(mImpl, callback);
}
/**
* Sets the target language for translation such that whenever the translate UI shows in this
* Tab, the target language will be |targetLanguage|. Notes:
* - |targetLanguage| should be specified as the language code (e.g., "de" for German).
* - Passing an empty string causes behavior to revert to default.
* - Even with the target language specified, the translate UI will not trigger for pages in the
* user's locale.
* @since 86
*/
public void setTranslateTargetLanguage(@NonNull String targetLanguage) {
ThreadCheck.ensureOnUiThread();
if (WebLayer.getSupportedMajorVersionInternal() < 86) {
throw new UnsupportedOperationException();
}
try {
mImpl.setTranslateTargetLanguage(targetLanguage);
} catch (RemoteException e) {
throw new APICallException(e);
}
}
/**
* Executes the script, and returns the result as a JSON object to the callback if provided. The
* object passed to the callback will have a single key SCRIPT_RESULT_KEY which will hold the
......
......@@ -118,6 +118,10 @@ public final class TestWebLayer {
return mITestWebLayer.getDisplayedUrl(ObjectWrapper.wrap(urlBarView));
}
public String getTranslateInfoBarTargetLanguage(Tab tab) throws RemoteException {
return mITestWebLayer.getTranslateInfoBarTargetLanguage(tab.getITab());
}
public static void disableWebViewCompatibilityMode() {
WebLayer.disableWebViewCompatibilityMode();
}
......
......@@ -22,4 +22,8 @@
android:title="Restart with WebView compat mode" />
<item android:id="@+id/no_webview_compat_menu_id"
android:title="Restart without WebView compat mode" />
<item android:id="@+id/set_translate_target_lang_menu_id"
android:title="Set translate target language to German" />
<item android:id="@+id/clear_translate_target_lang_menu_id"
android:title="Clear translate target language override" />
</menu>
......@@ -273,6 +273,14 @@ public class WebLayerShellActivity extends AppCompatActivity {
restartShell(false);
}
if (item.getItemId() == R.id.set_translate_target_lang_menu_id) {
mBrowser.getActiveTab().setTranslateTargetLanguage("de");
}
if (item.getItemId() == R.id.clear_translate_target_lang_menu_id) {
mBrowser.getActiveTab().setTranslateTargetLanguage("");
}
return false;
});
popup.show();
......
......@@ -2,5 +2,8 @@
<head><title>Cette page est en Français</title></head>
<body>
Cette page a été rédigée en français. Saviez-vous que le Français est la langue officielle des jeux olympiques? Ça vous en bouche un coin, pas vrai?
<a id='link_to_french_page2' href="/weblayer/test/data/french_page2.html">
Une autre page en français
</a>
</body>
</html>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment