Add testing/scripts/OWNERS
[chromium-blink-merge.git] / chrome / renderer / translate / translate_helper_browsertest.cc
blob6ce59c3edcec9c6c480504754a6a0b4b26921423
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/time/time.h"
6 #include "chrome/renderer/isolated_world_ids.h"
7 #include "chrome/test/base/chrome_render_view_test.h"
8 #include "components/translate/content/common/translate_messages.h"
9 #include "components/translate/content/renderer/translate_helper.h"
10 #include "components/translate/core/common/translate_constants.h"
11 #include "content/public/renderer/render_view.h"
12 #include "extensions/common/constants.h"
13 #include "extensions/renderer/extension_groups.h"
14 #include "testing/gmock/include/gmock/gmock.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 #include "third_party/WebKit/public/web/WebLocalFrame.h"
18 using testing::AtLeast;
19 using testing::Return;
20 using testing::_;
22 class TestTranslateHelper : public translate::TranslateHelper {
23 public:
24 explicit TestTranslateHelper(content::RenderView* render_view)
25 : translate::TranslateHelper(
26 render_view,
27 chrome::ISOLATED_WORLD_ID_TRANSLATE,
28 extensions::EXTENSION_GROUP_INTERNAL_TRANSLATE_SCRIPTS,
29 extensions::kExtensionScheme) {}
31 virtual base::TimeDelta AdjustDelay(int delayInMs) override {
32 // Just returns base::TimeDelta() which has initial value 0.
33 // Tasks doesn't need to be delayed in tests.
34 return base::TimeDelta();
37 void TranslatePage(const std::string& source_lang,
38 const std::string& target_lang,
39 const std::string& translate_script) {
40 OnTranslatePage(0, translate_script, source_lang, target_lang);
43 MOCK_METHOD0(IsTranslateLibAvailable, bool());
44 MOCK_METHOD0(IsTranslateLibReady, bool());
45 MOCK_METHOD0(HasTranslationFinished, bool());
46 MOCK_METHOD0(HasTranslationFailed, bool());
47 MOCK_METHOD0(GetOriginalPageLanguage, std::string());
48 MOCK_METHOD0(StartTranslation, bool());
49 MOCK_METHOD1(ExecuteScript, void(const std::string&));
50 MOCK_METHOD2(ExecuteScriptAndGetBoolResult, bool(const std::string&, bool));
51 MOCK_METHOD1(ExecuteScriptAndGetStringResult,
52 std::string(const std::string&));
53 MOCK_METHOD1(ExecuteScriptAndGetDoubleResult, double(const std::string&));
55 private:
56 DISALLOW_COPY_AND_ASSIGN(TestTranslateHelper);
59 class TranslateHelperBrowserTest : public ChromeRenderViewTest {
60 public:
61 TranslateHelperBrowserTest() : translate_helper_(NULL) {}
63 protected:
64 void SetUp() override {
65 ChromeRenderViewTest::SetUp();
66 translate_helper_ = new TestTranslateHelper(view_);
69 void TearDown() override {
70 delete translate_helper_;
71 ChromeRenderViewTest::TearDown();
74 bool GetPageTranslatedMessage(std::string* original_lang,
75 std::string* target_lang,
76 translate::TranslateErrors::Type* error) {
77 const IPC::Message* message = render_thread_->sink().
78 GetUniqueMessageMatching(ChromeViewHostMsg_PageTranslated::ID);
79 if (!message)
80 return false;
81 Tuple3<std::string, std::string, translate::TranslateErrors::Type>
82 translate_param;
83 ChromeViewHostMsg_PageTranslated::Read(message, &translate_param);
84 if (original_lang)
85 *original_lang = translate_param.a;
86 if (target_lang)
87 *target_lang = translate_param.b;
88 if (error)
89 *error = translate_param.c;
90 return true;
93 TestTranslateHelper* translate_helper_;
95 private:
96 DISALLOW_COPY_AND_ASSIGN(TranslateHelperBrowserTest);
99 // Tests that the browser gets notified of the translation failure if the
100 // translate library fails/times-out during initialization.
101 TEST_F(TranslateHelperBrowserTest, TranslateLibNeverReady) {
102 // We make IsTranslateLibAvailable true so we don't attempt to inject the
103 // library.
104 EXPECT_CALL(*translate_helper_, IsTranslateLibAvailable())
105 .Times(AtLeast(1))
106 .WillRepeatedly(Return(true));
108 EXPECT_CALL(*translate_helper_, IsTranslateLibReady())
109 .Times(AtLeast(5)) // See kMaxTranslateInitCheckAttempts in
110 // translate_helper.cc
111 .WillRepeatedly(Return(false));
113 translate_helper_->TranslatePage("en", "fr", std::string());
114 base::MessageLoop::current()->RunUntilIdle();
116 translate::TranslateErrors::Type error;
117 ASSERT_TRUE(GetPageTranslatedMessage(NULL, NULL, &error));
118 EXPECT_EQ(translate::TranslateErrors::INITIALIZATION_ERROR, error);
121 // Tests that the browser gets notified of the translation success when the
122 // translation succeeds.
123 TEST_F(TranslateHelperBrowserTest, TranslateSuccess) {
124 // We make IsTranslateLibAvailable true so we don't attempt to inject the
125 // library.
126 EXPECT_CALL(*translate_helper_, IsTranslateLibAvailable())
127 .Times(AtLeast(1))
128 .WillRepeatedly(Return(true));
130 EXPECT_CALL(*translate_helper_, IsTranslateLibReady())
131 .WillOnce(Return(false))
132 .WillOnce(Return(true));
134 EXPECT_CALL(*translate_helper_, StartTranslation()).WillOnce(Return(true));
136 // Succeed after few checks.
137 EXPECT_CALL(*translate_helper_, HasTranslationFailed())
138 .WillRepeatedly(Return(false));
139 EXPECT_CALL(*translate_helper_, HasTranslationFinished())
140 .WillOnce(Return(false))
141 .WillOnce(Return(false))
142 .WillOnce(Return(true));
144 // V8 call for performance monitoring should be ignored.
145 EXPECT_CALL(*translate_helper_,
146 ExecuteScriptAndGetDoubleResult(_)).Times(3);
148 std::string original_lang("en");
149 std::string target_lang("fr");
150 translate_helper_->TranslatePage(original_lang, target_lang, std::string());
151 base::MessageLoop::current()->RunUntilIdle();
153 std::string received_original_lang;
154 std::string received_target_lang;
155 translate::TranslateErrors::Type error;
156 ASSERT_TRUE(GetPageTranslatedMessage(&received_original_lang,
157 &received_target_lang,
158 &error));
159 EXPECT_EQ(original_lang, received_original_lang);
160 EXPECT_EQ(target_lang, received_target_lang);
161 EXPECT_EQ(translate::TranslateErrors::NONE, error);
164 // Tests that the browser gets notified of the translation failure when the
165 // translation fails.
166 TEST_F(TranslateHelperBrowserTest, TranslateFailure) {
167 // We make IsTranslateLibAvailable true so we don't attempt to inject the
168 // library.
169 EXPECT_CALL(*translate_helper_, IsTranslateLibAvailable())
170 .Times(AtLeast(1))
171 .WillRepeatedly(Return(true));
173 EXPECT_CALL(*translate_helper_, IsTranslateLibReady())
174 .WillOnce(Return(true));
176 EXPECT_CALL(*translate_helper_, StartTranslation()).WillOnce(Return(true));
178 // Fail after few checks.
179 EXPECT_CALL(*translate_helper_, HasTranslationFailed())
180 .WillOnce(Return(false))
181 .WillOnce(Return(false))
182 .WillOnce(Return(false))
183 .WillOnce(Return(true));
185 EXPECT_CALL(*translate_helper_, HasTranslationFinished())
186 .Times(AtLeast(1))
187 .WillRepeatedly(Return(false));
189 // V8 call for performance monitoring should be ignored.
190 EXPECT_CALL(*translate_helper_,
191 ExecuteScriptAndGetDoubleResult(_)).Times(2);
193 translate_helper_->TranslatePage("en", "fr", std::string());
194 base::MessageLoop::current()->RunUntilIdle();
196 translate::TranslateErrors::Type error;
197 ASSERT_TRUE(GetPageTranslatedMessage(NULL, NULL, &error));
198 EXPECT_EQ(translate::TranslateErrors::TRANSLATION_ERROR, error);
201 // Tests that when the browser translate a page for which the language is
202 // undefined we query the translate element to get the language.
203 TEST_F(TranslateHelperBrowserTest, UndefinedSourceLang) {
204 // We make IsTranslateLibAvailable true so we don't attempt to inject the
205 // library.
206 EXPECT_CALL(*translate_helper_, IsTranslateLibAvailable())
207 .Times(AtLeast(1))
208 .WillRepeatedly(Return(true));
210 EXPECT_CALL(*translate_helper_, IsTranslateLibReady())
211 .WillOnce(Return(true));
213 EXPECT_CALL(*translate_helper_, GetOriginalPageLanguage())
214 .WillOnce(Return("de"));
216 EXPECT_CALL(*translate_helper_, StartTranslation()).WillOnce(Return(true));
217 EXPECT_CALL(*translate_helper_, HasTranslationFailed())
218 .WillOnce(Return(false));
219 EXPECT_CALL(*translate_helper_, HasTranslationFinished())
220 .Times(AtLeast(1))
221 .WillRepeatedly(Return(true));
223 // V8 call for performance monitoring should be ignored.
224 EXPECT_CALL(*translate_helper_,
225 ExecuteScriptAndGetDoubleResult(_)).Times(3);
227 translate_helper_->TranslatePage(translate::kUnknownLanguageCode,
228 "fr",
229 std::string());
230 base::MessageLoop::current()->RunUntilIdle();
232 translate::TranslateErrors::Type error;
233 std::string original_lang;
234 std::string target_lang;
235 ASSERT_TRUE(GetPageTranslatedMessage(&original_lang, &target_lang, &error));
236 EXPECT_EQ("de", original_lang);
237 EXPECT_EQ("fr", target_lang);
238 EXPECT_EQ(translate::TranslateErrors::NONE, error);
241 // Tests that starting a translation while a similar one is pending does not
242 // break anything.
243 TEST_F(TranslateHelperBrowserTest, MultipleSimilarTranslations) {
244 // We make IsTranslateLibAvailable true so we don't attempt to inject the
245 // library.
246 EXPECT_CALL(*translate_helper_, IsTranslateLibAvailable())
247 .Times(AtLeast(1))
248 .WillRepeatedly(Return(true));
250 EXPECT_CALL(*translate_helper_, IsTranslateLibReady())
251 .WillRepeatedly(Return(true));
252 EXPECT_CALL(*translate_helper_, StartTranslation())
253 .WillRepeatedly(Return(true));
254 EXPECT_CALL(*translate_helper_, HasTranslationFailed())
255 .WillRepeatedly(Return(false));
256 EXPECT_CALL(*translate_helper_, HasTranslationFinished())
257 .WillOnce(Return(true));
259 // V8 call for performance monitoring should be ignored.
260 EXPECT_CALL(*translate_helper_,
261 ExecuteScriptAndGetDoubleResult(_)).Times(3);
263 std::string original_lang("en");
264 std::string target_lang("fr");
265 translate_helper_->TranslatePage(original_lang, target_lang, std::string());
266 // While this is running call again TranslatePage to make sure noting bad
267 // happens.
268 translate_helper_->TranslatePage(original_lang, target_lang, std::string());
269 base::MessageLoop::current()->RunUntilIdle();
271 std::string received_original_lang;
272 std::string received_target_lang;
273 translate::TranslateErrors::Type error;
274 ASSERT_TRUE(GetPageTranslatedMessage(&received_original_lang,
275 &received_target_lang,
276 &error));
277 EXPECT_EQ(original_lang, received_original_lang);
278 EXPECT_EQ(target_lang, received_target_lang);
279 EXPECT_EQ(translate::TranslateErrors::NONE, error);
282 // Tests that starting a translation while a different one is pending works.
283 TEST_F(TranslateHelperBrowserTest, MultipleDifferentTranslations) {
284 EXPECT_CALL(*translate_helper_, IsTranslateLibAvailable())
285 .Times(AtLeast(1))
286 .WillRepeatedly(Return(true));
287 EXPECT_CALL(*translate_helper_, IsTranslateLibReady())
288 .WillRepeatedly(Return(true));
289 EXPECT_CALL(*translate_helper_, StartTranslation())
290 .WillRepeatedly(Return(true));
291 EXPECT_CALL(*translate_helper_, HasTranslationFailed())
292 .WillRepeatedly(Return(false));
293 EXPECT_CALL(*translate_helper_, HasTranslationFinished())
294 .WillOnce(Return(true));
296 // V8 call for performance monitoring should be ignored.
297 EXPECT_CALL(*translate_helper_,
298 ExecuteScriptAndGetDoubleResult(_)).Times(5);
300 std::string original_lang("en");
301 std::string target_lang("fr");
302 translate_helper_->TranslatePage(original_lang, target_lang, std::string());
303 // While this is running call again TranslatePage with a new target lang.
304 std::string new_target_lang("de");
305 translate_helper_->TranslatePage(
306 original_lang, new_target_lang, std::string());
307 base::MessageLoop::current()->RunUntilIdle();
309 std::string received_original_lang;
310 std::string received_target_lang;
311 translate::TranslateErrors::Type error;
312 ASSERT_TRUE(GetPageTranslatedMessage(&received_original_lang,
313 &received_target_lang,
314 &error));
315 EXPECT_EQ(original_lang, received_original_lang);
316 EXPECT_EQ(new_target_lang, received_target_lang);
317 EXPECT_EQ(translate::TranslateErrors::NONE, error);
320 // Tests that we send the right translate language message for a page and that
321 // we respect the "no translate" meta-tag.
322 TEST_F(ChromeRenderViewTest, TranslatablePage) {
323 // Suppress the normal delay that occurs when the page is loaded before which
324 // the renderer sends the page contents to the browser.
325 SendContentStateImmediately();
327 LoadHTML("<html><body>A random page with random content.</body></html>");
328 const IPC::Message* message = render_thread_->sink().GetUniqueMessageMatching(
329 ChromeViewHostMsg_TranslateLanguageDetermined::ID);
330 ASSERT_NE(static_cast<IPC::Message*>(NULL), message);
331 ChromeViewHostMsg_TranslateLanguageDetermined::Param params;
332 ChromeViewHostMsg_TranslateLanguageDetermined::Read(message, &params);
333 EXPECT_TRUE(params.b) << "Page should be translatable.";
334 render_thread_->sink().ClearMessages();
336 // Now the page specifies the META tag to prevent translation.
337 LoadHTML("<html><head><meta name=\"google\" value=\"notranslate\"></head>"
338 "<body>A random page with random content.</body></html>");
339 message = render_thread_->sink().GetUniqueMessageMatching(
340 ChromeViewHostMsg_TranslateLanguageDetermined::ID);
341 ASSERT_NE(static_cast<IPC::Message*>(NULL), message);
342 ChromeViewHostMsg_TranslateLanguageDetermined::Read(message, &params);
343 EXPECT_FALSE(params.b) << "Page should not be translatable.";
344 render_thread_->sink().ClearMessages();
346 // Try the alternate version of the META tag (content instead of value).
347 LoadHTML("<html><head><meta name=\"google\" content=\"notranslate\"></head>"
348 "<body>A random page with random content.</body></html>");
349 message = render_thread_->sink().GetUniqueMessageMatching(
350 ChromeViewHostMsg_TranslateLanguageDetermined::ID);
351 ASSERT_NE(static_cast<IPC::Message*>(NULL), message);
352 ChromeViewHostMsg_TranslateLanguageDetermined::Read(message, &params);
353 EXPECT_FALSE(params.b) << "Page should not be translatable.";
356 // Tests that the language meta tag takes precedence over the CLD when reporting
357 // the page's language.
358 TEST_F(ChromeRenderViewTest, LanguageMetaTag) {
359 // Suppress the normal delay that occurs when the page is loaded before which
360 // the renderer sends the page contents to the browser.
361 SendContentStateImmediately();
363 LoadHTML("<html><head><meta http-equiv=\"content-language\" content=\"es\">"
364 "</head><body>A random page with random content.</body></html>");
365 const IPC::Message* message = render_thread_->sink().GetUniqueMessageMatching(
366 ChromeViewHostMsg_TranslateLanguageDetermined::ID);
367 ASSERT_NE(static_cast<IPC::Message*>(NULL), message);
368 ChromeViewHostMsg_TranslateLanguageDetermined::Param params;
369 ChromeViewHostMsg_TranslateLanguageDetermined::Read(message, &params);
370 EXPECT_EQ("es", params.a.adopted_language);
371 render_thread_->sink().ClearMessages();
373 // Makes sure we support multiple languages specified.
374 LoadHTML("<html><head><meta http-equiv=\"content-language\" "
375 "content=\" fr , es,en \">"
376 "</head><body>A random page with random content.</body></html>");
377 message = render_thread_->sink().GetUniqueMessageMatching(
378 ChromeViewHostMsg_TranslateLanguageDetermined::ID);
379 ASSERT_NE(static_cast<IPC::Message*>(NULL), message);
380 ChromeViewHostMsg_TranslateLanguageDetermined::Read(message, &params);
381 EXPECT_EQ("fr", params.a.adopted_language);
384 // Tests that the language meta tag works even with non-all-lower-case.
385 // http://code.google.com/p/chromium/issues/detail?id=145689
386 TEST_F(ChromeRenderViewTest, LanguageMetaTagCase) {
387 // Suppress the normal delay that occurs when the page is loaded before which
388 // the renderer sends the page contents to the browser.
389 SendContentStateImmediately();
391 LoadHTML("<html><head><meta http-equiv=\"Content-Language\" content=\"es\">"
392 "</head><body>A random page with random content.</body></html>");
393 const IPC::Message* message = render_thread_->sink().GetUniqueMessageMatching(
394 ChromeViewHostMsg_TranslateLanguageDetermined::ID);
395 ASSERT_NE(static_cast<IPC::Message*>(NULL), message);
396 ChromeViewHostMsg_TranslateLanguageDetermined::Param params;
397 ChromeViewHostMsg_TranslateLanguageDetermined::Read(message, &params);
398 EXPECT_EQ("es", params.a.adopted_language);
399 render_thread_->sink().ClearMessages();
401 // Makes sure we support multiple languages specified.
402 LoadHTML("<html><head><meta http-equiv=\"Content-Language\" "
403 "content=\" fr , es,en \">"
404 "</head><body>A random page with random content.</body></html>");
405 message = render_thread_->sink().GetUniqueMessageMatching(
406 ChromeViewHostMsg_TranslateLanguageDetermined::ID);
407 ASSERT_NE(static_cast<IPC::Message*>(NULL), message);
408 ChromeViewHostMsg_TranslateLanguageDetermined::Read(message, &params);
409 EXPECT_EQ("fr", params.a.adopted_language);
412 // Tests that the language meta tag is converted to Chrome standard of dashes
413 // instead of underscores and proper capitalization.
414 // http://code.google.com/p/chromium/issues/detail?id=159487
415 TEST_F(ChromeRenderViewTest, LanguageCommonMistakesAreCorrected) {
416 // Suppress the normal delay that occurs when the page is loaded before which
417 // the renderer sends the page contents to the browser.
418 SendContentStateImmediately();
420 LoadHTML("<html><head><meta http-equiv='Content-Language' content='EN_us'>"
421 "</head><body>A random page with random content.</body></html>");
422 const IPC::Message* message = render_thread_->sink().GetUniqueMessageMatching(
423 ChromeViewHostMsg_TranslateLanguageDetermined::ID);
424 ASSERT_NE(static_cast<IPC::Message*>(NULL), message);
425 ChromeViewHostMsg_TranslateLanguageDetermined::Param params;
426 ChromeViewHostMsg_TranslateLanguageDetermined::Read(message, &params);
427 EXPECT_EQ("en-US", params.a.adopted_language);
428 render_thread_->sink().ClearMessages();
431 // Tests that a back navigation gets a translate language message.
432 TEST_F(ChromeRenderViewTest, BackToTranslatablePage) {
433 SendContentStateImmediately();
434 LoadHTML("<html><head><meta http-equiv=\"content-language\" content=\"zh\">"
435 "</head><body>This page is in Chinese.</body></html>");
436 const IPC::Message* message = render_thread_->sink().GetUniqueMessageMatching(
437 ChromeViewHostMsg_TranslateLanguageDetermined::ID);
438 ASSERT_NE(static_cast<IPC::Message*>(NULL), message);
439 ChromeViewHostMsg_TranslateLanguageDetermined::Param params;
440 ChromeViewHostMsg_TranslateLanguageDetermined::Read(message, &params);
441 EXPECT_EQ("zh", params.a.adopted_language);
442 render_thread_->sink().ClearMessages();
444 content::PageState back_state = GetCurrentPageState();
446 LoadHTML("<html><head><meta http-equiv=\"content-language\" content=\"fr\">"
447 "</head><body>This page is in French.</body></html>");
448 message = render_thread_->sink().GetUniqueMessageMatching(
449 ChromeViewHostMsg_TranslateLanguageDetermined::ID);
450 ASSERT_NE(static_cast<IPC::Message*>(NULL), message);
451 ChromeViewHostMsg_TranslateLanguageDetermined::Read(message, &params);
452 EXPECT_EQ("fr", params.a.adopted_language);
453 render_thread_->sink().ClearMessages();
455 GoBack(back_state);
457 message = render_thread_->sink().GetUniqueMessageMatching(
458 ChromeViewHostMsg_TranslateLanguageDetermined::ID);
459 ASSERT_NE(static_cast<IPC::Message*>(NULL), message);
460 ChromeViewHostMsg_TranslateLanguageDetermined::Read(message, &params);
461 EXPECT_EQ("zh", params.a.adopted_language);
462 render_thread_->sink().ClearMessages();