blob: 6bfb9122f7aaf08bd8354a85c820a9d4b65d4b22 [file] [log] [blame]
// Copyright 2020 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.
#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/profile_impl.h"
#include "weblayer/browser/tab_impl.h"
#include "weblayer/browser/translate_client_impl.h"
#include "weblayer/public/tab.h"
#include "weblayer/shell/browser/shell.h"
#include "weblayer/test/weblayer_browser_test.h"
#include "weblayer/test/weblayer_browser_test_utils.h"
namespace weblayer {
namespace {
static std::string kTestValidScript = R"(
var google = {};
google.translate = (function() {
return {
TranslateService: function() {
return {
isAvailable : function() {
return true;
},
restore : function() {
return;
},
getDetectedLanguage : function() {
return "fr";
},
translatePage : function(originalLang, targetLang,
onTranslateProgress) {
var error = (originalLang == 'auto') ? true : false;
onTranslateProgress(100, true, error);
}
};
}
};
})();
cr.googleTranslate.onTranslateElementLoad();)";
static std::string kTestScriptInitializationError = R"(
var google = {};
google.translate = (function() {
return {
TranslateService: function() {
return error;
}
};
})();
cr.googleTranslate.onTranslateElementLoad();)";
static std::string kTestScriptTimeout = R"(
var google = {};
google.translate = (function() {
return {
TranslateService: function() {
return {
isAvailable : function() {
return false;
},
};
}
};
})();
cr.googleTranslate.onTranslateElementLoad();)";
TranslateClientImpl* GetTranslateClient(Shell* shell) {
return TranslateClientImpl::FromWebContents(
static_cast<TabImpl*>(shell->tab())->web_contents());
}
std::unique_ptr<translate::TranslateWaiter> CreateTranslateWaiter(
Shell* shell,
translate::TranslateWaiter::WaitEvent wait_event) {
return std::make_unique<translate::TranslateWaiter>(
GetTranslateClient(shell)->translate_driver(), wait_event);
}
void WaitUntilLanguageDetermined(Shell* shell) {
CreateTranslateWaiter(
shell, translate::TranslateWaiter::WaitEvent::kLanguageDetermined)
->Wait();
}
void WaitUntilPageTranslated(Shell* shell) {
CreateTranslateWaiter(shell,
translate::TranslateWaiter::WaitEvent::kPageTranslated)
->Wait();
}
} // namespace
class TranslateBrowserTest : public WebLayerBrowserTest {
public:
TranslateBrowserTest() {
error_subscription_ =
translate::TranslateManager::RegisterTranslateErrorCallback(
base::BindRepeating(&TranslateBrowserTest::OnTranslateError,
base::Unretained(this)));
}
~TranslateBrowserTest() override = default;
void SetUpOnMainThread() override {
embedded_test_server()->RegisterRequestHandler(base::BindRepeating(
&TranslateBrowserTest::HandleRequest, base::Unretained(this)));
embedded_test_server()->StartAcceptingConnections();
}
void SetUpCommandLine(base::CommandLine* command_line) override {
ASSERT_TRUE(embedded_test_server()->InitializeAndListen());
command_line->AppendSwitchASCII(
translate::switches::kTranslateScriptURL,
embedded_test_server()->GetURL("/mock_translate_script.js").spec());
}
protected:
translate::TranslateErrors::Type GetPageTranslatedResult() {
return error_type_;
}
void SetTranslateScript(const std::string& script) { script_ = script; }
private:
std::unique_ptr<net::test_server::HttpResponse> HandleRequest(
const net::test_server::HttpRequest& request) {
if (request.GetURL().path() != "/mock_translate_script.js")
return nullptr;
auto http_response =
std::make_unique<net::test_server::BasicHttpResponse>();
http_response->set_code(net::HTTP_OK);
http_response->set_content(script_);
http_response->set_content_type("text/javascript");
return std::move(http_response);
}
void OnTranslateError(const translate::TranslateErrorDetails& details) {
error_type_ = details.error;
}
translate::TranslateErrors::Type error_type_ =
translate::TranslateErrors::NONE;
std::unique_ptr<
translate::TranslateManager::TranslateErrorCallbackList::Subscription>
error_subscription_;
std::string script_;
};
// Tests that the CLD (Compact Language Detection) works properly.
IN_PROC_BROWSER_TEST_F(TranslateBrowserTest, PageLanguageDetection) {
TranslateClientImpl* translate_client = GetTranslateClient(shell());
NavigateAndWaitForCompletion(GURL("about:blank"), shell());
WaitUntilLanguageDetermined(shell());
EXPECT_EQ("und", translate_client->GetLanguageState().original_language());
// Go to a page in English.
NavigateAndWaitForCompletion(
GURL(embedded_test_server()->GetURL("/english_page.html")), shell());
WaitUntilLanguageDetermined(shell());
EXPECT_EQ("en", translate_client->GetLanguageState().original_language());
// Now 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());
}
// Test that the translation was successful.
IN_PROC_BROWSER_TEST_F(TranslateBrowserTest, PageTranslationSuccess) {
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());
}
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) {
SetTranslateScript(kTestValidScript);
TranslateClientImpl* translate_client = GetTranslateClient(shell());
NavigateAndWaitForCompletion(GURL("about:blank"), shell());
WaitUntilLanguageDetermined(shell());
EXPECT_EQ("und", 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_TRUE(translate_client->GetLanguageState().translation_error());
EXPECT_EQ(translate::TranslateErrors::TRANSLATION_ERROR,
GetPageTranslatedResult());
}
// Test if there was an error during translate library initialization.
IN_PROC_BROWSER_TEST_F(TranslateBrowserTest,
PageTranslationInitializationError) {
SetTranslateScript(kTestScriptInitializationError);
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_TRUE(translate_client->GetLanguageState().translation_error());
EXPECT_EQ(translate::TranslateErrors::INITIALIZATION_ERROR,
GetPageTranslatedResult());
}
// Test the checks translate lib never gets ready and throws timeout.
IN_PROC_BROWSER_TEST_F(TranslateBrowserTest, PageTranslationTimeoutError) {
SetTranslateScript(kTestScriptTimeout);
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_TRUE(translate_client->GetLanguageState().translation_error());
EXPECT_EQ(translate::TranslateErrors::TRANSLATION_TIMEOUT,
GetPageTranslatedResult());
}
// Test that autotranslation kicks in if configured via prefs.
IN_PROC_BROWSER_TEST_F(TranslateBrowserTest, Autotranslation) {
// The translate feature will disable autotranslation if NetworkChangeNotifier
// reports that the app is offline, which can occur on bots. Prevent this.
net::test::ScopedMockNetworkChangeNotifier mock_network_change_notifier;
mock_network_change_notifier.mock_network_change_notifier()
->SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI);
SetTranslateScript(kTestValidScript);
TranslateClientImpl* translate_client = GetTranslateClient(shell());
// By default, autotranslation is disabled if the Google API key is not set.
translate_client->GetTranslateManager()->SetIgnoreMissingKeyForTesting(true);
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());
}
} // namespace weblayer