window.location.href and others needlessly decodes URI-encoded characters
authorarv@chromium.org <arv@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 6 Oct 2011 01:40:05 +0000 (01:40 +0000)
committerarv@chromium.org <arv@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 6 Oct 2011 01:40:05 +0000 (01:40 +0000)
https://bugs.webkit.org/show_bug.cgi?id=30225

Reviewed by Darin Adler.

Source/WebCore:

Don't decode KURL::path() and stop using KURL::deprecatedString() in Location methods.

This slightly changes how we parse data and javascript URLs (non hierarchical URLs) to
not encode so aggressively.

* fileapi/DOMFileSystemBase.cpp:
(WebCore::DOMFileSystemBase::crackFileSystemURL): Manually decode path()
* loader/FrameLoader.cpp:
(WebCore::FrameLoader::defaultObjectContentType): Manually decode path()
* page/Location.cpp:
(WebCore::Location::href): Use string() instead of deprecatedString()
* page/Location.h:
(WebCore::Location::toString): Inline call to href()
* platform/KURL.cpp:
(WebCore::KURL::path): Don't decode.
(WebCore::escapeAndAppendNonHierarchicalPart): Rename escapeAndAppendFragment to escapeAndAppendNonHierarchicalPart
                                               since this is now used for more than just fragments.
(WebCore::KURL::parse): Don't decode
* platform/KURLGoogle.cpp:
(WebCore::KURL::path): Remove out of date comment
* platform/qt/KURLQt.cpp:
(WebCore::KURL::fileSystemPath): Manually decode path()
* platform/win/ClipboardWin.cpp:
(WebCore::createGlobalHDropContent): Manually decode path()
* workers/WorkerLocation.cpp:
(WebCore::WorkerLocation::href): Use string() instead of deprecatedString()
* workers/WorkerLocation.h:
(WebCore::WorkerLocation::toString): Inline call to href()

Tools:

* DumpRenderTree/chromium/TestShell.cpp:
(normalizeLayoutTestURLInternal): Remove extra encode.

LayoutTests:

The path part of location.href and location.pathname are now not decoded and we keep percent escape sequences.

data and javascript URLs only encodes non ascii characters.

* fast/dom/anchor-origin-expected.txt:
* fast/dom/anchor-origin.html: Change to not use document.write since we don't want to output HTML.
* fast/history/history-back-initial-vs-final-url-expected.txt:
* fast/loader/subframe-navigate-during-main-frame-load-expected.txt:
* fast/url/file-http-base-expected.txt:
* fast/url/mailto-expected.txt:
* fast/url/script-tests/file-http-base.js:
* fast/url/script-tests/segments.js:
* fast/url/script-tests/standard-url.js:
* fast/url/segments-expected.txt:
* fast/url/segments-from-data-url-expected.txt:
* fast/url/segments.html: Use UTF-8
* fast/url/standard-url-expected.txt:
* http/tests/security/dataURL/xss-DENIED-from-data-url-in-foreign-domain-subframe-expected.txt:
* http/tests/security/dataURL/xss-DENIED-from-data-url-in-foreign-domain-window-open-expected.txt:
* http/tests/security/dataURL/xss-DENIED-from-data-url-sub-frame-2-level-expected.txt:
* http/tests/security/dataURL/xss-DENIED-from-data-url-sub-frame-expected.txt:
* http/tests/security/dataURL/xss-DENIED-from-data-url-sub-frame-to-data-url-sub-frame-expected.txt:
* http/tests/security/dataURL/xss-DENIED-from-data-url-to-data-url-expected.txt:
* http/tests/security/dataURL/xss-DENIED-from-javascript-url-window-open-expected.txt:
* http/tests/security/dataURL/xss-DENIED-to-data-url-from-data-url-expected.txt:
* http/tests/security/dataURL/xss-DENIED-to-data-url-in-foreign-domain-subframe-expected.txt:
* http/tests/security/dataURL/xss-DENIED-to-data-url-in-foreign-domain-subframe-location-change-expected.txt:
* http/tests/security/dataURL/xss-DENIED-to-data-url-in-foreign-domain-window-open-expected.txt:
* http/tests/security/dataURL/xss-DENIED-to-data-url-sub-frame-2-level-expected.txt:
* http/tests/security/dataURL/xss-DENIED-to-data-url-sub-frame-expected.txt:
* http/tests/security/dataURL/xss-DENIED-to-data-url-sub-frame-uppercase-expected.txt:
* http/tests/security/dataURL/xss-DENIED-to-data-url-window-open-expected.txt:
* platform/chromium-cg-mac/fast/url/standard-url-expected.txt:
* platform/chromium-linux/fast/url/standard-url-expected.txt:
* platform/chromium-mac/fast/url/standard-url-expected.txt:
* platform/chromium-win/fast/url/standard-url-expected.txt:
* platform/chromium/fast/dom/anchor-origin-expected.txt: Removed.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@96779 268f45cc-cd09-0410-ab3c-d52691b4dbfc

47 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/dom/anchor-origin-expected.txt
LayoutTests/fast/dom/anchor-origin.html
LayoutTests/fast/history/history-back-initial-vs-final-url-expected.txt
LayoutTests/fast/loader/subframe-navigate-during-main-frame-load-expected.txt
LayoutTests/fast/url/file-http-base-expected.txt
LayoutTests/fast/url/mailto-expected.txt
LayoutTests/fast/url/script-tests/file-http-base.js
LayoutTests/fast/url/script-tests/segments.js
LayoutTests/fast/url/script-tests/standard-url.js
LayoutTests/fast/url/segments-expected.txt
LayoutTests/fast/url/segments-from-data-url-expected.txt
LayoutTests/fast/url/segments.html
LayoutTests/fast/url/standard-url-expected.txt
LayoutTests/http/tests/security/dataURL/xss-DENIED-from-data-url-in-foreign-domain-subframe-expected.txt
LayoutTests/http/tests/security/dataURL/xss-DENIED-from-data-url-in-foreign-domain-window-open-expected.txt
LayoutTests/http/tests/security/dataURL/xss-DENIED-from-data-url-sub-frame-2-level-expected.txt
LayoutTests/http/tests/security/dataURL/xss-DENIED-from-data-url-sub-frame-expected.txt
LayoutTests/http/tests/security/dataURL/xss-DENIED-from-data-url-sub-frame-to-data-url-sub-frame-expected.txt
LayoutTests/http/tests/security/dataURL/xss-DENIED-from-data-url-to-data-url-expected.txt
LayoutTests/http/tests/security/dataURL/xss-DENIED-from-javascript-url-window-open-expected.txt
LayoutTests/http/tests/security/dataURL/xss-DENIED-to-data-url-from-data-url-expected.txt
LayoutTests/http/tests/security/dataURL/xss-DENIED-to-data-url-in-foreign-domain-subframe-expected.txt
LayoutTests/http/tests/security/dataURL/xss-DENIED-to-data-url-in-foreign-domain-subframe-location-change-expected.txt
LayoutTests/http/tests/security/dataURL/xss-DENIED-to-data-url-in-foreign-domain-window-open-expected.txt
LayoutTests/http/tests/security/dataURL/xss-DENIED-to-data-url-sub-frame-2-level-expected.txt
LayoutTests/http/tests/security/dataURL/xss-DENIED-to-data-url-sub-frame-expected.txt
LayoutTests/http/tests/security/dataURL/xss-DENIED-to-data-url-sub-frame-uppercase-expected.txt
LayoutTests/http/tests/security/dataURL/xss-DENIED-to-data-url-window-open-expected.txt
LayoutTests/platform/chromium-cg-mac/fast/url/standard-url-expected.txt
LayoutTests/platform/chromium-linux/fast/url/standard-url-expected.txt
LayoutTests/platform/chromium-mac/fast/url/standard-url-expected.txt
LayoutTests/platform/chromium-win/fast/url/standard-url-expected.txt
LayoutTests/platform/chromium/fast/dom/anchor-origin-expected.txt [deleted file]
Source/WebCore/ChangeLog
Source/WebCore/fileapi/DOMFileSystemBase.cpp
Source/WebCore/loader/FrameLoader.cpp
Source/WebCore/page/Location.cpp
Source/WebCore/page/Location.h
Source/WebCore/platform/KURL.cpp
Source/WebCore/platform/KURLGoogle.cpp
Source/WebCore/platform/qt/KURLQt.cpp
Source/WebCore/platform/win/ClipboardWin.cpp
Source/WebCore/workers/WorkerLocation.cpp
Source/WebCore/workers/WorkerLocation.h
Tools/ChangeLog
Tools/DumpRenderTree/chromium/TestShell.cpp

