diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-12 14:27:29 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-13 09:35:20 +0000 |
commit | c30a6232df03e1efbd9f3b226777b07e087a1122 (patch) | |
tree | e992f45784689f373bcc38d1b79a239ebe17ee23 /chromium/weblayer/browser/translate_browsertest.cc | |
parent | 7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3 (diff) | |
download | qtwebengine-chromium-85-based.tar.gz |
BASELINE: Update Chromium to 85.0.4183.14085-based
Change-Id: Iaa42f4680837c57725b1344f108c0196741f6057
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/weblayer/browser/translate_browsertest.cc')
-rw-r--r-- | chromium/weblayer/browser/translate_browsertest.cc | 488 |
1 files changed, 488 insertions, 0 deletions
diff --git a/chromium/weblayer/browser/translate_browsertest.cc b/chromium/weblayer/browser/translate_browsertest.cc index 77daf3c92e4..2824d8b91ea 100644 --- a/chromium/weblayer/browser/translate_browsertest.cc +++ b/chromium/weblayer/browser/translate_browsertest.cc @@ -2,13 +2,18 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "build/build_config.h" #include "components/translate/content/browser/translate_waiter.h" #include "components/translate/core/browser/language_state.h" #include "components/translate/core/browser/translate_error_details.h" #include "components/translate/core/browser/translate_manager.h" #include "components/translate/core/common/translate_switches.h" +#include "content/public/browser/browser_context.h" +#include "net/base/mock_network_change_notifier.h" #include "net/test/embedded_test_server/http_request.h" #include "net/test/embedded_test_server/http_response.h" +#include "weblayer/browser/browser_context_impl.h" +#include "weblayer/browser/profile_impl.h" #include "weblayer/browser/tab_impl.h" #include "weblayer/browser/translate_client_impl.h" #include "weblayer/public/tab.h" @@ -16,6 +21,15 @@ #include "weblayer/test/weblayer_browser_test.h" #include "weblayer/test/weblayer_browser_test_utils.h" +#if defined(OS_ANDROID) +#include "base/android/build_info.h" +#include "components/infobars/core/infobar_manager.h" // nogncheck +#include "components/translate/core/browser/translate_download_manager.h" +#include "weblayer/browser/infobar_android.h" +#include "weblayer/browser/infobar_service.h" +#include "weblayer/browser/translate_compact_infobar.h" +#endif + namespace weblayer { namespace { @@ -98,6 +112,35 @@ void WaitUntilPageTranslated(Shell* shell) { } // namespace +#if defined(OS_ANDROID) +class TestInfoBarManagerObserver : public infobars::InfoBarManager::Observer { + public: + TestInfoBarManagerObserver() = default; + ~TestInfoBarManagerObserver() override = default; + void OnInfoBarAdded(infobars::InfoBar* infobar) override { + if (on_infobar_added_callback_) + std::move(on_infobar_added_callback_).Run(); + } + + void OnInfoBarRemoved(infobars::InfoBar* infobar, bool animate) override { + if (on_infobar_removed_callback_) + std::move(on_infobar_removed_callback_).Run(); + } + + void set_on_infobar_added_callback(base::OnceClosure callback) { + on_infobar_added_callback_ = std::move(callback); + } + + void set_on_infobar_removed_callback(base::OnceClosure callback) { + on_infobar_removed_callback_ = std::move(callback); + } + + private: + base::OnceClosure on_infobar_added_callback_; + base::OnceClosure on_infobar_removed_callback_; +}; +#endif // if defined(OS_ANDROID) + class TranslateBrowserTest : public WebLayerBrowserTest { public: TranslateBrowserTest() { @@ -112,6 +155,26 @@ class TranslateBrowserTest : public WebLayerBrowserTest { embedded_test_server()->RegisterRequestHandler(base::BindRepeating( &TranslateBrowserTest::HandleRequest, base::Unretained(this))); embedded_test_server()->StartAcceptingConnections(); + + // Translation will not be offered if NetworkChangeNotifier reports that the + // app is offline, which can occur on bots. Prevent this. + // NOTE: MockNetworkChangeNotifier cannot be instantiated earlier than this + // due to its dependence on browser state having been created. + mock_network_change_notifier_ = + std::make_unique<net::test::ScopedMockNetworkChangeNotifier>(); + mock_network_change_notifier_->mock_network_change_notifier() + ->SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); + + // By default, translation is not offered if the Google API key is not set. + GetTranslateClient(shell()) + ->GetTranslateManager() + ->SetIgnoreMissingKeyForTesting(true); + + GetTranslateClient(shell())->GetTranslatePrefs()->ResetToDefaults(); + } + + void TearDownOnMainThread() override { + mock_network_change_notifier_.reset(); } void SetUpCommandLine(base::CommandLine* command_line) override { @@ -146,6 +209,9 @@ class TranslateBrowserTest : public WebLayerBrowserTest { error_type_ = details.error; } + std::unique_ptr<net::test::ScopedMockNetworkChangeNotifier> + mock_network_change_notifier_; + translate::TranslateErrors::Type error_type_ = translate::TranslateErrors::NONE; std::unique_ptr< @@ -203,8 +269,54 @@ IN_PROC_BROWSER_TEST_F(TranslateBrowserTest, PageTranslationSuccess) { EXPECT_EQ(translate::TranslateErrors::NONE, GetPageTranslatedResult()); } +class IncognitoTranslateBrowserTest : public TranslateBrowserTest { + public: + IncognitoTranslateBrowserTest() { SetShellStartsInIncognitoMode(); } +}; + +// Test that the translation infrastructure is set up properly when the user is +// in incognito mode. +IN_PROC_BROWSER_TEST_F(IncognitoTranslateBrowserTest, + PageTranslationSuccess_IncognitoMode) { + ASSERT_TRUE(GetProfile()->GetBrowserContext()->IsOffTheRecord()); + + SetTranslateScript(kTestValidScript); + + TranslateClientImpl* translate_client = GetTranslateClient(shell()); + + NavigateAndWaitForCompletion(GURL("about:blank"), shell()); + WaitUntilLanguageDetermined(shell()); + EXPECT_EQ("und", translate_client->GetLanguageState().original_language()); + + // Navigate to a page in French. + NavigateAndWaitForCompletion( + GURL(embedded_test_server()->GetURL("/french_page.html")), shell()); + WaitUntilLanguageDetermined(shell()); + EXPECT_EQ("fr", translate_client->GetLanguageState().original_language()); + + // Translate the page through TranslateManager. + translate::TranslateManager* manager = + translate_client->GetTranslateManager(); + manager->TranslatePage( + translate_client->GetLanguageState().original_language(), "en", true); + + WaitUntilPageTranslated(shell()); + + EXPECT_FALSE(translate_client->GetLanguageState().translation_error()); + EXPECT_EQ(translate::TranslateErrors::NONE, GetPageTranslatedResult()); +} + // Test if there was an error during translation. IN_PROC_BROWSER_TEST_F(TranslateBrowserTest, PageTranslationError) { +#if defined(OS_ANDROID) + // TODO(crbug.com/1094903): Determine why this test times out on the M + // trybot. + if (base::android::BuildInfo::GetInstance()->sdk_int() <= + base::android::SDK_VERSION_MARSHMALLOW) { + return; + } +#endif + SetTranslateScript(kTestValidScript); TranslateClientImpl* translate_client = GetTranslateClient(shell()); @@ -285,4 +397,380 @@ IN_PROC_BROWSER_TEST_F(TranslateBrowserTest, PageTranslationTimeoutError) { GetPageTranslatedResult()); } +// Test that autotranslation kicks in if configured via prefs. +IN_PROC_BROWSER_TEST_F(TranslateBrowserTest, Autotranslation) { +#if defined(OS_ANDROID) + // TODO(crbug.com/1094903): Determine why this test times out on the M + // trybot. + if (base::android::BuildInfo::GetInstance()->sdk_int() <= + base::android::SDK_VERSION_MARSHMALLOW) { + return; + } +#endif + + SetTranslateScript(kTestValidScript); + + TranslateClientImpl* translate_client = GetTranslateClient(shell()); + + NavigateAndWaitForCompletion(GURL("about:blank"), shell()); + WaitUntilLanguageDetermined(shell()); + EXPECT_EQ("und", translate_client->GetLanguageState().original_language()); + + // Before browsing, set autotranslate from French to Chinese. + translate_client->GetTranslatePrefs()->WhitelistLanguagePair("fr", "zh-CN"); + + // Navigate to a page in French. + NavigateAndWaitForCompletion( + GURL(embedded_test_server()->GetURL("/french_page.html")), shell()); + WaitUntilLanguageDetermined(shell()); + EXPECT_EQ("fr", translate_client->GetLanguageState().original_language()); + + // Autotranslation should kick in. + WaitUntilPageTranslated(shell()); + + EXPECT_FALSE(translate_client->GetLanguageState().translation_error()); + EXPECT_EQ(translate::TranslateErrors::NONE, GetPageTranslatedResult()); + EXPECT_EQ("zh-CN", translate_client->GetLanguageState().current_language()); +} + +#if defined(OS_ANDROID) +// Test that the translation infobar is presented when visiting a page with a +// translation opportunity and removed when navigating away. +IN_PROC_BROWSER_TEST_F(TranslateBrowserTest, TranslateInfoBarPresentation) { + auto* web_contents = static_cast<TabImpl*>(shell()->tab())->web_contents(); + auto* infobar_service = InfoBarService::FromWebContents(web_contents); + + SetTranslateScript(kTestValidScript); + + TranslateClientImpl* translate_client = GetTranslateClient(shell()); + + NavigateAndWaitForCompletion(GURL("about:blank"), shell()); + WaitUntilLanguageDetermined(shell()); + EXPECT_EQ("und", translate_client->GetLanguageState().original_language()); + + TestInfoBarManagerObserver infobar_observer; + infobar_service->AddObserver(&infobar_observer); + + base::RunLoop run_loop; + infobar_observer.set_on_infobar_added_callback(run_loop.QuitClosure()); + + EXPECT_EQ(0u, infobar_service->infobar_count()); + // Navigate to a page in French. + NavigateAndWaitForCompletion( + GURL(embedded_test_server()->GetURL("/french_page.html")), shell()); + WaitUntilLanguageDetermined(shell()); + EXPECT_EQ("fr", translate_client->GetLanguageState().original_language()); + + // The translate infobar should be added. + run_loop.Run(); + + EXPECT_EQ(1u, infobar_service->infobar_count()); + auto* infobar = static_cast<InfoBarAndroid*>(infobar_service->infobar_at(0)); + EXPECT_TRUE(infobar->HasSetJavaInfoBar()); + + base::RunLoop run_loop2; + infobar_observer.set_on_infobar_removed_callback(run_loop2.QuitClosure()); + + NavigateAndWaitForCompletion(GURL("about:blank"), shell()); + + // The translate infobar should be removed. + run_loop2.Run(); + + EXPECT_EQ(0u, infobar_service->infobar_count()); + infobar_service->RemoveObserver(&infobar_observer); +} +#endif + +#if defined(OS_ANDROID) +// Test that the translation can be successfully initiated via infobar. +IN_PROC_BROWSER_TEST_F(TranslateBrowserTest, TranslationViaInfoBar) { + // TODO(crbug.com/1094903): Determine why this test times out on the M + // trybot. + if (base::android::BuildInfo::GetInstance()->sdk_int() <= + base::android::SDK_VERSION_MARSHMALLOW) { + return; + } + + auto* web_contents = static_cast<TabImpl*>(shell()->tab())->web_contents(); + auto* infobar_service = InfoBarService::FromWebContents(web_contents); + + SetTranslateScript(kTestValidScript); + + TranslateClientImpl* translate_client = GetTranslateClient(shell()); + + NavigateAndWaitForCompletion(GURL("about:blank"), shell()); + WaitUntilLanguageDetermined(shell()); + EXPECT_EQ("und", translate_client->GetLanguageState().original_language()); + + TestInfoBarManagerObserver infobar_observer; + infobar_service->AddObserver(&infobar_observer); + + base::RunLoop run_loop; + infobar_observer.set_on_infobar_added_callback(run_loop.QuitClosure()); + + // Navigate to a page in French and wait for the infobar to be added. + NavigateAndWaitForCompletion( + GURL(embedded_test_server()->GetURL("/french_page.html")), shell()); + WaitUntilLanguageDetermined(shell()); + EXPECT_EQ("fr", translate_client->GetLanguageState().original_language()); + + run_loop.Run(); + + // Select the target language via the Java infobar and ensure that translation + // occurs. + auto* infobar = + static_cast<TranslateCompactInfoBar*>(infobar_service->infobar_at(0)); + infobar->SelectButtonForTesting(InfoBarAndroid::ActionType::ACTION_TRANSLATE); + + WaitUntilPageTranslated(shell()); + + EXPECT_FALSE(translate_client->GetLanguageState().translation_error()); + EXPECT_EQ(translate::TranslateErrors::NONE, GetPageTranslatedResult()); + + // The translate infobar should still be present. + EXPECT_EQ(1u, infobar_service->infobar_count()); + + // NOTE: The notification that the translate state of the page changed can + // occur synchronously once reversion is initiated, so it's necessary to start + // listening for that notification prior to initiating the reversion. + auto translate_reversion_waiter = CreateTranslateWaiter( + shell(), translate::TranslateWaiter::WaitEvent::kIsPageTranslatedChanged); + + // Revert to the source language via the Java infobar and ensure that the + // translation is undone. + infobar->SelectButtonForTesting( + InfoBarAndroid::ActionType::ACTION_TRANSLATE_SHOW_ORIGINAL); + + translate_reversion_waiter->Wait(); + EXPECT_EQ("fr", translate_client->GetLanguageState().current_language()); + + // The translate infobar should still be present. + EXPECT_EQ(1u, infobar_service->infobar_count()); + + infobar_service->RemoveObserver(&infobar_observer); +} +#endif + +#if defined(OS_ANDROID) +// Test that the translation infobar stays present when the "never translate +// language" item is clicked. Note that this behavior is intentionally different +// from that of Chrome, where the infobar is removed in this case and a snackbar +// is shown. As WebLayer has no snackbars, the UX decision was to simply leave +// the infobar open to allow the user to revert the decision if desired. +IN_PROC_BROWSER_TEST_F(TranslateBrowserTest, + TranslateInfoBarNeverTranslateLanguage) { + auto* web_contents = static_cast<TabImpl*>(shell()->tab())->web_contents(); + auto* infobar_service = InfoBarService::FromWebContents(web_contents); + + SetTranslateScript(kTestValidScript); + + TranslateClientImpl* translate_client = GetTranslateClient(shell()); + + NavigateAndWaitForCompletion(GURL("about:blank"), shell()); + WaitUntilLanguageDetermined(shell()); + EXPECT_EQ("und", translate_client->GetLanguageState().original_language()); + + TestInfoBarManagerObserver infobar_observer; + infobar_service->AddObserver(&infobar_observer); + + base::RunLoop run_loop; + infobar_observer.set_on_infobar_added_callback(run_loop.QuitClosure()); + + // Navigate to a page in French and wait for the infobar to be added. + EXPECT_EQ(0u, infobar_service->infobar_count()); + NavigateAndWaitForCompletion( + GURL(embedded_test_server()->GetURL("/french_page.html")), shell()); + WaitUntilLanguageDetermined(shell()); + EXPECT_EQ("fr", translate_client->GetLanguageState().original_language()); + + run_loop.Run(); + + auto* infobar = + static_cast<TranslateCompactInfoBar*>(infobar_service->infobar_at(0)); + infobar->ClickOverflowMenuItemForTesting( + TranslateCompactInfoBar::OverflowMenuItemId::NEVER_TRANSLATE_LANGUAGE); + + // The translate infobar should still be present. + EXPECT_EQ(1u, infobar_service->infobar_count()); + + // However, the infobar should not be shown on a new navigation to a page in + // French. + NavigateAndWaitForCompletion( + GURL(embedded_test_server()->GetURL("/french_page2.html")), shell()); + WaitUntilLanguageDetermined(shell()); + EXPECT_EQ("fr", translate_client->GetLanguageState().original_language()); + + // NOTE: There is no notification to wait for for the event of the infobar not + // showing. However, in practice the infobar is added synchronously, so if it + // were to be shown, this check would fail. + EXPECT_EQ(0u, infobar_service->infobar_count()); + + // The infobar *should* be shown on a navigation to this site if the page's + // language is detected as something other than French. + base::RunLoop run_loop2; + infobar_observer.set_on_infobar_added_callback(run_loop2.QuitClosure()); + + NavigateAndWaitForCompletion( + GURL(embedded_test_server()->GetURL("/german_page.html")), shell()); + WaitUntilLanguageDetermined(shell()); + EXPECT_EQ("de", translate_client->GetLanguageState().original_language()); + + run_loop2.Run(); + + EXPECT_EQ(1u, infobar_service->infobar_count()); + + infobar_service->RemoveObserver(&infobar_observer); +} + +// Test that the translation infobar stays present when the "never translate +// site" item is clicked. Note that this behavior is intentionally different +// from that of Chrome, where the infobar is removed in this case and a snackbar +// is shown. As WebLayer has no snackbars, the UX decision was to simply leave +// the infobar open to allow the user to revert the decision if desired. +IN_PROC_BROWSER_TEST_F(TranslateBrowserTest, + TranslateInfoBarNeverTranslateSite) { + auto* web_contents = static_cast<TabImpl*>(shell()->tab())->web_contents(); + auto* infobar_service = InfoBarService::FromWebContents(web_contents); + + SetTranslateScript(kTestValidScript); + + TranslateClientImpl* translate_client = GetTranslateClient(shell()); + + NavigateAndWaitForCompletion(GURL("about:blank"), shell()); + WaitUntilLanguageDetermined(shell()); + EXPECT_EQ("und", translate_client->GetLanguageState().original_language()); + + TestInfoBarManagerObserver infobar_observer; + infobar_service->AddObserver(&infobar_observer); + + base::RunLoop run_loop; + infobar_observer.set_on_infobar_added_callback(run_loop.QuitClosure()); + + // Navigate to a page in French and wait for the infobar to be added. + EXPECT_EQ(0u, infobar_service->infobar_count()); + NavigateAndWaitForCompletion( + GURL(embedded_test_server()->GetURL("/french_page.html")), shell()); + WaitUntilLanguageDetermined(shell()); + EXPECT_EQ("fr", translate_client->GetLanguageState().original_language()); + + run_loop.Run(); + + auto* infobar = + static_cast<TranslateCompactInfoBar*>(infobar_service->infobar_at(0)); + infobar->ClickOverflowMenuItemForTesting( + TranslateCompactInfoBar::OverflowMenuItemId::NEVER_TRANSLATE_SITE); + + // The translate infobar should still be present. + EXPECT_EQ(1u, infobar_service->infobar_count()); + + // However, the infobar should not be shown on a new navigation to this site, + // independent of the detected language. + NavigateAndWaitForCompletion( + GURL(embedded_test_server()->GetURL("/french_page2.html")), shell()); + WaitUntilLanguageDetermined(shell()); + EXPECT_EQ("fr", translate_client->GetLanguageState().original_language()); + + // NOTE: There is no notification to wait for for the event of the infobar not + // showing. However, in practice the infobar is added synchronously, so if it + // were to be shown, this check would fail. + EXPECT_EQ(0u, infobar_service->infobar_count()); + + NavigateAndWaitForCompletion( + GURL(embedded_test_server()->GetURL("/german_page.html")), shell()); + WaitUntilLanguageDetermined(shell()); + EXPECT_EQ("de", translate_client->GetLanguageState().original_language()); + EXPECT_EQ(0u, infobar_service->infobar_count()); + + infobar_service->RemoveObserver(&infobar_observer); +} + +// Parameterized to run tests on the "never translate language" and "never +// translate site" menu items. +class NeverTranslateMenuItemTranslateBrowserTest + : public TranslateBrowserTest, + public testing::WithParamInterface< + TranslateCompactInfoBar::OverflowMenuItemId> {}; + +// Test that clicking and unclicking a never translate item ends up being a +// no-op. +IN_PROC_BROWSER_TEST_P(NeverTranslateMenuItemTranslateBrowserTest, + TranslateInfoBarToggleAndToggleBackNeverTranslateItem) { + auto* web_contents = static_cast<TabImpl*>(shell()->tab())->web_contents(); + auto* infobar_service = InfoBarService::FromWebContents(web_contents); + + SetTranslateScript(kTestValidScript); + + TranslateClientImpl* translate_client = GetTranslateClient(shell()); + + NavigateAndWaitForCompletion(GURL("about:blank"), shell()); + WaitUntilLanguageDetermined(shell()); + EXPECT_EQ("und", translate_client->GetLanguageState().original_language()); + + TestInfoBarManagerObserver infobar_observer; + infobar_service->AddObserver(&infobar_observer); + + // Navigate to a page in French, wait for the infobar to be added, and click + // twice on the given overflow menu item. + { + base::RunLoop run_loop; + infobar_observer.set_on_infobar_added_callback(run_loop.QuitClosure()); + + EXPECT_EQ(0u, infobar_service->infobar_count()); + NavigateAndWaitForCompletion( + GURL(embedded_test_server()->GetURL("/french_page.html")), shell()); + WaitUntilLanguageDetermined(shell()); + EXPECT_EQ("fr", translate_client->GetLanguageState().original_language()); + + run_loop.Run(); + + auto* infobar = + static_cast<TranslateCompactInfoBar*>(infobar_service->infobar_at(0)); + infobar->ClickOverflowMenuItemForTesting(GetParam()); + + // The translate infobar should still be present. + EXPECT_EQ(1u, infobar_service->infobar_count()); + + infobar->ClickOverflowMenuItemForTesting(GetParam()); + } + + // The infobar should be shown on a new navigation to a page in the same + // language. + { + base::RunLoop run_loop; + infobar_observer.set_on_infobar_added_callback(run_loop.QuitClosure()); + + NavigateAndWaitForCompletion( + GURL(embedded_test_server()->GetURL("/french_page2.html")), shell()); + WaitUntilLanguageDetermined(shell()); + EXPECT_EQ("fr", translate_client->GetLanguageState().original_language()); + + run_loop.Run(); + } + + // The infobar should be shown on a new navigation to a page in a different + // language in the same site. + { + base::RunLoop run_loop; + infobar_observer.set_on_infobar_added_callback(run_loop.QuitClosure()); + + NavigateAndWaitForCompletion( + GURL(embedded_test_server()->GetURL("/german_page.html")), shell()); + WaitUntilLanguageDetermined(shell()); + EXPECT_EQ("de", translate_client->GetLanguageState().original_language()); + + run_loop.Run(); + } + + infobar_service->RemoveObserver(&infobar_observer); +} + +INSTANTIATE_TEST_SUITE_P( + All, + NeverTranslateMenuItemTranslateBrowserTest, + ::testing::Values( + TranslateCompactInfoBar::OverflowMenuItemId::NEVER_TRANSLATE_LANGUAGE, + TranslateCompactInfoBar::OverflowMenuItemId::NEVER_TRANSLATE_SITE)); + +#endif // #if defined(OS_ANDROID) + } // namespace weblayer |