| OLD | NEW |
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 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 #include <vector> | 5 #include <vector> |
| 6 | 6 |
| 7 #import <CoreGraphics/CoreGraphics.h> | |
| 8 #import <Foundation/Foundation.h> | |
| 9 | |
| 10 #include "base/macros.h" | 7 #include "base/macros.h" |
| 11 #include "base/strings/stringprintf.h" | 8 #include "base/strings/stringprintf.h" |
| 12 #import "base/strings/sys_string_conversions.h" | 9 #include "base/strings/sys_string_conversions.h" |
| 13 #import "ios/web/public/test/web_test_with_web_state.h" | 10 #import "ios/web/public/test/web_test_with_web_state.h" |
| 14 #import "ios/web/public/web_state/ui/crw_web_view_proxy.h" | |
| 15 #import "ios/web/public/web_state/ui/crw_web_view_scroll_view_proxy.h" | |
| 16 #import "ios/web/public/web_state/web_state.h" | |
| 17 #include "testing/gtest/include/gtest/gtest.h" | 11 #include "testing/gtest/include/gtest/gtest.h" |
| 18 #import "testing/gtest_mac.h" | 12 #include "testing/gtest_mac.h" |
| 19 | 13 |
| 20 // Unit tests for ios/web/web_state/js/resources/core.js. | 14 // Unit tests for ios/web/web_state/js/resources/core.js. |
| 21 | 15 |
| 22 namespace { | 16 namespace { |
| 23 | 17 |
| 24 struct TestScriptAndExpectedValue { | 18 struct TestScriptAndExpectedValue { |
| 25 NSString* test_script; | 19 NSString* test_script; |
| 26 id expected_value; | 20 id expected_value; |
| 27 }; | 21 }; |
| 28 | 22 |
| 29 // Test coordinates and expected result for __gCrWeb.getElementFromPoint call. | |
| 30 struct TestCoordinatesAndExpectedValue { | |
| 31 TestCoordinatesAndExpectedValue(CGFloat x, CGFloat y, id expected_value) | |
| 32 : x(x), y(y), expected_value(expected_value) {} | |
| 33 CGFloat x = 0; | |
| 34 CGFloat y = 0; | |
| 35 id expected_value = nil; | |
| 36 }; | |
| 37 | |
| 38 } // namespace | 23 } // namespace |
| 39 | 24 |
| 40 namespace web { | 25 namespace web { |
| 41 | 26 |
| 42 // Test fixture to test core.js. | 27 // Test fixture to test core.js. |
| 43 class CoreJsTest : public web::WebTestWithWebState { | 28 typedef web::WebTestWithWebState CoreJsTest; |
| 44 protected: | |
| 45 // Verifies that __gCrWeb.getElementFromPoint returns |expected_value| for | |
| 46 // the given image |html|. | |
| 47 void ImageTesterHelper(NSString* html, NSDictionary* expected_value) { | |
| 48 NSString* page_content_template = | |
| 49 @"<html><body style='margin-left:10px;margin-top:10px;'>" | |
| 50 "<div style='width:100px;height:100px;'>" | |
| 51 " <p style='position:absolute;left:25px;top:25px;" | |
| 52 " width:50px;height:50px'>" | |
| 53 "%@" | |
| 54 " Chrome rocks!" | |
| 55 " </p></div></body></html>"; | |
| 56 NSString* page_content = | |
| 57 [NSString stringWithFormat:page_content_template, html]; | |
| 58 | |
| 59 TestCoordinatesAndExpectedValue test_data[] = { | |
| 60 // Point outside the document margins. | |
| 61 {0, 0, @{}}, | |
| 62 // Point inside the <p> element. | |
| 63 {20, 20, expected_value}, | |
| 64 // Point outside the <p> element. | |
| 65 {GetWebViewContentSize().width / 2, 50, @{}}, | |
| 66 }; | |
| 67 for (size_t i = 0; i < arraysize(test_data); i++) { | |
| 68 const TestCoordinatesAndExpectedValue& data = test_data[i]; | |
| 69 LoadHtml(page_content); | |
| 70 id result = ExecuteGetElementFromPointJavaScript(data.x, data.y); | |
| 71 EXPECT_NSEQ(data.expected_value, result) | |
| 72 << " in test " << i << ": (" << data.x << ", " << data.y << ")"; | |
| 73 } | |
| 74 } | |
| 75 // Returns web view's content size from the current web state. | |
| 76 CGSize GetWebViewContentSize() { | |
| 77 return web_state()->GetWebViewProxy().scrollViewProxy.contentSize; | |
| 78 } | |
| 79 | |
| 80 // Executes __gCrWeb.getElementFromPoint script and syncronously returns the | |
| 81 // result. |x| and |y| are points in web view coordinate system. | |
| 82 id ExecuteGetElementFromPointJavaScript(CGFloat x, CGFloat y) { | |
| 83 CGSize contentSize = GetWebViewContentSize(); | |
| 84 NSString* const script = [NSString | |
| 85 stringWithFormat:@"__gCrWeb.getElementFromPoint(%g, %g, %g, %g)", x, y, | |
| 86 contentSize.width, contentSize.height]; | |
| 87 return ExecuteJavaScript(script); | |
| 88 } | |
| 89 }; | |
| 90 | |
| 91 // Tests that __gCrWeb.getElementFromPoint function returns correct src. | |
| 92 TEST_F(CoreJsTest, GetImageUrlAtPoint) { | |
| 93 NSString* html = | |
| 94 @"<img id='foo' style='width:200;height:200;' src='file:///bogus'/>"; | |
| 95 NSDictionary* expected_value = @{ | |
| 96 @"src" : @"file:///bogus", | |
| 97 @"referrerPolicy" : @"default", | |
| 98 }; | |
| 99 ImageTesterHelper(html, expected_value); | |
| 100 } | |
| 101 | |
| 102 // Tests that __gCrWeb.getElementFromPoint function returns correct title. | |
| 103 TEST_F(CoreJsTest, GetImageTitleAtPoint) { | |
| 104 NSString* html = @"<img id='foo' title='Hello world!'" | |
| 105 "style='width:200;height:200;' src='file:///bogus'/>"; | |
| 106 NSDictionary* expected_value = @{ | |
| 107 @"src" : @"file:///bogus", | |
| 108 @"referrerPolicy" : @"default", | |
| 109 @"title" : @"Hello world!", | |
| 110 }; | |
| 111 ImageTesterHelper(html, expected_value); | |
| 112 } | |
| 113 | |
| 114 // Tests that __gCrWeb.getElementFromPoint function returns correct href. | |
| 115 TEST_F(CoreJsTest, GetLinkImageUrlAtPoint) { | |
| 116 NSString* html = | |
| 117 @"<a href='file:///linky'>" | |
| 118 "<img id='foo' style='width:200;height:200;' src='file:///bogus'/>" | |
| 119 "</a>"; | |
| 120 NSDictionary* expected_value = @{ | |
| 121 @"src" : @"file:///bogus", | |
| 122 @"referrerPolicy" : @"default", | |
| 123 @"href" : @"file:///linky", | |
| 124 }; | |
| 125 ImageTesterHelper(html, expected_value); | |
| 126 } | |
| 127 | |
| 128 TEST_F(CoreJsTest, TextAreaStopsProximity) { | |
| 129 NSString* html = | |
| 130 @"<html><body style='margin-left:10px;margin-top:10px;'>" | |
| 131 "<div style='width:100px;height:100px;'>" | |
| 132 "<img id='foo'" | |
| 133 " style='position:absolute;left:0px;top:0px;width:50px;height:50px'" | |
| 134 " src='file:///bogus' />" | |
| 135 "<input type='text' name='name'" | |
| 136 " style='position:absolute;left:5px;top:5px; " | |
| 137 "width:40px;height:40px'/>" | |
| 138 "</div></body> </html>"; | |
| 139 | |
| 140 NSDictionary* success = @{ | |
| 141 @"src" : @"file:///bogus", | |
| 142 @"referrerPolicy" : @"default", | |
| 143 }; | |
| 144 NSDictionary* failure = @{}; | |
| 145 | |
| 146 TestCoordinatesAndExpectedValue test_data[] = { | |
| 147 {2, 20, success}, {10, 10, failure}, | |
| 148 }; | |
| 149 | |
| 150 for (size_t i = 0; i < arraysize(test_data); i++) { | |
| 151 const TestCoordinatesAndExpectedValue& data = test_data[i]; | |
| 152 LoadHtml(html); | |
| 153 id result = ExecuteGetElementFromPointJavaScript(data.x, data.y); | |
| 154 EXPECT_NSEQ(data.expected_value, result) | |
| 155 << " in test " << i << ": (" << data.x << ", " << data.y << ")"; | |
| 156 } | |
| 157 } | |
| 158 | 29 |
| 159 struct TestDataForPasswordFormDetection { | 30 struct TestDataForPasswordFormDetection { |
| 160 NSString* pageContent; | 31 NSString* pageContent; |
| 161 NSNumber* containsPassword; | 32 NSNumber* containsPassword; |
| 162 }; | 33 }; |
| 163 | 34 |
| 164 TEST_F(CoreJsTest, HasPasswordField) { | 35 TEST_F(CoreJsTest, HasPasswordField) { |
| 165 TestDataForPasswordFormDetection testData[] = { | 36 TestDataForPasswordFormDetection testData[] = { |
| 166 // Form without a password field. | 37 // Form without a password field. |
| 167 {@"<form><input type='text' name='password'></form>", @NO}, | 38 {@"<form><input type='text' name='password'></form>", @NO}, |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 250 // Load a sample HTML page. As a side-effect, loading HTML via | 121 // Load a sample HTML page. As a side-effect, loading HTML via |
| 251 // |webController_| will also inject core.js. | 122 // |webController_| will also inject core.js. |
| 252 LoadHtml(@"<p>"); | 123 LoadHtml(@"<p>"); |
| 253 id result = ExecuteJavaScript(data.test_script); | 124 id result = ExecuteJavaScript(data.test_script); |
| 254 EXPECT_NSEQ(data.expected_value, result) | 125 EXPECT_NSEQ(data.expected_value, result) |
| 255 << " in test " << i << ": " | 126 << " in test " << i << ": " |
| 256 << base::SysNSStringToUTF8(data.test_script); | 127 << base::SysNSStringToUTF8(data.test_script); |
| 257 } | 128 } |
| 258 } | 129 } |
| 259 | 130 |
| 260 // Tests the javascript of the url of the an image present in the DOM. | |
| 261 TEST_F(CoreJsTest, LinkOfImage) { | |
| 262 // A page with a large image surrounded by a link. | |
| 263 static const char image[] = | |
| 264 "<a href='%s'><img width=400 height=400 src='foo'></img></a>"; | |
| 265 | |
| 266 // A page with a link to a destination URL. | |
| 267 LoadHtml(base::StringPrintf(image, "http://destination")); | |
| 268 id result = ExecuteGetElementFromPointJavaScript(20, 20); | |
| 269 NSDictionary* expected_result = @{ | |
| 270 @"src" : [NSString stringWithFormat:@"%sfoo", BaseUrl().c_str()], | |
| 271 @"referrerPolicy" : @"default", | |
| 272 @"href" : @"http://destination/", | |
| 273 }; | |
| 274 EXPECT_NSEQ(expected_result, result); | |
| 275 | |
| 276 // A page with a link with some JavaScript that does not result in a NOP. | |
| 277 LoadHtml(base::StringPrintf(image, "javascript:console.log('whatever')")); | |
| 278 result = ExecuteGetElementFromPointJavaScript(20, 20); | |
| 279 expected_result = @{ | |
| 280 @"src" : [NSString stringWithFormat:@"%sfoo", BaseUrl().c_str()], | |
| 281 @"referrerPolicy" : @"default", | |
| 282 @"href" : @"javascript:console.log(", | |
| 283 }; | |
| 284 EXPECT_NSEQ(expected_result, result); | |
| 285 | |
| 286 // A list of JavaScripts that result in a NOP. | |
| 287 std::vector<std::string> nop_javascripts; | |
| 288 nop_javascripts.push_back(";"); | |
| 289 nop_javascripts.push_back("void(0);"); | |
| 290 nop_javascripts.push_back("void(0); void(0); void(0)"); | |
| 291 | |
| 292 for (auto js : nop_javascripts) { | |
| 293 // A page with a link with some JavaScript that results in a NOP. | |
| 294 const std::string javascript = std::string("javascript:") + js; | |
| 295 LoadHtml(base::StringPrintf(image, javascript.c_str())); | |
| 296 result = ExecuteGetElementFromPointJavaScript(20, 20); | |
| 297 expected_result = @{ | |
| 298 @"src" : [NSString stringWithFormat:@"%sfoo", BaseUrl().c_str()], | |
| 299 @"referrerPolicy" : @"default", | |
| 300 }; | |
| 301 // Make sure the returned JSON does not have an 'href' key. | |
| 302 EXPECT_NSEQ(expected_result, result); | |
| 303 } | |
| 304 } | |
| 305 | |
| 306 } // namespace web | 131 } // namespace web |
| OLD | NEW |