index dcc0e9e..2a252b6 100644 (file)
@@ -1,3 +1,48 @@
+2011-10-05  Erik Arvidsson  <arv@chromium.org>
+
+        window.location.href and others needlessly decodes URI-encoded characters
+        https://bugs.webkit.org/show_bug.cgi?id=30225
+
+        Reviewed by Darin Adler.
+
+        The path part of location.href and location.pathname are now not decoded and we keep percent escape sequences.
+
+        data and javascript URLs only encodes non ascii characters.
+
+        * fast/dom/anchor-origin-expected.txt:
+        * fast/dom/anchor-origin.html: Change to not use document.write since we don't want to output HTML.
+        * fast/history/history-back-initial-vs-final-url-expected.txt:
+        * fast/loader/subframe-navigate-during-main-frame-load-expected.txt:
+        * fast/url/file-http-base-expected.txt:
+        * fast/url/mailto-expected.txt:
+        * fast/url/script-tests/file-http-base.js:
+        * fast/url/script-tests/segments.js:
+        * fast/url/script-tests/standard-url.js:
+        * fast/url/segments-expected.txt:
+        * fast/url/segments-from-data-url-expected.txt:
+        * fast/url/segments.html: Use UTF-8
+        * fast/url/standard-url-expected.txt:
+        * http/tests/security/dataURL/xss-DENIED-from-data-url-in-foreign-domain-subframe-expected.txt:
+        * http/tests/security/dataURL/xss-DENIED-from-data-url-in-foreign-domain-window-open-expected.txt:
+        * http/tests/security/dataURL/xss-DENIED-from-data-url-sub-frame-2-level-expected.txt:
+        * http/tests/security/dataURL/xss-DENIED-from-data-url-sub-frame-expected.txt:
+        * http/tests/security/dataURL/xss-DENIED-from-data-url-sub-frame-to-data-url-sub-frame-expected.txt:
+        * http/tests/security/dataURL/xss-DENIED-from-data-url-to-data-url-expected.txt:
+        * http/tests/security/dataURL/xss-DENIED-from-javascript-url-window-open-expected.txt:
+        * http/tests/security/dataURL/xss-DENIED-to-data-url-from-data-url-expected.txt:
+        * http/tests/security/dataURL/xss-DENIED-to-data-url-in-foreign-domain-subframe-expected.txt:
+        * http/tests/security/dataURL/xss-DENIED-to-data-url-in-foreign-domain-subframe-location-change-expected.txt:
+        * http/tests/security/dataURL/xss-DENIED-to-data-url-in-foreign-domain-window-open-expected.txt:
+        * http/tests/security/dataURL/xss-DENIED-to-data-url-sub-frame-2-level-expected.txt:
+        * http/tests/security/dataURL/xss-DENIED-to-data-url-sub-frame-expected.txt:
+        * http/tests/security/dataURL/xss-DENIED-to-data-url-sub-frame-uppercase-expected.txt:
+        * http/tests/security/dataURL/xss-DENIED-to-data-url-window-open-expected.txt:
+        * platform/chromium-cg-mac/fast/url/standard-url-expected.txt:
+        * platform/chromium-linux/fast/url/standard-url-expected.txt:
+        * platform/chromium-mac/fast/url/standard-url-expected.txt:
+        * platform/chromium-win/fast/url/standard-url-expected.txt:
+        * platform/chromium/fast/dom/anchor-origin-expected.txt: Removed.
+
 2011-10-05  Tony Chang  <tony@chromium.org>
 
         force margin:auto to 0 in flex items
index f0a6704..c89e80b 100644 (file)
@@ -9,5 +9,5 @@ http://example.com/foo/bar => http://example.com
 https://example.com/ttt?ggg => https://example.com
 ftp://example.com/ttt?ggg => ftp://example.com
 file:///home/abarth => file://
-data:text/html,%3Cb%3Efoo%3C/b%3E => null
+data:text/html,<b>foo</b> => null
 
index 4b3483e..d5a07d5 100644 (file)
@@ -14,12 +14,26 @@ var cases = [
     "data:text/html,<b>foo</b>"
 ];
 
-for (var i = 0; i < cases.length; ++i)
-    document.write('<a href="' + cases[i] + '">Link</a><br>');
+window.onload = function(e)
+{
+    for (var i = 0; i < cases.length; ++i) {
+        var a = document.createElement('a');
+        a.href = cases[i];
+        a.textContent = 'Link';
+        document.body.appendChild(a);
+        document.body.appendChild(document.createElement('br'));
+    }
+
+    var s = '';
+    var elmts = document.getElementsByTagName('a');
+    for (var i = 0; i < elmts.length; ++i)
+        s += elmts[i].href + ' => ' + elmts[i].origin + '\n';
+
+    var pre = document.createElement('pre');
+    pre.textContent = s;
+    document.body.appendChild(pre);
+};
 
-var elmts = document.getElementsByTagName('a');
-for (var i = 0; i < elmts.length; ++i)
-    document.write(elmts[i].href + ' => ' + elmts[i].origin + '<br>');
 </script>
 </body>
 </html>
index 5872195..0b4fbc4 100644 (file)
@@ -18,5 +18,5 @@ final page contents
 ============== Back Forward List ==============
 curr->  (file test):fast/history/history-back-initial-vs-final-url.html  **nav target**
             (file test):fast/history/resources/frame-final-url.html (in frame "<!--framePath //<!--frame0-->-->")
-        data:text/html,%3Cscript%3Ealert(%22Going%20back.%22);history.back();%3C/script%3E  **nav target**
+        data:text/html,<script>alert("Going back.");history.back();</script>  **nav target**
 ===============================================
index a682eb0..4fb9981 100644 (file)
@@ -6,5 +6,5 @@ The iframe navigation should *not* result in a second back-history item being cr
 ============== Back Forward List ==============
         (file test):fast/loader/subframe-navigate-during-main-frame-load.html  **nav target**
 curr->  (file test):fast/loader/resources/subframe-navigate-during-main-frame-load2.html  **nav target**
-            data:text/html,%3Cbody%20onload=%22layoutTestController.notifyDone();%22%3E%3C/body%3E (in frame "subframe")
+            data:text/html,<body onload="layoutTestController.notifyDone();"></body> (in frame "subframe")
 ===============================================
index afd3131..f9169cd 100644 (file)
@@ -20,7 +20,8 @@ PASS canonicalize('file:///foo/bar.txt') is 'file:///foo/bar.txt'
 FAIL canonicalize('FILE:/\\/\\7:\\\\//foo\\bar.html') should be file://7:////foo/bar.html. Was file:////7:////foo/bar.html.
 PASS canonicalize('file:filer/home\\me') is 'file://filer/home/me'
 FAIL canonicalize('file:///C:/foo/../../../bar.html') should be file:///C:/bar.html. Was file:///bar.html.
-FAIL canonicalize('file:///C:/asdf#\xc2') should be file:///C:/asdf#�. Was file:///C:/asdf#%C2.
+FAIL canonicalize('file:///C:/asdf#\xc2') should be file:///C:/asdf#Â. Was file:///C:/asdf#%C2.
+FAIL canonicalize('file:///C:/asdf#Â') should be file:///C:/asdf#Â. Was file:///C:/asdf#%C2.
 PASS canonicalize('file:///home/me') is 'file:///home/me'
 FAIL canonicalize('file:c:\\foo\\bar.html') should be file:///c:/foo/bar.html. Was file://c:/foo/bar.html.
 FAIL canonicalize('file:c|//foo\\bar.html') should be file:///c%7C//foo/bar.html. Was file://c|//foo/bar.html.
index cd318f9..dc49e91 100644 (file)
@@ -8,7 +8,7 @@ PASS canonicalize('mailto:addr1@foo.com') is 'mailto:addr1@foo.com'
 PASS canonicalize('mailto:addr1         ') is 'mailto:addr1'
 PASS canonicalize('mailto:addr1?to=jon') is 'mailto:addr1?to=jon'
 PASS canonicalize('mailto:addr1,addr2') is 'mailto:addr1,addr2'
-FAIL canonicalize('mailto:addr1, addr2') should be mailto:addr1, addr2. Was mailto:addr1,%20addr2.
+PASS canonicalize('mailto:addr1, addr2') is 'mailto:addr1, addr2'
 PASS canonicalize('mailto:addr1%2caddr2') is 'mailto:addr1%2caddr2'
 PASS canonicalize('mailto:𐌀') is 'mailto:%F0%90%8C%80'
 PASS canonicalize('mailto:addr1?') is 'mailto:addr1?'
