From e9fdd159ffd94e3e097bd6905d84e6b564b04c2c Mon Sep 17 00:00:00 2001
From: "johnnyg@chromium.org"
 <johnnyg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>
Date: Wed, 9 Jun 2010 21:47:24 +0000
Subject: Properly escape user input for notifications, since URL-encoded
 characters are leaking through as HTML in non-HTML notifications.

BUG=45859
TEST=see bug

Review URL: http://codereview.chromium.org/2743007

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@49328 0039d316-1c4b-4281-b951-d872f2087c98
---
 .../notifications/desktop_notification_service.cc  | 22 +++++++++++-----------
 .../desktop_notifications_unittest.cc              |  5 ++++-
 2 files changed, 15 insertions(+), 12 deletions(-)

diff --git a/chrome/browser/notifications/desktop_notification_service.cc b/chrome/browser/notifications/desktop_notification_service.cc
index df61f2f..683af4e 100644
--- a/chrome/browser/notifications/desktop_notification_service.cc
+++ b/chrome/browser/notifications/desktop_notification_service.cc
@@ -43,24 +43,24 @@ string16 DesktopNotificationService::CreateDataUrl(
   int resource;
   string16 line_name;
   string16 line;
-  std::vector<string16> subst;
+  std::vector<std::string> subst;
   if (icon_url.is_valid()) {
     resource = IDR_NOTIFICATION_ICON_HTML;
-    subst.push_back(UTF8ToUTF16(icon_url.spec()));
-    subst.push_back(UTF8ToUTF16(EscapeForHTML(UTF16ToUTF8(title))));
-    subst.push_back(UTF8ToUTF16(EscapeForHTML(UTF16ToUTF8(body))));
+    subst.push_back(icon_url.spec());
+    subst.push_back(EscapeForHTML(UTF16ToUTF8(title)));
+    subst.push_back(EscapeForHTML(UTF16ToUTF8(body)));
   } else if (title.empty() || body.empty()) {
     resource = IDR_NOTIFICATION_1LINE_HTML;
     line = title.empty() ? body : title;
     // Strings are div names in the template file.
     line_name = title.empty() ? ASCIIToUTF16("description")
                               : ASCIIToUTF16("title");
-    subst.push_back(UTF8ToUTF16(EscapeForHTML(UTF16ToUTF8(line_name))));
-    subst.push_back(UTF8ToUTF16(EscapeForHTML(UTF16ToUTF8(line))));
+    subst.push_back(EscapeForHTML(UTF16ToUTF8(line_name)));
+    subst.push_back(EscapeForHTML(UTF16ToUTF8(line)));
   } else {
     resource = IDR_NOTIFICATION_2LINE_HTML;
-    subst.push_back(UTF8ToUTF16(EscapeForHTML(UTF16ToUTF8(title))));
-    subst.push_back(UTF8ToUTF16(EscapeForHTML(UTF16ToUTF8(body))));
+    subst.push_back(EscapeForHTML(UTF16ToUTF8(title)));
+    subst.push_back(EscapeForHTML(UTF16ToUTF8(body)));
   }
 
   const base::StringPiece template_html(
@@ -72,9 +72,9 @@ string16 DesktopNotificationService::CreateDataUrl(
     return string16();
   }
 
-  string16 format_string = ASCIIToUTF16("data:text/html;charset=utf-8,"
-                                        + template_html.as_string());
-  return ReplaceStringPlaceholders(format_string, subst, NULL);
+  std::string data = ReplaceStringPlaceholders(template_html, subst, NULL);
+  return UTF8ToUTF16("data:text/html;charset=utf-8," +
+                      EscapeQueryParamValue(data, false));
 }
 
 // A task object which calls the renderer to inform the web page that the
diff --git a/chrome/browser/notifications/desktop_notifications_unittest.cc b/chrome/browser/notifications/desktop_notifications_unittest.cc
index be7a6f6..5cd03c3 100644
--- a/chrome/browser/notifications/desktop_notifications_unittest.cc
+++ b/chrome/browser/notifications/desktop_notifications_unittest.cc
@@ -281,7 +281,7 @@ TEST_F(DesktopNotificationsTest, TestUserInputEscaping) {
       GURL("http://www.google.com"),
       GURL("/icon.png"),
       ASCIIToUTF16("<script>window.alert('uh oh');</script>"),
-      ASCIIToUTF16("<i>this text is in italics</i>"),
+      ASCIIToUTF16("<i>this text is in italics</i>, as is %3ci%3ethis%3c/i%3e"),
       0, 0, DesktopNotificationService::PageNotification, 1));
 
   MessageLoopForUI::current()->RunAllPending();
@@ -290,4 +290,7 @@ TEST_F(DesktopNotificationsTest, TestUserInputEscaping) {
   GURL data_url = balloon->notification().content_url();
   EXPECT_EQ(std::string::npos, data_url.spec().find("<script>"));
   EXPECT_EQ(std::string::npos, data_url.spec().find("<i>"));
+  // URL-encoded versions of tags should also not be found.
+  EXPECT_EQ(std::string::npos, data_url.spec().find("%3cscript%3e"));
+  EXPECT_EQ(std::string::npos, data_url.spec().find("%3ci%3e"));
 }
-- 
cgit v1.1