Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / renderer / translate / translate_helper_browsertest.cc
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.
4
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"
17
18 using testing::AtLeast;
19 using testing::Return;
20 using testing::_;
21
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) {}
30
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();
35   }
36
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);
41   }
42
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&));
54
55  private:
56   DISALLOW_COPY_AND_ASSIGN(TestTranslateHelper);
57 };
58
59 class TranslateHelperBrowserTest : public ChromeRenderViewTest {
60  public:
61   TranslateHelperBrowserTest() : translate_helper_(NULL) {}
62
63  protected:
64   void SetUp() override {
65     ChromeRenderViewTest::SetUp();
66     translate_helper_ = new TestTranslateHelper(view_);
67   }
68
69   void TearDown() override {
70     delete translate_helper_;
71     ChromeRenderViewTest::TearDown();
72   }
73
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;
91   }
92
93   TestTranslateHelper* translate_helper_;
94
95  private:
96   DISALLOW_COPY_AND_ASSIGN(TranslateHelperBrowserTest);
97 };
98
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));
107
108   EXPECT_CALL(*translate_helper_, IsTranslateLibReady())
109       .Times(AtLeast(5))  // See kMaxTranslateInitCheckAttempts in
110                           // translate_helper.cc
111       .WillRepeatedly(Return(false));
112
113   translate_helper_->TranslatePage("en", "fr", std::string());
114   base::MessageLoop::current()->RunUntilIdle();
115
116   translate::TranslateErrors::Type error;
117   ASSERT_TRUE(GetPageTranslatedMessage(NULL, NULL, &error));
118   EXPECT_EQ(translate::TranslateErrors::INITIALIZATION_ERROR, error);
119 }
120
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));
129
130   EXPECT_CALL(*translate_helper_, IsTranslateLibReady())
131       .WillOnce(Return(false))
132       .WillOnce(Return(true));
133
134   EXPECT_CALL(*translate_helper_, StartTranslation()).WillOnce(Return(true));
135
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));
143
144   // V8 call for performance monitoring should be ignored.
145   EXPECT_CALL(*translate_helper_,
146               ExecuteScriptAndGetDoubleResult(_)).Times(3);
147
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();
152
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);
162 }
163
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));
172
173   EXPECT_CALL(*translate_helper_, IsTranslateLibReady())
174       .WillOnce(Return(true));
175
176   EXPECT_CALL(*translate_helper_, StartTranslation()).WillOnce(Return(true));
177
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));
184
185   EXPECT_CALL(*translate_helper_, HasTranslationFinished())
186       .Times(AtLeast(1))
187       .WillRepeatedly(Return(false));
188
189   // V8 call for performance monitoring should be ignored.
190   EXPECT_CALL(*translate_helper_,
191               ExecuteScriptAndGetDoubleResult(_)).Times(2);
192
193   translate_helper_->TranslatePage("en", "fr", std::string());
194   base::MessageLoop::current()->RunUntilIdle();
195
196   translate::TranslateErrors::Type error;
197   ASSERT_TRUE(GetPageTranslatedMessage(NULL, NULL, &error));
198   EXPECT_EQ(translate::TranslateErrors::TRANSLATION_ERROR, error);
199 }
200
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));
209
210   EXPECT_CALL(*translate_helper_, IsTranslateLibReady())
211       .WillOnce(Return(true));
212
213   EXPECT_CALL(*translate_helper_, GetOriginalPageLanguage())
214       .WillOnce(Return("de"));
215
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));
222
223   // V8 call for performance monitoring should be ignored.
224   EXPECT_CALL(*translate_helper_,
225               ExecuteScriptAndGetDoubleResult(_)).Times(3);
226
227   translate_helper_->TranslatePage(translate::kUnknownLanguageCode,
228                                    "fr",
229                                    std::string());
230   base::MessageLoop::current()->RunUntilIdle();
231
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);
239 }
240
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));
249
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));
258
259   // V8 call for performance monitoring should be ignored.
260   EXPECT_CALL(*translate_helper_,
261               ExecuteScriptAndGetDoubleResult(_)).Times(3);
262
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();
270
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);
280 }
281
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));
295
296   // V8 call for performance monitoring should be ignored.
297   EXPECT_CALL(*translate_helper_,
298               ExecuteScriptAndGetDoubleResult(_)).Times(5);
299
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();
308
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);
318 }
319
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();
326
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();
335
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();
345
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.";
354 }
355
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();
362
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();
372
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);
382 }
383
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();
390
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();
400
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);
410 }
411
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();
419
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();
429 }
430
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();
443
444   content::PageState back_state = GetCurrentPageState();
445
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();
454
455   GoBack(back_state);
456
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();
463 }