index ca9e734..00965b8 100644 (file)
@@ -36,7 +36,8 @@ cases = [
     // Make sure relative paths can't go above the "C:"
     ["file:///C:/foo/../../../bar.html", "file:///C:/bar.html"],
     // Busted refs shouldn't make the whole thing fail.
-    ["file:///C:/asdf#\\xc2", "file:///C:/asdf#\\xef\\xbf\\xbd"],
+    ["file:///C:/asdf#\\xc2", "file:///C:/asdf#\\xc2"],
+    ["file:///C:/asdf#\xc2", "file:///C:/asdf#\xc2"],
 
     // Unix-style paths
     ["file:///home/me", "file:///home/me"],
index a1e5dba..a83cb61 100644 (file)
@@ -1,6 +1,6 @@
 description("Test URL segmentation");
 
-cases = [ 
+cases = [
   // [URL, [SCHEME, HOST, PORT, PATH, QUERY, REF]]
   ["http://user:pass@foo:21/bar;par?b#c",    ["http:","foo","21","/bar;par","?b","#c"]],
   ["http:foo.com",                           ["http:","example.org","","/foo/foo.com","",""]],
@@ -91,7 +91,14 @@ cases = [
   ["wss:example.com/",                       ["wss:","example.com","","/","",""]],
   ["data:example.com/",                      ["data:","","","example.com/","",""]],
   ["javascript:example.com/",                ["javascript:","","","example.com/","",""]],
-  ["mailto:example.com/",                    ["mailto:","","","example.com/","",""]],  
+  ["mailto:example.com/",                    ["mailto:","","","example.com/","",""]],
+
+  ["/a/b/c",                                  ["http:","example.org","","/a/b/c","",""]],
+  ["/a/ /c",                                  ["http:","example.org","","/a/%20/c","",""]],
+  ["/a%2fc",                                  ["http:","example.org","","/a%2fc","",""]],
+  ["/a/%2f/c",                                ["http:","example.org","","/a/%2f/c","",""]],
+
+  ["#\u03B2",                                 ["http:","example.org","","/foo/bar","","#\u03B2"]],
 ];
 
 var originalBaseURL = canonicalize(".");
index 27afe76..5611faa 100644 (file)
@@ -1,8 +1,10 @@
 description("Canonicalization of standard URLs");
 
-cases = [ 
+cases = [
   ["http://www.google.com/foo?bar=baz#", "http://www.google.com/foo?bar=baz#"],
+  ["http://www.google.com/foo?bar=baz# \u00bb", "http://www.google.com/foo?bar=baz# \u00bb"],
   ["http://[www.google.com]/", "http://[www.google.com]/"],
+  ["http://www.google.com", "http://www.google.com/"],
   // Disabled because whitespace gets treated different in this API.
   // ["ht\ttp:@www.google.com:80/;p?#", "ht%09tp://www.google.com:80/;p?#"],
   ["http:////////user:@google.com:99?foo", "http://user@google.com:99/?foo"],
@@ -58,6 +60,9 @@ cases = [
   ["data:example.com/", "data:example.com/"],
   ["javascript:example.com/", "javascript:example.com/"],
   ["mailto:example.com/", "mailto:example.com/"],
+  // Escaping of non hierarchical URLs
+  ["javascript:alert(\\t 1 \\n\\r)", "javascript:alert( 1 )"],
+  ['javascript:alert(" \1 \u03B2 ")', 'javascript:alert(" %01 %CE%B2 ")'],
 ];
 
 for (var i = 0; i < cases.length; ++i) {
index 0e51a1a..76e49aa 100644 (file)
@@ -8,7 +8,7 @@ PASS segments('http:foo.com') is '["http:","example.org","","/foo/foo.com","",""
 PASS segments('\t   :foo.com   \n') is '["http:","example.org","","/foo/:foo.com","",""]'
 PASS segments(' foo.com  ') is '["http:","example.org","","/foo/foo.com","",""]'
 PASS segments('a:\t foo.com') is '["a:","",""," foo.com","",""]'
-FAIL segments('http://f:21/ b ? d # e ') should be ["http:","f","21","/%20b%20","?%20d%20","# e"]. Was ["http:","f","21","/ b ","?%20d%20","# e"].
+PASS segments('http://f:21/ b ? d # e ') is '["http:","f","21","/%20b%20","?%20d%20","# e"]'
 PASS segments('http://f:/c') is '["http:","f","","/c","",""]'
 PASS segments('http://f:0/c') is '["http:","f","0","/c","",""]'
 PASS segments('http://f:00000000000000/c') is '["http:","f","0","/c","",""]'
@@ -93,6 +93,11 @@ PASS segments('wss:example.com/') is '["wss:","example.com","","/","",""]'
 PASS segments('data:example.com/') is '["data:","","","example.com/","",""]'
 PASS segments('javascript:example.com/') is '["javascript:","","","example.com/","",""]'
 PASS segments('mailto:example.com/') is '["mailto:","","","example.com/","",""]'
+PASS segments('/a/b/c') is '["http:","example.org","","/a/b/c","",""]'
+PASS segments('/a/ /c') is '["http:","example.org","","/a/%20/c","",""]'
+PASS segments('/a%2fc') is '["http:","example.org","","/a%2fc","",""]'
+PASS segments('/a/%2f/c') is '["http:","example.org","","/a/%2f/c","",""]'
+FAIL segments('#β') should be ["http:","example.org","","/foo/bar","","#β"]. Was ["http:","example.org","","/foo/bar","","#%CE%B2"].
 PASS successfullyParsed is true
 
 TEST COMPLETE
index b4195a4..c64aefc 100644 (file)
@@ -8,7 +8,7 @@ PASS segments('http:foo.com') is '["http:","foo.com","","/","",""]'
 PASS segments('\t   :foo.com   \n') is '[":","","","","",""]'
 PASS segments(' foo.com  ') is '[":","","","","",""]'
 PASS segments('a:\t foo.com') is '["a:","",""," foo.com","",""]'
-FAIL segments('http://f:21/ b ? d # e ') should be ["http:","f","21","/%20b%20","?%20d%20","# e"]. Was ["http:","f","21","/ b ","?%20d%20","# e"].
+PASS segments('http://f:21/ b ? d # e ') is '["http:","f","21","/%20b%20","?%20d%20","# e"]'
 PASS segments('http://f:/c') is '["http:","f","","/c","",""]'
 PASS segments('http://f:0/c') is '["http:","f","0","/c","",""]'
 PASS segments('http://f:00000000000000/c') is '["http:","f","0","/c","",""]'
index 5cc2f82..96aa871 100644 (file)
@@ -1,6 +1,7 @@
-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<!DOCTYPE html>
 <html>
 <head>
+<meta charset="utf-8">
 <link rel="stylesheet" href="../js/resources/js-test-style.css">
 <script src="../js/resources/js-test-pre.js"></script>
 <script src="resources/utilities.js"></script>
index 99ba8bb..d274059 100644 (file)
@@ -4,7 +4,9 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
 
 
 PASS canonicalize('http://www.google.com/foo?bar=baz#') is 'http://www.google.com/foo?bar=baz#'
+FAIL canonicalize('http://www.google.com/foo?bar=baz# »') should be http://www.google.com/foo?bar=baz# ». Was http://www.google.com/foo?bar=baz# %BB.
 PASS canonicalize('http://[www.google.com]/') is 'http://[www.google.com]/'
+PASS canonicalize('http://www.google.com') is 'http://www.google.com/'
 FAIL canonicalize('http:////////user:@google.com:99?foo') should be http://user@google.com:99/?foo. Was http://////user:@google.com:99?foo.
 FAIL canonicalize('http://192.0x00A80001') should be http://192.168.0.1/. Was http://192.0x00A80001/.
 FAIL canonicalize('http://www/foo%2Ehtml') should be http://www/foo.html. Was http://www/foo%2Ehtml.
@@ -53,6 +55,8 @@ PASS canonicalize('wss:example.com/') is 'wss://example.com/'
 PASS canonicalize('data:example.com/') is 'data:example.com/'
 PASS canonicalize('javascript:example.com/') is 'javascript:example.com/'
 PASS canonicalize('mailto:example.com/') is 'mailto:example.com/'
+PASS canonicalize('javascript:alert(\t 1 \n\r)') is 'javascript:alert( 1 )'
+PASS canonicalize('javascript:alert(" \ 1 β ")') is 'javascript:alert(" %01 %CE%B2 ")'
 PASS successfullyParsed is true
 
 TEST COMPLETE
index ae4b61c..996069c 100644 (file)
@@ -1,4 +1,4 @@
-CONSOLE MESSAGE: line 1: Unsafe JavaScript attempt to access frame with URL http://127.0.0.1:8000/security/dataURL/xss-DENIED-from-data-url-in-foreign-domain-subframe.html from frame with URL data:text/html,%3Chtml%3E%3Chead%3E%3Cscript%3Ewindow.onload%20=%20function(){try%20{top.document.getElementById('accessMe').innerHTML%20=%20'FAIL:%20Cross%20frame%20access%20from%20a%20data:%20URL%20on%20a%20different%20domain%20was%20allowed';alert('FAIL:%20No%20exception%20thrown.');}%20catch%20(e)%20{alert('PASS:%20Exception%20thrown%20successfully.');}if%20(window.layoutTestController)layoutTestController.notifyDone();}%3C/script%3E%3C/head%3E%3Cbody%3E%3Cp%3EInner-inner%20iframe.%20This%20iframe%20(which%20is%20data:%20URL%20and%20whose%20parent%20is%20on%20a%20foreign%20domain)%20is%20the%20frame%20attempting%20to%20access%20the%20main%20frame.%20%20It%20should%20not%20have%20access%20to%20it.%3C/p%3E%3C/body%3E%3C/html%3E. Domains, protocols and ports must match.
+CONSOLE MESSAGE: line 1: Unsafe JavaScript attempt to access frame with URL http://127.0.0.1:8000/security/dataURL/xss-DENIED-from-data-url-in-foreign-domain-subframe.html from frame with URL data:text/html,<html><head><script>window.onload = function(){try {top.document.getElementById('accessMe').innerHTML = 'FAIL: Cross frame access from a data: URL on a different domain was allowed';alert('FAIL: No exception thrown.');} catch (e) {alert('PASS: Exception thrown successfully.');}if (window.layoutTestController)layoutTestController.notifyDone();}</script></head><body><p>Inner-inner iframe. This iframe (which is data: URL and whose parent is on a foreign domain) is the frame attempting to access the main frame.  It should not have access to it.</p></body></html>. Domains, protocols and ports must match.
 
 ALERT: PASS: Exception thrown successfully.
 The scenario for this test is that you have an iframe with content from a foreign domain. In that foreign content is an iframe which loads a data: URL. This tests that the data: URL loaded iframe does not have access to the main frame using top.document.
index edadf4e..e280d91 100644 (file)
@@ -1,4 +1,4 @@
-CONSOLE MESSAGE: line 1: Unsafe JavaScript attempt to access frame with URL http://127.0.0.1:8000/security/dataURL/xss-DENIED-from-data-url-in-foreign-domain-window-open.html from frame with URL data:text/html,%3Chtml%3E%3Chead%3E%3Cscript%3Ewindow.onload%20=%20function(){try%20{parent.opener.document.getElementById('accessMe').innerHTML%20=%20'FAIL:%20Cross%20frame%20access%20from%20a%20data:%20URL%20on%20a%20different%20domain%20was%20allowed';alert('FAIL:%20No%20exception%20thrown.');}%20catch%20(e)%20{alert('PASS:%20Exception%20thrown%20successfully.');}if%20(window.layoutTestController)layoutTestController.globalFlag%20=%20true;}%3C/script%3E%3C/head%3E%3Cbody%3E%3Cp%3EInner-inner%20iframe.%20This%20iframe%20(which%20is%20data:%20URL%20and%20whose%20parent%20is%20on%20a%20foreign%20domain)%20is%20the%20frame%20attempting%20to%20access%20the%20main%20frame.%20%20It%20should%20not%20have%20access%20to%20it.%3C/p%3E%3C/body%3E%3C/html%3E. Domains, protocols and ports must match.
+CONSOLE MESSAGE: line 1: Unsafe JavaScript attempt to access frame with URL http://127.0.0.1:8000/security/dataURL/xss-DENIED-from-data-url-in-foreign-domain-window-open.html from frame with URL data:text/html,<html><head><script>window.onload = function(){try {parent.opener.document.getElementById('accessMe').innerHTML = 'FAIL: Cross frame access from a data: URL on a different domain was allowed';alert('FAIL: No exception thrown.');} catch (e) {alert('PASS: Exception thrown successfully.');}if (window.layoutTestController)layoutTestController.globalFlag = true;}</script></head><body><p>Inner-inner iframe. This iframe (which is data: URL and whose parent is on a foreign domain) is the frame attempting to access the main frame.  It should not have access to it.</p></body></html>. Domains, protocols and ports must match.
 
 ALERT: PASS: Exception thrown successfully.
 Opener Frame
index 7cbdba2..0afc516 100644 (file)
@@ -1,4 +1,4 @@
-CONSOLE MESSAGE: line 1: Unsafe JavaScript attempt to access frame with URL http://127.0.0.1:8000/security/dataURL/xss-DENIED-from-data-url-sub-frame-2-level.html from frame with URL data:text/html,%3Chtml%3E%3Chead%3E%3Cscript%3Efunction%20test()%20{try%20{top.document.getElementById(%22accessMe%22).innerHTML%20=%20%22FAIL:%20Cross%20frame%20access%20from%20a%20data:%20URL%20inside%20another%20data:%20URL%20was%20allowed.%22;}%20catch%20(e)%20{}if%20(window.layoutTestController)layoutTestController.notifyDone();}%3C/script%3E%3C/head%3E%3Cbody%20onload=%22test();%22%3E%3Cp%3EInner-inner%20iframe.%3C/p%3E%3C/body%3E%3C/html%3E. Domains, protocols and ports must match.
+CONSOLE MESSAGE: line 1: Unsafe JavaScript attempt to access frame with URL http://127.0.0.1:8000/security/dataURL/xss-DENIED-from-data-url-sub-frame-2-level.html from frame with URL data:text/html,<html><head><script>function test() {try {top.document.getElementById("accessMe").innerHTML = "FAIL: Cross frame access from a data: URL inside another data: URL was allowed.";} catch (e) {}if (window.layoutTestController)layoutTestController.notifyDone();}</script></head><body onload="test();"><p>Inner-inner iframe.</p></body></html>. Domains, protocols and ports must match.
 
 This tests that a data: URL loaded in an iframe inside another data: URL loaded iframe doesn't have access to the main frame.
 
index ae07831..9d340d4 100644 (file)
@@ -1,4 +1,4 @@
-CONSOLE MESSAGE: line 1: Unsafe JavaScript attempt to access frame with URL http://127.0.0.1:8000/security/dataURL/xss-DENIED-from-data-url-sub-frame.html from frame with URL data:text/html,%3Chtml%3E%3Chead%3E%3Cscript%3Efunction%20test()%20{try%20{parent.document.getElementById('accessMe').innerHTML%20=%20'FAIL:%20Cross%20frame%20access%20from%20a%20data:%20URL%20was%20allowed.';}%20catch%20(e)%20{}if%20(window.layoutTestController)layoutTestController.notifyDone();}%3C/script%3E%3C/head%3E%3Cbody%20onload=%22test()%22%3E%3Cp%3EInner%20iframe.%3C/p%3E%3C/body%3E%3C/html%3E. Domains, protocols and ports must match.
+CONSOLE MESSAGE: line 1: Unsafe JavaScript attempt to access frame with URL http://127.0.0.1:8000/security/dataURL/xss-DENIED-from-data-url-sub-frame.html from frame with URL data:text/html,<html><head><script>function test() {try {parent.document.getElementById('accessMe').innerHTML = 'FAIL: Cross frame access from a data: URL was allowed.';} catch (e) {}if (window.layoutTestController)layoutTestController.notifyDone();}</script></head><body onload="test()"><p>Inner iframe.</p></body></html>. Domains, protocols and ports must match.
 
 This tests that a data: URL loaded in an iframe doesn't have access to its parent's frame
 
index f0319f6..8a65079 100644 (file)
@@ -1,4 +1,4 @@
-CONSOLE MESSAGE: line 1: Unsafe JavaScript attempt to access frame with URL data:text/html,%3Chtml%3E%3Chead%3E%3Cscript%3Efunction%20fireSentinel()%20{if%20(window.layoutTestController)layoutTestController.globalFlag%20=%20true;}%3C/script%3E%3C/head%3E%3Cbody%20onload=%22fireSentinel();%22%3E%3Cp%3EInner%20iframe.%3C/p%3E%3Cp%20id='accessMe'%3EPass:%20Cross%20frame%20access%20from%20a%20sibling%20data:%20URL%20was%20denied.%3C/p%3E%3C/body%3E%3C/html%3E from frame with URL data:text/html,%3Chtml%3E%3Chead%3E%3Cscript%3Efunction%20loaded()%20{if%20(window.layoutTestController)%20{setTimeout(waitForFlag,%201);function%20waitForFlag()%20{if%20(!layoutTestController.globalFlag)%20{setTimeout(waitForFlag,%201);return;}performTest();}}%20else%20{document.getElementById('console').innerHTML%20=%20'Click%20the%20button%20when%20all%20the%20subframes%20have%20finished%20loading.';}}function%20performTest()%20{try%20{parent.frames['firstSubFrame'].document.getElementById('accessMe').innerHTML%20=%20'FAIL:%20Cross%20frame%20access%20from%20a%20sibling%20data:%20URL%20was%20allowed.';}%20catch%20(e)%20{}if%20(window.layoutTestController)layoutTestController.notifyDone();}%3C/script%3E%3C/head%3E%3Cbody%20onload=%22loaded();%22%3E%3Cp%3EInner%20iframe.%3C/p%3E%3Cbutton%20onclick='performTest();'%3ETest%3C/button%3E%3Cpre%20id='console'%3E%3C/pre%3E%3C/body%3E%3C/html%3E. Domains, protocols and ports must match.
+CONSOLE MESSAGE: line 1: Unsafe JavaScript attempt to access frame with URL data:text/html,<html><head><script>function fireSentinel() {if (window.layoutTestController)layoutTestController.globalFlag = true;}</script></head><body onload="fireSentinel();"><p>Inner iframe.</p><p id='accessMe'>Pass: Cross frame access from a sibling data: URL was denied.</p></body></html> from frame with URL data:text/html,<html><head><script>function loaded() {if (window.layoutTestController) {setTimeout(waitForFlag, 1);function waitForFlag() {if (!layoutTestController.globalFlag) {setTimeout(waitForFlag, 1);return;}performTest();}} else {document.getElementById('console').innerHTML = 'Click the button when all the subframes have finished loading.';}}function performTest() {try {parent.frames['firstSubFrame'].document.getElementById('accessMe').innerHTML = 'FAIL: Cross frame access from a sibling data: URL was allowed.';} catch (e) {}if (window.layoutTestController)layoutTestController.notifyDone();}</script></head><body onload="loaded();"><p>Inner iframe.</p><button onclick='performTest();'>Test</button><pre id='console'></pre></body></html>. Domains, protocols and ports must match.
 
 This tests that a data: URL subframe can't access a sibling data: URL subframe.
 
index 7e85bd5..42af3f2 100644 (file)
@@ -1,4 +1,4 @@
-CONSOLE MESSAGE: line 1: Unsafe JavaScript attempt to access frame with URL data:text/html,%3Chtml%3E%3Chead%3E%3Cscript%3Efunction%20fireSentinel()%20{if%20(window.layoutTestController)layoutTestController.globalFlag%20=%20true;}%3C/script%3E%3C/head%3E%3Cbody%20onload=%22fireSentinel();%22%3E%3Cp%20id=%22accessMe%22%3EPASS:%20Cross%20frame%20access%20from%20a%20data:%20URL%20was%20denied.%3C/p%3E%3Cp%3EInner-inner%20iframe.%3C/p%3E%3C/body%3E%3C/html%3E from frame with URL data:text/html,%3Chtml%3E%3Chead%3E%3Cscript%3Efunction%20loaded()%20{var%20iframe%20=%20document.getElementById('inner');iframe.src%20=%20'data:text/html,%3Chtml%3E%3Chead%3E%3Cscr'%20+%20'ipt%3Efunction%20fireSentinel()%20{if%20(window.layoutTestController)layoutTestController.globalFlag%20=%20true;}%3C/scr'%20+%20'ipt%3E%3C/head%3E%3Cbody%20onload=%22fireSentinel();%22%3E%3Cp%20id=%22accessMe%22%3EPASS:%20Cross%20frame%20access%20from%20a%20data:%20URL%20was%20denied.%3C/p%3E%3Cp%3EInner-inner%20iframe.%3C/p%3E%3C/body%3E%3C/html%3E';if%20(window.layoutTestController)%20{setTimeout(waitForFlag,%201);function%20waitForFlag()%20{if%20(!layoutTestController.globalFlag)%20{setTimeout(waitForFlag,%201);return;}performTest();}}%20else%20{document.getElementById('console').innerHTML%20=%20'Click%20the%20button%20when%20all%20the%20subframes%20have%20finished%20loading.';}}function%20performTest()%20{try%20{frames[0].document.getElementById('accessMe').innerHTML%20=%20'FAIL:%20Cross%20frame%20access%20from%20a%20data:%20URL%20was%20allowed.';}%20catch%20(e)%20{}if%20(window.layoutTestController)layoutTestController.notifyDone();}%3C/script%3E%3C/head%3E%3Cbody%20onload='loaded();'%3E%3Ciframe%20id='inner'%3E%3C/iframe%3E%3Cp%3EInner%20iframe.%3C/p%3E%3Cbutton%20onclick='performTest();'%3ETest%3C/button%3E%3Cpre%20id='console'%3E%3C/pre%3E%3C/body%3E%3C/html%3E. Domains, protocols and ports must match.
+CONSOLE MESSAGE: line 1: Unsafe JavaScript attempt to access frame with URL data:text/html,<html><head><script>function fireSentinel() {if (window.layoutTestController)layoutTestController.globalFlag = true;}</script></head><body onload="fireSentinel();"><p id="accessMe">PASS: Cross frame access from a data: URL was denied.</p><p>Inner-inner iframe.</p></body></html> from frame with URL data:text/html,<html><head><script>function loaded() {var iframe = document.getElementById('inner');iframe.src = 'data:text/html,<html><head><scr' + 'ipt>function fireSentinel() {if (window.layoutTestController)layoutTestController.globalFlag = true;}</scr' + 'ipt></head><body onload="fireSentinel();"><p id="accessMe">PASS: Cross frame access from a data: URL was denied.</p><p>Inner-inner iframe.</p></body></html>';if (window.layoutTestController) {setTimeout(waitForFlag, 1);function waitForFlag() {if (!layoutTestController.globalFlag) {setTimeout(waitForFlag, 1);return;}performTest();}} else {document.getElementById('console').innerHTML = 'Click the button when all the subframes have finished loading.';}}function performTest() {try {frames[0].document.getElementById('accessMe').innerHTML = 'FAIL: Cross frame access from a data: URL was allowed.';} catch (e) {}if (window.layoutTestController)layoutTestController.notifyDone();}</script></head><body onload='loaded();'><iframe id='inner'></iframe><p>Inner iframe.</p><button onclick='performTest();'>Test</button><pre id='console'></pre></body></html>. Domains, protocols and ports must match.
 
 This tests that a data: URL subframe can't access a child data: URL subframe of itself.
 
index 727819b..d24c947 100644 (file)
@@ -1,4 +1,4 @@
-CONSOLE MESSAGE: line 1: Unsafe JavaScript attempt to access frame with URL http://127.0.0.1:8000/security/dataURL/xss-DENIED-from-javascript-url-window-open.html from frame with URL data:text/html,%3Chtml%3E%3Chead%3E%3Cscript%3Efunction%20test()%20{try%20{opener.document.getElementById(%22accessMe%22).innerHTML%20=%20%22FAIL:%20Access%20from%20a%20window%20opened%20with%20a%20data:%20URL%20was%20allowed!%22;}%20catch%20(e)%20{}if%20(window.layoutTestController)layoutTestController.globalFlag%20=%20true;}%3C/script%3E%3C/head%3E%3Cbody%20onload=%22test();%22%3E%3Cp%3EOpened%20Frame.%3C/p%3E%3C/body%3E%3C/html%3E. Domains, protocols and ports must match.
+CONSOLE MESSAGE: line 1: Unsafe JavaScript attempt to access frame with URL http://127.0.0.1:8000/security/dataURL/xss-DENIED-from-javascript-url-window-open.html from frame with URL data:text/html,<html><head><script>function test() {try {opener.document.getElementById("accessMe").innerHTML = "FAIL: Access from a window opened with a data: URL was allowed!";} catch (e) {}if (window.layoutTestController)layoutTestController.globalFlag = true;}</script></head><body onload="test();"><p>Opened Frame.</p></body></html>. Domains, protocols and ports must match.
 
 Opener Frame
 
index fc6189a..598be9c 100644 (file)
@@ -1,4 +1,4 @@
-CONSOLE MESSAGE: line 1: Unsafe JavaScript attempt to access frame with URL data:text/html,%3Chtml%3E%3Cbody%3E%3Cp%20id='accessMe'%3EPASS:%20Cross%20frame%20access%20from%20a%20data:%20URL%20was%20denied.%3C/p%3E%3Cp%3EInner%20iframe.%3C/p%3E%3Ciframe%20name='innerFrame'%20id='innerFrame'%20src='data:text/html,%3Chtml%3E%3Chead%3E%3Cscript%3Efunction%20test()%20{try%20{parent.document.getElementById(%22accessMe%22).innerHTML%20=%20%22FAIL:%20Cross%20frame%20access%20from%20a%20data:%20URL%20was%20allowed.%22;}%20catch%20(e)%20{}if%20(window.layoutTestController)layoutTestController.notifyDone();}%3C/script%3E%3C/head%3E%3Cbody%20onload=%22test();%22%3E%3Cp%3EInner-inner%20iframe.%3C/p%3E%3C/body%3E%3C/html%3E'%3E%3C/iframe%3E%3C/body%3E%3C/html%3E from frame with URL data:text/html,%3Chtml%3E%3Chead%3E%3Cscript%3Efunction%20test()%20{try%20{parent.document.getElementById(%22accessMe%22).innerHTML%20=%20%22FAIL:%20Cross%20frame%20access%20from%20a%20data:%20URL%20was%20allowed.%22;}%20catch%20(e)%20{}if%20(window.layoutTestController)layoutTestController.notifyDone();}%3C/script%3E%3C/head%3E%3Cbody%20onload=%22test();%22%3E%3Cp%3EInner-inner%20iframe.%3C/p%3E%3C/body%3E%3C/html%3E. Domains, protocols and ports must match.
+CONSOLE MESSAGE: line 1: Unsafe JavaScript attempt to access frame with URL data:text/html,<html><body><p id='accessMe'>PASS: Cross frame access from a data: URL was denied.</p><p>Inner iframe.</p><iframe name='innerFrame' id='innerFrame' src='data:text/html,<html><head><script>function test() {try {parent.document.getElementById("accessMe").innerHTML = "FAIL: Cross frame access from a data: URL was allowed.";} catch (e) {}if (window.layoutTestController)layoutTestController.notifyDone();}</script></head><body onload="test();"><p>Inner-inner iframe.</p></body></html>'></iframe></body></html> from frame with URL data:text/html,<html><head><script>function test() {try {parent.document.getElementById("accessMe").innerHTML = "FAIL: Cross frame access from a data: URL was allowed.";} catch (e) {}if (window.layoutTestController)layoutTestController.notifyDone();}</script></head><body onload="test();"><p>Inner-inner iframe.</p></body></html>. Domains, protocols and ports must match.
 
 This tests that a data: URL loaded in an iframe inside another data: URL loaded iframe doesn't have access to its parent, the first data: URL loaded iframe.
 
index 76fbddc..8e32580 100644 (file)
@@ -1,4 +1,4 @@
-CONSOLE MESSAGE: line 1: Unsafe JavaScript attempt to access frame with URL data:text/html,%3Chtml%3E%3Chead%3E%3Cscript%3Efunction%20loaded()%20{if%20(window.layoutTestController)layoutTestController.globalFlag%20=%20true;}%3C/script%3E%3C/head%3E%3Cbody%20onload='loaded();'%3E%3Cp%20id='accessMe'%3EPASS:%20Cross%20frame%20access%20from%20a%20frame%20on%20a%20foreign%20domain%20denied!%3C/p%3E%3Cp%3EInner-inner%20iframe.%20This%20iframe%20(which%20is%20data:%20URL%20and%20whose%20parent%20is%20on%20a%20foreign%20domain)%20is%20the%20frame%20that%20the%20main%20frame%20is%20trying%20to%20access.%20%20It%20should%20not%20have%20access%20to%20it.%3C/p%3E%3C/body%3E%3C/html%3E from frame with URL http://127.0.0.1:8000/security/dataURL/xss-DENIED-to-data-url-in-foreign-domain-subframe.html. Domains, protocols and ports must match.
+CONSOLE MESSAGE: line 1: Unsafe JavaScript attempt to access frame with URL data:text/html,<html><head><script>function loaded() {if (window.layoutTestController)layoutTestController.globalFlag = true;}</script></head><body onload='loaded();'><p id='accessMe'>PASS: Cross frame access from a frame on a foreign domain denied!</p><p>Inner-inner iframe. This iframe (which is data: URL and whose parent is on a foreign domain) is the frame that the main frame is trying to access.  It should not have access to it.</p></body></html> from frame with URL http://127.0.0.1:8000/security/dataURL/xss-DENIED-to-data-url-in-foreign-domain-subframe.html. Domains, protocols and ports must match.
 
 The scenario for this test is that you have an iframe with content from a foreign domain. In that foreign content is an iframe which loads a data: URL. This tests that this main document does not have access to that data: URL loaded iframe.
 
index 52f9b75..4dde727 100644 (file)
@@ -1,4 +1,4 @@
-CONSOLE MESSAGE: line 1: Unsafe JavaScript attempt to access frame with URL data:text/html,%3Chtml%3E%3Chead%3E%3Cscript%3Efunction%20loaded()%20{if%20(window.layoutTestController)layoutTestController.globalFlag%20=%20true;}%3C/script%3E%3C/head%3E%3Cbody%20onload='loaded();'%3E%3Cp%20id='accessMe'%3EPASS:%20Cross%20frame%20access%20from%20a%20frame%20on%20a%20foreign%20domain%20denied!%3C/p%3E%3Cp%3EInner%20iframe.%20This%20iframe%20(which%20is%20data:%20URL%20and%20whose%20parent%20is%20on%20a%20foreign%20domain)%20is%20the%20frame%20that%20the%20main%20frame%20is%20trying%20to%20access.%20%20It%20should%20not%20have%20access%20to%20it.%3C/p%3E%3C/body%3E%3C/html%3E from frame with URL http://127.0.0.1:8000/security/dataURL/xss-DENIED-to-data-url-in-foreign-domain-subframe-location-change.html. Domains, protocols and ports must match.
+CONSOLE MESSAGE: line 1: Unsafe JavaScript attempt to access frame with URL data:text/html,<html><head><script>function loaded() {if (window.layoutTestController)layoutTestController.globalFlag = true;}</script></head><body onload='loaded();'><p id='accessMe'>PASS: Cross frame access from a frame on a foreign domain denied!</p><p>Inner iframe. This iframe (which is data: URL and whose parent is on a foreign domain) is the frame that the main frame is trying to access.  It should not have access to it.</p></body></html> from frame with URL http://127.0.0.1:8000/security/dataURL/xss-DENIED-to-data-url-in-foreign-domain-subframe-location-change.html. Domains, protocols and ports must match.
 
 Opener frame
 
index 0b45abb..87b7a31 100644 (file)
@@ -1,4 +1,4 @@
-CONSOLE MESSAGE: line 1: Unsafe JavaScript attempt to access frame with URL data:text/html,%3Chtml%3E%3Chead%3E%3Cscript%3Efunction%20loaded()%20{if%20(window.layoutTestController)layoutTestController.globalFlag%20=%20true;}%3C/script%3E%3C/head%3E%3Cbody%20onload='loaded();'%3E%3Cp%20id='accessMe'%3EPASS:%20Access%20from%20the%20main%20frame%20was%20denied!%3C/p%3E%3Cp%3EInner-inner%20iframe.%20This%20iframe%20(which%20is%20data:%20URL%20and%20whose%20parent%20is%20on%20a%20foreign%20domain)%20is%20the%20frame%20that%20the%20main%20frame%20is%20trying%20to%20access.%20%20It%20should%20not%20have%20access%20to%20it.%3C/p%3E%3C/body%3E%3C/html%3E from frame with URL http://127.0.0.1:8000/security/dataURL/xss-DENIED-to-data-url-in-foreign-domain-window-open.html. Domains, protocols and ports must match.
+CONSOLE MESSAGE: line 1: Unsafe JavaScript attempt to access frame with URL data:text/html,<html><head><script>function loaded() {if (window.layoutTestController)layoutTestController.globalFlag = true;}</script></head><body onload='loaded();'><p id='accessMe'>PASS: Access from the main frame was denied!</p><p>Inner-inner iframe. This iframe (which is data: URL and whose parent is on a foreign domain) is the frame that the main frame is trying to access.  It should not have access to it.</p></body></html> from frame with URL http://127.0.0.1:8000/security/dataURL/xss-DENIED-to-data-url-in-foreign-domain-window-open.html. Domains, protocols and ports must match.
 
 PASS: Cross frame access to a data: URL embed in a frame window.open'ed on foreign domain denied!
 
index e42bc60..e980f65 100644 (file)
@@ -1,4 +1,4 @@
-CONSOLE MESSAGE: line 1: Unsafe JavaScript attempt to access frame with URL data:text/html,%3Chtml%3E%3Chead%3E%3Cscript%3Efunction%20fireSentinel()%20{if%20(window.layoutTestController)layoutTestController.globalFlag%20=%20true;}%3C/script%3E%3C/head%3E%3Cbody%20onload=%22fireSentinel();%22%3E%3Cp%20id=%22accessMe%22%3EPASS:%20Cross%20frame%20access%20to%20a%20data:%20URL%202%20levels%20deep%20was%20denied.%3C/p%3E%3Cp%3EInner-inner%20iframe.%3C/p%3E%3C/body%3E%3C/html%3E from frame with URL http://127.0.0.1:8000/security/dataURL/xss-DENIED-to-data-url-sub-frame-2-level.html. Domains, protocols and ports must match.
+CONSOLE MESSAGE: line 1: Unsafe JavaScript attempt to access frame with URL data:text/html,<html><head><script>function fireSentinel() {if (window.layoutTestController)layoutTestController.globalFlag = true;}</script></head><body onload="fireSentinel();"><p id="accessMe">PASS: Cross frame access to a data: URL 2 levels deep was denied.</p><p>Inner-inner iframe.</p></body></html> from frame with URL http://127.0.0.1:8000/security/dataURL/xss-DENIED-to-data-url-sub-frame-2-level.html. Domains, protocols and ports must match.
 
 This tests that the main frame doesn't have access to a data: URL loaded in an iframe inside another data: URL loaded iframe.
 
index 6c99dfe..b47269b 100644 (file)
@@ -1,4 +1,4 @@
-CONSOLE MESSAGE: line 1: Unsafe JavaScript attempt to access frame with URL data:text/html,%3Chtml%3E%3Cscript%3Eonload%20=%20function()%20{%20parent.postMessage('LOADED',%20'*');%20}%20%3C/script%3E%3Cbody%3E%3Cp%20id='accessMe'%3E%3C/p%3E%3Cp%3EInner%20iframe.%3C/p%3E%3C/body%3E%3C/html%3E from frame with URL http://127.0.0.1:8000/security/dataURL/xss-DENIED-to-data-url-sub-frame.html. Domains, protocols and ports must match.
+CONSOLE MESSAGE: line 1: Unsafe JavaScript attempt to access frame with URL data:text/html,<html><script>onload = function() { parent.postMessage('LOADED', '*'); } </script><body><p id='accessMe'></p><p>Inner iframe.</p></body></html> from frame with URL http://127.0.0.1:8000/security/dataURL/xss-DENIED-to-data-url-sub-frame.html. Domains, protocols and ports must match.
 
 This tests that the main frame can't access the contents of an iframe that contains a data: URL loaded page
 
index c006037..9253013 100644 (file)
@@ -1,4 +1,4 @@
-CONSOLE MESSAGE: line 1: Unsafe JavaScript attempt to access frame with URL data:text/html,%3Chtml%3E%3Cscript%3Eonload%20=%20function()%20{%20parent.postMessage('LOADED',%20'*');%20}%20%3C/script%3E%3Cbody%3E%3Cp%20id='accessMe'%3E%3C/p%3E%3Cp%3EInner%20iframe.%3C/p%3E%3C/body%3E%3C/html%3E from frame with URL http://127.0.0.1:8000/security/dataURL/xss-DENIED-to-data-url-sub-frame-uppercase.html. Domains, protocols and ports must match.
+CONSOLE MESSAGE: line 1: Unsafe JavaScript attempt to access frame with URL data:text/html,<html><script>onload = function() { parent.postMessage('LOADED', '*'); } </script><body><p id='accessMe'></p><p>Inner iframe.</p></body></html> from frame with URL http://127.0.0.1:8000/security/dataURL/xss-DENIED-to-data-url-sub-frame-uppercase.html. Domains, protocols and ports must match.
 
 This tests that the main frame can't access the contents of an iframe that contains a data: URL loaded page using the uppercased variant DATA:
 
index c0d09df..ad5fef1 100644 (file)
@@ -1,4 +1,4 @@
-CONSOLE MESSAGE: line 1: Unsafe JavaScript attempt to access frame with URL data:text/html,%3Chtml%3E%3Chead%3E%3Cscript%3Efunction%20fireSentinel()%20{if%20(window.layoutTestController)layoutTestController.globalFlag%20=%20true;}%3C/script%3E%3C/head%3E%3Cbody%20onload=%22fireSentinel();%22%3E%3Cp%3EOpened%20Frame%3C/p%3E%3Cp%20id='accessMe'%3EPASS:%20Cross%20frame%20access%20from%20an%20opener%20frame%20was%20denied%3C/p%3E%3C/body%3E%3C/html%3E from frame with URL http://127.0.0.1:8000/security/dataURL/xss-DENIED-to-data-url-window-open.html. Domains, protocols and ports must match.
+CONSOLE MESSAGE: line 1: Unsafe JavaScript attempt to access frame with URL data:text/html,<html><head><script>function fireSentinel() {if (window.layoutTestController)layoutTestController.globalFlag = true;}</script></head><body onload="fireSentinel();"><p>Opened Frame</p><p id='accessMe'>PASS: Cross frame access from an opener frame was denied</p></body></html> from frame with URL http://127.0.0.1:8000/security/dataURL/xss-DENIED-to-data-url-window-open.html. Domains, protocols and ports must match.
 
 Opener Frame
 
index fa68dd8..b196c15 100644 (file)
@@ -4,7 +4,9 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
 
 
 PASS canonicalize('http://www.google.com/foo?bar=baz#') is 'http://www.google.com/foo?bar=baz#'
+PASS canonicalize('http://www.google.com/foo?bar=baz# »') is 'http://www.google.com/foo?bar=baz# »'
 PASS canonicalize('http://[www.google.com]/') is 'http://[www.google.com]/'
+PASS canonicalize('http://www.google.com') is 'http://www.google.com/'
 PASS canonicalize('http:////////user:@google.com:99?foo') is 'http://user@google.com:99/?foo'
 PASS canonicalize('http://192.0x00A80001') is 'http://192.168.0.1/'
 PASS canonicalize('http://www/foo%2Ehtml') is 'http://www/foo.html'
@@ -53,6 +55,8 @@ PASS canonicalize('wss:example.com/') is 'wss://example.com/'
 PASS canonicalize('data:example.com/') is 'data:example.com/'
 PASS canonicalize('javascript:example.com/') is 'javascript:example.com/'
 PASS canonicalize('mailto:example.com/') is 'mailto:example.com/'
+PASS canonicalize('javascript:alert(\t 1 \n\r)') is 'javascript:alert( 1 )'
+PASS canonicalize('javascript:alert(" \ 1 β ")') is 'javascript:alert(" %01 %CE%B2 ")'
 PASS successfullyParsed is true
 
 TEST COMPLETE
index fa68dd8..b196c15 100644 (file)
@@ -4,7 +4,9 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
 
 
 PASS canonicalize('http://www.google.com/foo?bar=baz#') is 'http://www.google.com/foo?bar=baz#'
+PASS canonicalize('http://www.google.com/foo?bar=baz# »') is 'http://www.google.com/foo?bar=baz# »'
 PASS canonicalize('http://[www.google.com]/') is 'http://[www.google.com]/'
+PASS canonicalize('http://www.google.com') is 'http://www.google.com/'
 PASS canonicalize('http:////////user:@google.com:99?foo') is 'http://user@google.com:99/?foo'
 PASS canonicalize('http://192.0x00A80001') is 'http://192.168.0.1/'
 PASS canonicalize('http://www/foo%2Ehtml') is 'http://www/foo.html'
@@ -53,6 +55,8 @@ PASS canonicalize('wss:example.com/') is 'wss://example.com/'
 PASS canonicalize('data:example.com/') is 'data:example.com/'
 PASS canonicalize('javascript:example.com/') is 'javascript:example.com/'
 PASS canonicalize('mailto:example.com/') is 'mailto:example.com/'
+PASS canonicalize('javascript:alert(\t 1 \n\r)') is 'javascript:alert( 1 )'
+PASS canonicalize('javascript:alert(" \ 1 β ")') is 'javascript:alert(" %01 %CE%B2 ")'
 PASS successfullyParsed is true
 
 TEST COMPLETE
index fa68dd8..b196c15 100644 (file)
@@ -4,7 +4,9 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
 
 
 PASS canonicalize('http://www.google.com/foo?bar=baz#') is 'http://www.google.com/foo?bar=baz#'
+PASS canonicalize('http://www.google.com/foo?bar=baz# »') is 'http://www.google.com/foo?bar=baz# »'
 PASS canonicalize('http://[www.google.com]/') is 'http://[www.google.com]/'
+PASS canonicalize('http://www.google.com') is 'http://www.google.com/'
 PASS canonicalize('http:////////user:@google.com:99?foo') is 'http://user@google.com:99/?foo'
 PASS canonicalize('http://192.0x00A80001') is 'http://192.168.0.1/'
 PASS canonicalize('http://www/foo%2Ehtml') is 'http://www/foo.html'
@@ -53,6 +55,8 @@ PASS canonicalize('wss:example.com/') is 'wss://example.com/'
 PASS canonicalize('data:example.com/') is 'data:example.com/'
 PASS canonicalize('javascript:example.com/') is 'javascript:example.com/'
 PASS canonicalize('mailto:example.com/') is 'mailto:example.com/'
+PASS canonicalize('javascript:alert(\t 1 \n\r)') is 'javascript:alert( 1 )'
+PASS canonicalize('javascript:alert(" \ 1 β ")') is 'javascript:alert(" %01 %CE%B2 ")'
 PASS successfullyParsed is true
 
 TEST COMPLETE
index 4896aff..761246e 100644 (file)
@@ -4,7 +4,9 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
 
 
 PASS canonicalize('http://www.google.com/foo?bar=baz#') is 'http://www.google.com/foo?bar=baz#'
+PASS canonicalize('http://www.google.com/foo?bar=baz# »') is 'http://www.google.com/foo?bar=baz# »'
 PASS canonicalize('http://[www.google.com]/') is 'http://[www.google.com]/'
+PASS canonicalize('http://www.google.com') is 'http://www.google.com/'
 PASS canonicalize('http:////////user:@google.com:99?foo') is 'http://user@google.com:99/?foo'
 PASS canonicalize('http://192.0x00A80001') is 'http://192.168.0.1/'
 PASS canonicalize('http://www/foo%2Ehtml') is 'http://www/foo.html'
@@ -53,6 +55,8 @@ PASS canonicalize('wss:example.com/') is 'wss://example.com/'
 PASS canonicalize('data:example.com/') is 'data:example.com/'
 PASS canonicalize('javascript:example.com/') is 'javascript:example.com/'
 PASS canonicalize('mailto:example.com/') is 'mailto:example.com/'
+PASS canonicalize('javascript:alert(\t 1 \n\r)') is 'javascript:alert( 1 )'
+PASS canonicalize('javascript:alert(" \ 1 β ")') is 'javascript:alert(" %01 %CE%B2 ")'
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/LayoutTests/platform/chromium/fast/dom/anchor-origin-expected.txt b/LayoutTests/platform/chromium/fast/dom/anchor-origin-expected.txt
deleted file mode 100644 (file)
index 9b46791..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-Link
-Link
-Link
-Link
-Link
-Link
-http://example.com/foo/bar => http://example.com
-http://example.com/foo/bar => http://example.com
-https://example.com/ttt?ggg => https://example.com
-ftp://example.com/ttt?ggg => ftp://example.com
-file:///home/abarth => file://
-data:text/html,foo => null
-
index e7742ac..2b4a7f0 100644 (file)
@@ -1,3 +1,39 @@
+2011-10-05  Erik Arvidsson  <arv@chromium.org>
+
+        window.location.href and others needlessly decodes URI-encoded characters
+        https://bugs.webkit.org/show_bug.cgi?id=30225
+
+        Reviewed by Darin Adler.
+
+        Don't decode KURL::path() and stop using KURL::deprecatedString() in Location methods.
+
+        This slightly changes how we parse data and javascript URLs (non hierarchical URLs) to
+        not encode so aggressively.
+
+        * fileapi/DOMFileSystemBase.cpp:
+        (WebCore::DOMFileSystemBase::crackFileSystemURL): Manually decode path()
+        * loader/FrameLoader.cpp:
+        (WebCore::FrameLoader::defaultObjectContentType): Manually decode path()
+        * page/Location.cpp:
+        (WebCore::Location::href): Use string() instead of deprecatedString()
+        * page/Location.h:
+        (WebCore::Location::toString): Inline call to href()
+        * platform/KURL.cpp:
+        (WebCore::KURL::path): Don't decode.
+        (WebCore::escapeAndAppendNonHierarchicalPart): Rename escapeAndAppendFragment to escapeAndAppendNonHierarchicalPart
+                                                       since this is now used for more than just fragments.
+        (WebCore::KURL::parse): Don't decode
+        * platform/KURLGoogle.cpp:
+        (WebCore::KURL::path): Remove out of date comment
+        * platform/qt/KURLQt.cpp:
+        (WebCore::KURL::fileSystemPath): Manually decode path()
+        * platform/win/ClipboardWin.cpp:
+        (WebCore::createGlobalHDropContent): Manually decode path()
+        * workers/WorkerLocation.cpp:
+        (WebCore::WorkerLocation::href): Use string() instead of deprecatedString()
+        * workers/WorkerLocation.h:
+        (WebCore::WorkerLocation::toString): Inline call to href()
+
 2011-10-05  Darin Adler  <darin@apple.com>
 
         [Mac] Use four more named cursors if present
index 68a00a7..ec8ef72 100644 (file)
@@ -63,7 +63,7 @@ bool DOMFileSystemBase::crackFileSystemURL(const KURL& url, AsyncFileSystem::Typ
         return false;
 
     KURL originURL(ParsedURLString, url.path());
-    String path = originURL.path();
+    String path = decodeURLEscapeSequences(originURL.path());
     if (path.isEmpty() || path[0] != '/')
         return false;
     path = path.substring(1);
index 4a52002..0fe54b4 100644 (file)
@@ -849,7 +849,8 @@ void FrameLoader::loadArchive(PassRefPtr<Archive> archive)
 ObjectContentType FrameLoader::defaultObjectContentType(const KURL& url, const String& mimeTypeIn, bool shouldPreferPlugInsForImages)
 {
     String mimeType = mimeTypeIn;
-    String extension = url.path().substring(url.path().reverseFind('.') + 1);
+    String decodedPath = decodeURLEscapeSequences(url.path());
+    String extension = decodedPath.substring(decodedPath.reverseFind('.') + 1);
 
     // We don't use MIMETypeRegistry::getMIMETypeForPath() because it returns "application/octet-stream" upon failure
     if (mimeType.isEmpty())
index 4e5b228..abdb867 100644 (file)
@@ -65,9 +65,7 @@ String Location::href() const
     if (!m_frame)
         return String();
 
-    const KURL& url = this->url();
-    // FIXME: Stop using deprecatedString(): https://bugs.webkit.org/show_bug.cgi?id=30225
-    return url.hasPath() ? url.deprecatedString() : url.deprecatedString() + "/";
+    return url().string();
 }
 
 String Location::protocol() const
@@ -150,16 +148,6 @@ String Location::getParameter(const String& name) const
     return parameters.get(name);
 }
 
-String Location::toString() const
-{
-    if (!m_frame)
-        return String();
-
-    const KURL& url = this->url();
-    // FIXME: Stop using deprecatedString(): https://bugs.webkit.org/show_bug.cgi?id=30225
-    return url.hasPath() ? url.deprecatedString() : url.deprecatedString() + "/";
-}
-
 void Location::setHref(const String& urlString, DOMWindow* activeWindow, DOMWindow* firstWindow)
 {
     if (!m_frame)
index 1b68cee..0e89ecf 100644 (file)
@@ -29,9 +29,9 @@
 #ifndef Location_h
 #define Location_h
 
-#include <wtf/Forward.h>
 #include <wtf/PassRefPtr.h>
 #include <wtf/RefCounted.h>
+#include <wtf/text/WTFString.h>
 
 namespace WebCore {
 
@@ -71,7 +71,7 @@ public:
     String hash() const;
     String origin() const;
 
-    String toString() const;
+    String toString() const { return href(); }
 
     String getParameter(const String&) const;
 
index 2402ef3..80f46d0 100644 (file)
@@ -720,7 +720,7 @@ String KURL::query() const
 
 String KURL::path() const
 {
-    return decodeURLEscapeSequences(m_string.substring(m_portEnd, m_pathEnd - m_portEnd)); 
+    return m_string.substring(m_portEnd, m_pathEnd - m_portEnd);
 }
 
 bool KURL::setProtocol(const String& s)
@@ -963,7 +963,7 @@ static void appendEscapingBadChars(char*& buffer, const char* strStart, size_t l
     buffer = p;
 }
 
-static void escapeAndAppendFragment(char*& buffer, const char* strStart, size_t length)
+static void escapeAndAppendNonHierarchicalPart(char*& buffer, const char* strStart, size_t length)
 {
     char* p = buffer;
 
@@ -1382,7 +1382,9 @@ void KURL::parse(const char* url, const String* originalString)
         *p++ = '/';
 
     // add path, escaping bad characters
-    if (!hierarchical || !hasSlashDotOrDotDot(url))
+    if (!hierarchical)
+        escapeAndAppendNonHierarchicalPart(p, url + pathStart, pathEnd - pathStart);
+    else if (!hasSlashDotOrDotDot(url))
         appendEscapingBadChars(p, url + pathStart, pathEnd - pathStart);
     else {
         CharBuffer pathBuffer(pathEnd - pathStart + 1);
@@ -1408,7 +1410,7 @@ void KURL::parse(const char* url, const String* originalString)
     // add fragment, escaping bad characters
     if (fragmentEnd != queryEnd) {
         *p++ = '#';
-        escapeAndAppendFragment(p, url + fragmentStart, fragmentEnd - fragmentStart);
+        escapeAndAppendNonHierarchicalPart(p, url + fragmentStart, fragmentEnd - fragmentStart);
     }
     m_fragmentEnd = p - buffer.data();
 
index b83c287..08550c6 100644 (file)
@@ -594,7 +594,6 @@ String KURL::query() const
 
 String KURL::path() const
 {
-    // Note: KURL.cpp unescapes here.
     return m_url.componentString(m_url.m_parsed.path);
 }
 
index c8f9ed7..ddc5580 100644 (file)
@@ -51,10 +51,9 @@ String KURL::fileSystemPath() const
 
     // A valid qrc resource path begins with a colon.
     if (protocolIs("qrc"))
-        return ":" + path();
+        return ":" + decodeURLEscapeSequences(path());
 
     return String();
 }
 
 }
-
index bf408d7..8ca61c8 100644 (file)
@@ -176,7 +176,7 @@ static HGLOBAL createGlobalHDropContent(const KURL& url, String& fileName, Share
     WCHAR filePath[MAX_PATH];
 
     if (url.isLocalFile()) {
-        String localPath = url.path();
+        String localPath = decodeURLEscapeSequences(url.path());
         // windows does not enjoy a leading slash on paths
         if (localPath[0] == '/')
             localPath = localPath.substring(1);
index dc88238..eb76a8b 100644 (file)
@@ -36,8 +36,7 @@ namespace WebCore {
 
 String WorkerLocation::href() const
 {
-    // FIXME: Stop using deprecatedString(): https://bugs.webkit.org/show_bug.cgi?id=30225
-    return m_url.hasPath() ? m_url.deprecatedString() : m_url.deprecatedString() + "/";
+    return m_url.string();
 }
 
 String WorkerLocation::protocol() const
@@ -75,12 +74,6 @@ String WorkerLocation::hash() const
     return m_url.fragmentIdentifier().isEmpty() ? emptyString() : "#" + m_url.fragmentIdentifier();
 }
 
-String WorkerLocation::toString() const
-{
-    // FIXME: Stop using deprecatedString(): https://bugs.webkit.org/show_bug.cgi?id=30225
-    return m_url.hasPath() ? m_url.deprecatedString() : m_url.deprecatedString() + "/";
-}
-
 
 } // namespace WebCore
 
index 5200e35..692c0e3 100644 (file)
 #if ENABLE(WORKERS)
 
 #include "KURL.h"
-#include <wtf/Forward.h>
 #include <wtf/PassRefPtr.h>
 #include <wtf/RefCounted.h>
 #include <wtf/RefPtr.h>
+#include <wtf/text/WTFString.h>
 
 namespace WebCore {
 
@@ -57,7 +57,7 @@ namespace WebCore {
         String search() const;
         String hash() const;
 
-        String toString() const;
+        String toString() const { return href(); }
 
     private:
         WorkerLocation(const KURL& url) : m_url(url) { }
index 5f3ef3e..f7e4a8e 100644 (file)
@@ -1,3 +1,13 @@
+2011-10-05  Erik Arvidsson  <arv@chromium.org>
+
+        window.location.href and others needlessly decodes URI-encoded characters
+        https://bugs.webkit.org/show_bug.cgi?id=30225
+
+        Reviewed by Darin Adler.
+
+        * DumpRenderTree/chromium/TestShell.cpp:
+        (normalizeLayoutTestURLInternal): Remove extra encode.
+
 2011-10-05  Darin Adler  <darin@apple.com>
 
         Fix build.
index 41134f7..fbb786d 100644 (file)
@@ -403,7 +403,7 @@ static string normalizeLayoutTestURLInternal(const string& url)
         result.replace(0, pos + layoutTestsPatternSize, fileTestPrefix);
     } else if (!url.find(dataUrlPattern)) {
         // URL-escape data URLs to match results upstream.
-        string path = webkit_support::EscapePath(url.substr(dataUrlPatternSize));
+        string path = url.substr(dataUrlPatternSize);
         result.replace(dataUrlPatternSize, url.length(), path);
     }
     return result;