Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(817)

Side by Side Diff: chrome/browser/android/vr_shell/textures/url_bar_texture_unittest.cc

Issue 2945173006: VR: Enforce LTR directionality on rendered URL text. (Closed)
Patch Set: Add a test to ensure that a malicious RTL URL cannot spoof a hostname. Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/browser/android/vr_shell/textures/url_bar_texture.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 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 "chrome/browser/android/vr_shell/textures/url_bar_texture.h" 5 #include "chrome/browser/android/vr_shell/textures/url_bar_texture.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/macros.h" 8 #include "base/macros.h"
9 #include "base/memory/ptr_util.h" 9 #include "base/memory/ptr_util.h"
10 #include "base/strings/utf_string_conversions.h" 10 #include "base/strings/utf_string_conversions.h"
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
43 ~TestUrlBarTexture() override {} 43 ~TestUrlBarTexture() override {}
44 44
45 void DrawURL(const GURL& gurl) { 45 void DrawURL(const GURL& gurl) {
46 unsupported_mode_ = UiUnsupportedMode::kCount; 46 unsupported_mode_ = UiUnsupportedMode::kCount;
47 SetURL(gurl); 47 SetURL(gurl);
48 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul( 48 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(
49 texture_size_.width(), texture_size_.height()); 49 texture_size_.width(), texture_size_.height());
50 DrawAndLayout(surface->getCanvas(), texture_size_); 50 DrawAndLayout(surface->getCanvas(), texture_size_);
51 } 51 }
52 52
53 static void TestUrlStyling(const base::string16& formatted_url,
cjgrant 2017/06/23 16:02:52 This is unrelated to RTL; just cleanup to the publ
54 const url::Parsed& parsed,
55 security_state::SecurityLevel security_level,
56 vr_shell::RenderTextWrapper* render_text,
57 const ColorScheme& color_scheme) {
58 ApplyUrlStyling(formatted_url, parsed, security_level, render_text,
59 color_scheme);
60 }
61
53 void SetForceFontFallbackFailure(bool force) { 62 void SetForceFontFallbackFailure(bool force) {
54 SetForceFontFallbackFailureForTesting(force); 63 SetForceFontFallbackFailureForTesting(force);
55 } 64 }
56 65
57 size_t GetNumberOfFontFallbacksForURL(const GURL& gurl) { 66 size_t GetNumberOfFontFallbacksForURL(const GURL& gurl) {
58 url::Parsed parsed; 67 url::Parsed parsed;
59 const base::string16 text = url_formatter::FormatUrl( 68 const base::string16 text = url_formatter::FormatUrl(
60 gurl, url_formatter::kFormatUrlOmitAll, net::UnescapeRule::NORMAL, 69 gurl, url_formatter::kFormatUrlOmitAll, net::UnescapeRule::NORMAL,
61 &parsed, nullptr, nullptr); 70 &parsed, nullptr, nullptr);
62 71
63 gfx::FontList font_list; 72 gfx::FontList font_list;
64 if (!GetFontList(kUrlHeight, text, &font_list)) 73 if (!GetFontList(kUrlHeight, text, &font_list))
65 return 0; 74 return 0;
66 75
67 return font_list.GetFonts().size(); 76 return font_list.GetFonts().size();
68 } 77 }
69 78
70 // Reports the last unsupported mode that was encountered. Returns kCount if 79 // Reports the last unsupported mode that was encountered. Returns kCount if
71 // no unsupported mode was encountered. 80 // no unsupported mode was encountered.
72 UiUnsupportedMode unsupported_mode() const { return unsupported_mode_; } 81 UiUnsupportedMode unsupported_mode() const { return unsupported_mode_; }
73 82
83 gfx::RenderText* url_render_text() { return url_render_text_.get(); }
84 const base::string16& url_text() { return url_text_; }
85
74 private: 86 private:
75 void OnUnsupportedFeature(UiUnsupportedMode mode) { 87 void OnUnsupportedFeature(UiUnsupportedMode mode) {
76 unsupported_mode_ = mode; 88 unsupported_mode_ = mode;
77 } 89 }
78 90
79 gfx::Size texture_size_; 91 gfx::Size texture_size_;
80 gfx::Rect bounds_; 92 gfx::Rect bounds_;
81 UiUnsupportedMode unsupported_mode_ = UiUnsupportedMode::kCount; 93 UiUnsupportedMode unsupported_mode_ = UiUnsupportedMode::kCount;
82 }; 94 };
83 95
(...skipping 25 matching lines...) Expand all
109 protected: 121 protected:
110 void Verify(const std::string& url_string, 122 void Verify(const std::string& url_string,
111 SecurityLevel level, 123 SecurityLevel level,
112 const std::string& expected_string) { 124 const std::string& expected_string) {
113 GURL url(base::UTF8ToUTF16(url_string)); 125 GURL url(base::UTF8ToUTF16(url_string));
114 url::Parsed parsed; 126 url::Parsed parsed;
115 const base::string16 formatted_url = url_formatter::FormatUrl( 127 const base::string16 formatted_url = url_formatter::FormatUrl(
116 url, url_formatter::kFormatUrlOmitAll, net::UnescapeRule::NORMAL, 128 url, url_formatter::kFormatUrlOmitAll, net::UnescapeRule::NORMAL,
117 &parsed, nullptr, nullptr); 129 &parsed, nullptr, nullptr);
118 EXPECT_EQ(formatted_url, base::UTF8ToUTF16(expected_string)); 130 EXPECT_EQ(formatted_url, base::UTF8ToUTF16(expected_string));
119 UrlBarTexture::ApplyUrlStyling( 131 TestUrlBarTexture::TestUrlStyling(
120 formatted_url, parsed, level, &mock_, 132 formatted_url, parsed, level, &mock_,
121 ColorScheme::GetColorScheme(ColorScheme::kModeNormal)); 133 ColorScheme::GetColorScheme(ColorScheme::kModeNormal));
122 UrlBarTexture::ApplyUrlStyling( 134 TestUrlBarTexture::TestUrlStyling(
123 formatted_url, parsed, level, &mock_, 135 formatted_url, parsed, level, &mock_,
124 ColorScheme::GetColorScheme(ColorScheme::kModeIncognito)); 136 ColorScheme::GetColorScheme(ColorScheme::kModeIncognito));
125 } 137 }
126 138
127 testing::InSequence in_sequence_; 139 testing::InSequence in_sequence_;
128 MockRenderText mock_; 140 MockRenderText mock_;
129 }; 141 };
130 142
131 #if !defined(OS_LINUX) 143 #if !defined(OS_LINUX)
132 // TODO(crbug/731894): This test does not work on Linux. 144 // TODO(crbug/731894): This test does not work on Linux.
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
195 texture.DrawURL(GURL("https://foo.com")); 207 texture.DrawURL(GURL("https://foo.com"));
196 EXPECT_EQ(UiUnsupportedMode::kCount, texture.unsupported_mode()); 208 EXPECT_EQ(UiUnsupportedMode::kCount, texture.unsupported_mode());
197 texture.SetForceFontFallbackFailure(true); 209 texture.SetForceFontFallbackFailure(true);
198 texture.DrawURL(GURL("https://bar.com")); 210 texture.DrawURL(GURL("https://bar.com"));
199 EXPECT_EQ(UiUnsupportedMode::kUnhandledCodePoint, texture.unsupported_mode()); 211 EXPECT_EQ(UiUnsupportedMode::kUnhandledCodePoint, texture.unsupported_mode());
200 texture.SetForceFontFallbackFailure(false); 212 texture.SetForceFontFallbackFailure(false);
201 texture.DrawURL(GURL("https://baz.com")); 213 texture.DrawURL(GURL("https://baz.com"));
202 EXPECT_EQ(UiUnsupportedMode::kCount, texture.unsupported_mode()); 214 EXPECT_EQ(UiUnsupportedMode::kCount, texture.unsupported_mode());
203 } 215 }
204 216
205 TEST(UrlBarTextureTest, WillFailOnStrongRTLChar) { 217 TEST(UrlBarTextureTest, MaliciousRTLIsRenderedLTR) {
206 TestUrlBarTexture texture; 218 TestUrlBarTexture texture;
207 texture.DrawURL(GURL("https://ש.com")); 219
208 EXPECT_EQ(UiUnsupportedMode::kURLWithStrongRTLChars, 220 // Construct a malicious URL that attempts to spoof the hostname.
209 texture.unsupported_mode()); 221 const std::string real_host("127.0.0.1");
222 const std::string spoofed_host("attack.com");
223 const std::string url =
224 "http://" + real_host + "/ا/http://" + spoofed_host + "‬";
225
226 texture.DrawURL(GURL(base::UTF8ToUTF16(url)));
227
228 // Determine the logical character ranges of the legitimate and spoofed
229 // hostnames in the processed URL text.
230 base::string16 text = texture.url_text();
231 base::string16 real_16 = base::UTF8ToUTF16(real_host);
232 base::string16 spoofed_16 = base::UTF8ToUTF16(spoofed_host);
233 size_t position = text.find(real_16);
234 ASSERT_NE(position, base::string16::npos);
235 gfx::Range real_range(position, position + real_16.size());
236 position = text.find(spoofed_16);
237 ASSERT_NE(position, base::string16::npos);
238 gfx::Range spoofed_range(position, position + spoofed_16.size());
239
240 // Extract the pixel locations at which hostnames were actually rendered.
241 auto real_bounds =
242 texture.url_render_text()->GetSubstringBoundsForTesting(real_range);
243 auto spoofed_bounds =
244 texture.url_render_text()->GetSubstringBoundsForTesting(spoofed_range);
245 EXPECT_EQ(real_bounds.size(), 1u);
246 EXPECT_GE(spoofed_bounds.size(), 1u);
247
248 // Verify that any spoofed portion of the hostname has remained to the right
249 // of the legitimate hostname. This will fail if LTR directionality is not
250 // specified during URL rendering.
251 auto minimum_position = real_bounds[0].x() + real_bounds[0].width();
cjgrant 2017/06/23 16:02:53 If I remove the new LTR directionality setting ove
252 for (const auto& region : spoofed_bounds) {
253 EXPECT_GT(region.x(), minimum_position);
254 }
210 } 255 }
211 256
212 TEST(UrlBarTexture, ElisionIsAnUnsupportedMode) { 257 TEST(UrlBarTexture, ElisionIsAnUnsupportedMode) {
213 TestUrlBarTexture texture; 258 TestUrlBarTexture texture;
214 texture.DrawURL(GURL( 259 texture.DrawURL(GURL(
215 "https://" 260 "https://"
216 "thereisnopossiblewaythatthishostnamecouldbecontainedinthelimitedspacetha" 261 "thereisnopossiblewaythatthishostnamecouldbecontainedinthelimitedspacetha"
217 "tweareaffordedtousitsreallynotsomethingweshouldconsiderorplanfororpinour" 262 "tweareaffordedtousitsreallynotsomethingweshouldconsiderorplanfororpinour"
218 "hopesonlestwegetdisappointedor.sad.com")); 263 "hopesonlestwegetdisappointedor.sad.com"));
219 EXPECT_EQ(UiUnsupportedMode::kCouldNotElideURL, texture.unsupported_mode()); 264 EXPECT_EQ(UiUnsupportedMode::kCouldNotElideURL, texture.unsupported_mode());
220 } 265 }
221 266
222 TEST(UrlBarTexture, ShortURLAreIndeedSupported) { 267 TEST(UrlBarTexture, ShortURLAreIndeedSupported) {
223 TestUrlBarTexture texture; 268 TestUrlBarTexture texture;
224 texture.DrawURL(GURL("https://short.com/")); 269 texture.DrawURL(GURL("https://short.com/"));
225 EXPECT_EQ(UiUnsupportedMode::kCount, texture.unsupported_mode()); 270 EXPECT_EQ(UiUnsupportedMode::kCount, texture.unsupported_mode());
226 } 271 }
227 272
228 TEST(UrlBarTexture, LongPathsDoNotRequireElisionAndAreSupported) { 273 TEST(UrlBarTexture, LongPathsDoNotRequireElisionAndAreSupported) {
229 TestUrlBarTexture texture; 274 TestUrlBarTexture texture;
230 texture.DrawURL(GURL( 275 texture.DrawURL(GURL(
231 "https://something.com/" 276 "https://something.com/"
232 "thereisnopossiblewaythatthishostnamecouldbecontainedinthelimitedspacetha" 277 "thereisnopossiblewaythatthishostnamecouldbecontainedinthelimitedspacetha"
233 "tweareaffordedtousitsreallynotsomethingweshouldconsiderorplanfororpinour" 278 "tweareaffordedtousitsreallynotsomethingweshouldconsiderorplanfororpinour"
234 "hopesonlestwegetdisappointedorsad.com")); 279 "hopesonlestwegetdisappointedorsad.com"));
235 EXPECT_EQ(UiUnsupportedMode::kCount, texture.unsupported_mode()); 280 EXPECT_EQ(UiUnsupportedMode::kCount, texture.unsupported_mode());
236 } 281 }
237 282
238 } // namespace vr_shell 283 } // namespace vr_shell
OLDNEW
« no previous file with comments | « chrome/browser/android/vr_shell/textures/url_bar_texture.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698