| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #import "components/translate/ios/browser/js_language_detection_manager.h" | 5 #import "components/translate/ios/browser/js_language_detection_manager.h" |
| 6 | 6 |
| 7 #include <string.h> | 7 #include <string.h> |
| 8 | 8 |
| 9 #include <memory> | 9 #include <memory> |
| 10 #include <vector> | 10 #include <vector> |
| 11 | 11 |
| 12 #include "base/bind.h" | 12 #include "base/bind.h" |
| 13 #include "base/mac/scoped_nsobject.h" | |
| 14 #import "base/test/ios/wait_util.h" | 13 #import "base/test/ios/wait_util.h" |
| 15 #include "base/values.h" | 14 #include "base/values.h" |
| 16 #import "ios/chrome/browser/web/chrome_web_test.h" | 15 #import "ios/chrome/browser/web/chrome_web_test.h" |
| 17 #include "ios/chrome/common/string_util.h" | 16 #include "ios/chrome/common/string_util.h" |
| 18 #import "ios/web/public/test/js_test_util.h" | 17 #import "ios/web/public/test/js_test_util.h" |
| 19 #import "ios/web/public/web_state/js/crw_js_injection_receiver.h" | 18 #import "ios/web/public/web_state/js/crw_js_injection_receiver.h" |
| 20 #import "ios/web/public/web_state/web_state.h" | 19 #import "ios/web/public/web_state/web_state.h" |
| 21 #include "testing/gtest/include/gtest/gtest.h" | 20 #include "testing/gtest/include/gtest/gtest.h" |
| 22 #include "testing/gtest_mac.h" | 21 #include "testing/gtest_mac.h" |
| 23 | 22 |
| 23 #if !defined(__has_feature) || !__has_feature(objc_arc) |
| 24 #error "This file requires ARC support." |
| 25 #endif |
| 26 |
| 24 namespace { | 27 namespace { |
| 25 | 28 |
| 26 const char kExpectedLanguage[] = "Foo"; | 29 const char kExpectedLanguage[] = "Foo"; |
| 27 | 30 |
| 28 // Returns an NSString filled with the char 'a' of length |length|. | 31 // Returns an NSString filled with the char 'a' of length |length|. |
| 29 NSString* GetLongString(NSUInteger length) { | 32 NSString* GetLongString(NSUInteger length) { |
| 30 base::scoped_nsobject<NSMutableData> data( | 33 NSMutableData* data = [[NSMutableData alloc] initWithLength:length]; |
| 31 [[NSMutableData alloc] initWithLength:length]); | |
| 32 memset([data mutableBytes], 'a', length); | 34 memset([data mutableBytes], 'a', length); |
| 33 NSString* long_string = | 35 NSString* long_string = |
| 34 [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding]; | 36 [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding]; |
| 35 return [long_string autorelease]; | 37 return long_string; |
| 36 } | 38 } |
| 37 | 39 |
| 38 } // namespace | 40 } // namespace |
| 39 | 41 |
| 40 // TODO(shreyasv): Moved this to the translate component. | 42 // TODO(shreyasv): Moved this to the translate component. |
| 41 // Test fixture to test language detection. | 43 // Test fixture to test language detection. |
| 42 class JsLanguageDetectionManagerTest : public ChromeWebTest { | 44 class JsLanguageDetectionManagerTest : public ChromeWebTest { |
| 43 protected: | 45 protected: |
| 44 void SetUp() override { | 46 void SetUp() override { |
| 45 ChromeWebTest::SetUp(); | 47 ChromeWebTest::SetUp(); |
| 46 manager_.reset(static_cast<JsLanguageDetectionManager*>( | 48 manager_ = static_cast<JsLanguageDetectionManager*>( |
| 47 [[web_state()->GetJSInjectionReceiver() | 49 [web_state()->GetJSInjectionReceiver() |
| 48 instanceOfClass:[JsLanguageDetectionManager class]] retain])); | 50 instanceOfClass:[JsLanguageDetectionManager class]]); |
| 49 ASSERT_TRUE(manager_); | 51 ASSERT_TRUE(manager_); |
| 50 } | 52 } |
| 51 | 53 |
| 52 void LoadHtmlAndInject(NSString* html) { | 54 void LoadHtmlAndInject(NSString* html) { |
| 53 ChromeWebTest::LoadHtml(html); | 55 ChromeWebTest::LoadHtml(html); |
| 54 [manager_ inject]; | 56 [manager_ inject]; |
| 55 ASSERT_TRUE([manager_ hasBeenInjected]); | 57 ASSERT_TRUE([manager_ hasBeenInjected]); |
| 56 } | 58 } |
| 57 | 59 |
| 58 // Injects JS, waits for the completion handler and verifies if the result | 60 // Injects JS, waits for the completion handler and verifies if the result |
| (...skipping 27 matching lines...) Expand all Loading... |
| 86 void ExpectHttpContentLanguage(NSString* expected_http_content_language) { | 88 void ExpectHttpContentLanguage(NSString* expected_http_content_language) { |
| 87 NSString* const kMetaTagContentJS = | 89 NSString* const kMetaTagContentJS = |
| 88 @"__gCrWeb.languageDetection.getMetaContentByHttpEquiv(" | 90 @"__gCrWeb.languageDetection.getMetaContentByHttpEquiv(" |
| 89 @"'content-language');"; | 91 @"'content-language');"; |
| 90 InjectJsAndVerify(kMetaTagContentJS, expected_http_content_language); | 92 InjectJsAndVerify(kMetaTagContentJS, expected_http_content_language); |
| 91 } | 93 } |
| 92 | 94 |
| 93 // Verifies if |__gCrWeb.languageDetection.getTextContent| correctly extracts | 95 // Verifies if |__gCrWeb.languageDetection.getTextContent| correctly extracts |
| 94 // the text content from an HTML page. | 96 // the text content from an HTML page. |
| 95 void ExpectTextContent(NSString* expected_text_content) { | 97 void ExpectTextContent(NSString* expected_text_content) { |
| 96 base::scoped_nsobject<NSString> script([[NSString alloc] | 98 NSString* script = [[NSString alloc] |
| 97 initWithFormat: | 99 initWithFormat: |
| 98 @"__gCrWeb.languageDetection.getTextContent(document.body, %lu);", | 100 @"__gCrWeb.languageDetection.getTextContent(document.body, %lu);", |
| 99 language_detection::kMaxIndexChars]); | 101 language_detection::kMaxIndexChars]; |
| 100 InjectJsAndVerify(script, expected_text_content); | 102 InjectJsAndVerify(script, expected_text_content); |
| 101 } | 103 } |
| 102 | 104 |
| 103 base::scoped_nsobject<JsLanguageDetectionManager> manager_; | 105 JsLanguageDetectionManager* manager_; |
| 104 }; | 106 }; |
| 105 | 107 |
| 106 // Tests that |hasBeenInjected| returns YES after |inject| call. | 108 // Tests that |hasBeenInjected| returns YES after |inject| call. |
| 107 TEST_F(JsLanguageDetectionManagerTest, InitAndInject) { | 109 TEST_F(JsLanguageDetectionManagerTest, InitAndInject) { |
| 108 LoadHtmlAndInject(@"<html></html>"); | 110 LoadHtmlAndInject(@"<html></html>"); |
| 109 } | 111 } |
| 110 | 112 |
| 111 // Tests |__gCrWeb.languageDetection.translationAllowed| JS call. | 113 // Tests |__gCrWeb.languageDetection.translationAllowed| JS call. |
| 112 TEST_F(JsLanguageDetectionManagerTest, IsTranslationAllowed) { | 114 TEST_F(JsLanguageDetectionManagerTest, IsTranslationAllowed) { |
| 113 LoadHtmlAndInject(@"<html></html>"); | 115 LoadHtmlAndInject(@"<html></html>"); |
| 114 ExpectTranslationAllowed(YES); | 116 ExpectTranslationAllowed(YES); |
| 115 | 117 |
| 116 LoadHtmlAndInject(@"<html><head>" | 118 LoadHtmlAndInject(@"<html><head>" |
| 117 "<meta name='google' content='notranslate'>" | 119 "<meta name='google' content='notranslate'>" |
| 118 "</head></html>"); | 120 "</head></html>"); |
| 119 ExpectTranslationAllowed(NO); | 121 ExpectTranslationAllowed(NO); |
| 120 | 122 |
| 121 LoadHtmlAndInject(@"<html><head>" | 123 LoadHtmlAndInject(@"<html><head>" |
| 122 "<meta name='google' value='notranslate'>" | 124 "<meta name='google' value='notranslate'>" |
| 123 "</head></html>"); | 125 "</head></html>"); |
| 124 ExpectTranslationAllowed(NO); | 126 ExpectTranslationAllowed(NO); |
| 125 } | 127 } |
| 126 | 128 |
| 127 // Tests correctness of |document.documentElement.lang| attribute. | 129 // Tests correctness of |document.documentElement.lang| attribute. |
| 128 TEST_F(JsLanguageDetectionManagerTest, HtmlLang) { | 130 TEST_F(JsLanguageDetectionManagerTest, HtmlLang) { |
| 129 base::scoped_nsobject<NSString> html; | 131 NSString* html; |
| 130 // Non-empty attribute. | 132 // Non-empty attribute. |
| 131 html.reset([[NSString alloc] | 133 html = [[NSString alloc] |
| 132 initWithFormat:@"<html lang='%s'></html>", kExpectedLanguage]); | 134 initWithFormat:@"<html lang='%s'></html>", kExpectedLanguage]; |
| 133 LoadHtmlAndInject(html); | 135 LoadHtmlAndInject(html); |
| 134 ExpectHtmlLang(@(kExpectedLanguage)); | 136 ExpectHtmlLang(@(kExpectedLanguage)); |
| 135 | 137 |
| 136 // Empty attribute. | 138 // Empty attribute. |
| 137 LoadHtmlAndInject(@"<html></html>"); | 139 LoadHtmlAndInject(@"<html></html>"); |
| 138 ExpectHtmlLang(@""); | 140 ExpectHtmlLang(@""); |
| 139 | 141 |
| 140 // Test with mixed case. | 142 // Test with mixed case. |
| 141 html.reset([[NSString alloc] | 143 html = [[NSString alloc] |
| 142 initWithFormat:@"<html lAnG='%s'></html>", kExpectedLanguage]); | 144 initWithFormat:@"<html lAnG='%s'></html>", kExpectedLanguage]; |
| 143 LoadHtmlAndInject(html); | 145 LoadHtmlAndInject(html); |
| 144 ExpectHtmlLang(@(kExpectedLanguage)); | 146 ExpectHtmlLang(@(kExpectedLanguage)); |
| 145 } | 147 } |
| 146 | 148 |
| 147 // Tests |__gCrWeb.languageDetection.getMetaContentByHttpEquiv| JS call. | 149 // Tests |__gCrWeb.languageDetection.getMetaContentByHttpEquiv| JS call. |
| 148 TEST_F(JsLanguageDetectionManagerTest, HttpContentLanguage) { | 150 TEST_F(JsLanguageDetectionManagerTest, HttpContentLanguage) { |
| 149 // No content language. | 151 // No content language. |
| 150 LoadHtmlAndInject(@"<html></html>"); | 152 LoadHtmlAndInject(@"<html></html>"); |
| 151 ExpectHttpContentLanguage(@""); | 153 ExpectHttpContentLanguage(@""); |
| 152 base::scoped_nsobject<NSString> html; | 154 NSString* html; |
| 153 | 155 |
| 154 // Some content language. | 156 // Some content language. |
| 155 html.reset(([[NSString alloc] | 157 html = ([[NSString alloc] |
| 156 initWithFormat:@"<html><head>" | 158 initWithFormat:@"<html><head>" |
| 157 "<meta http-equiv='content-language' content='%s'>" | 159 "<meta http-equiv='content-language' content='%s'>" |
| 158 "</head></html>", | 160 "</head></html>", |
| 159 kExpectedLanguage])); | 161 kExpectedLanguage]); |
| 160 LoadHtmlAndInject(html); | 162 LoadHtmlAndInject(html); |
| 161 ExpectHttpContentLanguage(@(kExpectedLanguage)); | 163 ExpectHttpContentLanguage(@(kExpectedLanguage)); |
| 162 | 164 |
| 163 // Test with mixed case. | 165 // Test with mixed case. |
| 164 html.reset(([[NSString alloc] | 166 html = ([[NSString alloc] |
| 165 initWithFormat:@"<html><head>" | 167 initWithFormat:@"<html><head>" |
| 166 "<meta http-equiv='cOnTenT-lAngUAge' content='%s'>" | 168 "<meta http-equiv='cOnTenT-lAngUAge' content='%s'>" |
| 167 "</head></html>", | 169 "</head></html>", |
| 168 kExpectedLanguage])); | 170 kExpectedLanguage]); |
| 169 LoadHtmlAndInject(html); | 171 LoadHtmlAndInject(html); |
| 170 ExpectHttpContentLanguage(@(kExpectedLanguage)); | 172 ExpectHttpContentLanguage(@(kExpectedLanguage)); |
| 171 } | 173 } |
| 172 | 174 |
| 173 // Tests |__gCrWeb.languageDetection.getTextContent| JS call. | 175 // Tests |__gCrWeb.languageDetection.getTextContent| JS call. |
| 174 TEST_F(JsLanguageDetectionManagerTest, ExtractTextContent) { | 176 TEST_F(JsLanguageDetectionManagerTest, ExtractTextContent) { |
| 175 LoadHtmlAndInject(@"<html><body>" | 177 LoadHtmlAndInject(@"<html><body>" |
| 176 "<script>var text = 'No scripts!'</script>" | 178 "<script>var text = 'No scripts!'</script>" |
| 177 "<p style='display: none;'>Not displayed!</p>" | 179 "<p style='display: none;'>Not displayed!</p>" |
| 178 "<p style='visibility: hidden;'>Hidden!</p>" | 180 "<p style='visibility: hidden;'>Hidden!</p>" |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 212 "<ul><li>One</li><li>T<a href='foo'>wo</a></li></ul><p>Three</p>" | 214 "<ul><li>One</li><li>T<a href='foo'>wo</a></li></ul><p>Three</p>" |
| 213 "</body></html>"); | 215 "</body></html>"); |
| 214 ExpectTextContent(@"\n\nOne\nTwo\nThree"); | 216 ExpectTextContent(@"\n\nOne\nTwo\nThree"); |
| 215 } | 217 } |
| 216 | 218 |
| 217 // Tests that |__gCrWeb.languageDetection.getTextContent| returns only until the | 219 // Tests that |__gCrWeb.languageDetection.getTextContent| returns only until the |
| 218 // kMaxIndexChars number of characters even if the text content is very large. | 220 // kMaxIndexChars number of characters even if the text content is very large. |
| 219 TEST_F(JsLanguageDetectionManagerTest, LongTextContent) { | 221 TEST_F(JsLanguageDetectionManagerTest, LongTextContent) { |
| 220 // Very long string. | 222 // Very long string. |
| 221 NSUInteger kLongStringLength = language_detection::kMaxIndexChars - 5; | 223 NSUInteger kLongStringLength = language_detection::kMaxIndexChars - 5; |
| 222 base::scoped_nsobject<NSMutableString> long_string( | 224 NSMutableString* long_string = [GetLongString(kLongStringLength) mutableCopy]; |
| 223 [GetLongString(kLongStringLength) mutableCopy]); | |
| 224 [long_string appendString:@" b cdefghijklmnopqrstuvwxyz"]; | 225 [long_string appendString:@" b cdefghijklmnopqrstuvwxyz"]; |
| 225 | 226 |
| 226 // The string should be cut at the last whitespace, after the 'b' character. | 227 // The string should be cut at the last whitespace, after the 'b' character. |
| 227 base::scoped_nsobject<NSString> html([[NSString alloc] | 228 NSString* html = [[NSString alloc] |
| 228 initWithFormat:@"<html><body>%@</html></body>", long_string.get()]); | 229 initWithFormat:@"<html><body>%@</html></body>", long_string]; |
| 229 LoadHtmlAndInject(html); | 230 LoadHtmlAndInject(html); |
| 230 | 231 |
| 231 base::scoped_nsobject<NSString> script([[NSString alloc] | 232 NSString* script = [[NSString alloc] |
| 232 initWithFormat: | 233 initWithFormat: |
| 233 @"__gCrWeb.languageDetection.getTextContent(document.body, %lu);", | 234 @"__gCrWeb.languageDetection.getTextContent(document.body, %lu);", |
| 234 language_detection::kMaxIndexChars]); | 235 language_detection::kMaxIndexChars]; |
| 235 NSString* result = web::ExecuteJavaScript(manager_, script); | 236 NSString* result = web::ExecuteJavaScript(manager_, script); |
| 236 EXPECT_EQ(language_detection::kMaxIndexChars, [result length]); | 237 EXPECT_EQ(language_detection::kMaxIndexChars, [result length]); |
| 237 } | 238 } |
| 238 | 239 |
| 239 // Tests if |__gCrWeb.languageDetection.retrieveBufferedTextContent| correctly | 240 // Tests if |__gCrWeb.languageDetection.retrieveBufferedTextContent| correctly |
| 240 // retrieves the cache and then purges it. | 241 // retrieves the cache and then purges it. |
| 241 TEST_F(JsLanguageDetectionManagerTest, RetrieveBufferedTextContent) { | 242 TEST_F(JsLanguageDetectionManagerTest, RetrieveBufferedTextContent) { |
| 242 LoadHtmlAndInject(@"<html></html>"); | 243 LoadHtmlAndInject(@"<html></html>"); |
| 243 // Set some cached text content. | 244 // Set some cached text content. |
| 244 [manager_ executeJavaScript: | 245 [manager_ executeJavaScript: |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 344 | 345 |
| 345 EXPECT_TRUE(value->HasKey("translationAllowed")); | 346 EXPECT_TRUE(value->HasKey("translationAllowed")); |
| 346 EXPECT_TRUE(value->HasKey("captureTextTime")); | 347 EXPECT_TRUE(value->HasKey("captureTextTime")); |
| 347 EXPECT_TRUE(value->HasKey("htmlLang")); | 348 EXPECT_TRUE(value->HasKey("htmlLang")); |
| 348 EXPECT_TRUE(value->HasKey("httpContentLanguage")); | 349 EXPECT_TRUE(value->HasKey("httpContentLanguage")); |
| 349 | 350 |
| 350 bool translation_allowed = false; | 351 bool translation_allowed = false; |
| 351 value->GetBoolean("translationAllowed", &translation_allowed); | 352 value->GetBoolean("translationAllowed", &translation_allowed); |
| 352 EXPECT_TRUE(translation_allowed); | 353 EXPECT_TRUE(translation_allowed); |
| 353 } | 354 } |
| OLD | NEW |