Ensure that all base URL's are absolut-ify-ed, no matter where we get them from. Also refactor the compute script base code to be easier to read Review at http://gwt-code-reviews.appspot.com/1066801 Review by: amitmanjhi@google.com git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@9180 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/core/ext/linker/impl/computeScriptBase.js b/dev/core/src/com/google/gwt/core/ext/linker/impl/computeScriptBase.js index dd27fa0..3d4b61a 100644 --- a/dev/core/src/com/google/gwt/core/ext/linker/impl/computeScriptBase.js +++ b/dev/core/src/com/google/gwt/core/ext/linker/impl/computeScriptBase.js
@@ -29,53 +29,8 @@ */ function computeScriptBase() { - // First, check if the meta properties give the baseUrl - var metaVal = __gwt_getMetaProperty('baseUrl'); - // Note: the base variable should not be defined in this function because in - // the older templates (like IFrameTemplate.js), base is defined outside this - // function, and they rely on the fact that calling computeScriptBase will set - // that base variable rather than using the return value. Instead, we define - // a tempBase variable, and then right before we return, we also set the - // base variable for backwards compatability - var tempBase = ''; - if (metaVal != null) { - tempBase = metaVal; - base = tempBase; - return tempBase; - } - - // The baseUrl will be similar to the URL for this script's URL - var thisScript; - - // By default, this script looks like something/moduleName.nocache.js - // so look for a script tag that looks like that - var scriptTags = $doc.getElementsByTagName('script'); - for (var i = 0; i < scriptTags.length; ++i) { - if (scriptTags[i].src.indexOf('__MODULE_NAME__.nocache.js') != -1) { - thisScript = scriptTags[i]; - } - } - - // If the user renamed their script tag, we'll use a fancier method to find - // it. Note that this will not work in the Late Loading case due to the - // document.write call. - if (!thisScript) { - if (typeof isBodyLoaded == 'undefined' || !isBodyLoaded()) { - // Put in a marker script element which should be the first script tag after - // the tag we're looking for. To find it, we start at the marker and walk - // backwards until we find a script. - var markerId = "__gwt_marker___MODULE_NAME__"; - var markerScript; - $doc.write('<script id="' + markerId + '"></script>'); - markerScript = $doc.getElementById(markerId); - thisScript = markerScript && markerScript.previousSibling; - while (thisScript && thisScript.tagName != 'SCRIPT') { - thisScript = thisScript.previousSibling; - } - } - } - + // ================ Helper methods to process tags ====================== // Gets the part of a url up to and including the 'path' portion. function getDirectoryOfFile(path) { // Truncate starting at the first '?' or '#', whichever comes first. @@ -89,41 +44,102 @@ } var slashIndex = path.lastIndexOf('/', Math.min(queryIndex, hashIndex)); return (slashIndex >= 0) ? path.substring(0, slashIndex + 1) : ''; - }; - - if (thisScript && thisScript.src) { - // Compute our base url - tempBase = getDirectoryOfFile(thisScript.src); } - // Make the base URL absolute - if (tempBase == '') { - // If there's a base tag, use it. + function ensureAbsoluteUrl(url) { + if ((url.match(/^\w+:\/\//))) { + // If the URL is obviously absolute, do nothing. + } else { + // Probably a relative URL; use magic to make the browser absolutify it. + // I wish there were a better way to do this, but this seems the only + // sure way! (A side benefit is it preloads clear.cache.gif) + // Note: this trick is harmless if the URL was really already absolute. + var img = $doc.createElement("img"); + img.src = url + 'clear.cache.gif'; + url = getDirectoryOfFile(img.src); + } + return url; + } + +// =============== Various methods to try finding the base ================= + function tryMetaTag() { + var metaVal = __gwt_getMetaProperty('baseUrl'); + if (metaVal != null) { + return metaVal; + } + return ''; + } + + function tryNocacheJsTag() { + // By default, this script looks like something/moduleName.nocache.js + // so look for a script tag that looks like that + var scriptTags = $doc.getElementsByTagName('script'); + for (var i = 0; i < scriptTags.length; ++i) { + if (scriptTags[i].src.indexOf('__MODULE_NAME__.nocache.js') != -1) { + return getDirectoryOfFile(scriptTags[i].src); + } + } + return ''; + } + + function tryMarkerScript() { + // If the user renamed their script tag, we'll use a fancier method to find + // it. Note that this will not work in the Late Loading case due to the + // document.write call. + var thisScript; + if (typeof isBodyLoaded == 'undefined' || !isBodyLoaded()) { + // Put in a marker script element which should be the first script tag after + // the tag we're looking for. To find it, we start at the marker and walk + // backwards until we find a script. + var markerId = "__gwt_marker___MODULE_NAME__"; + var markerScript; + $doc.write('<script id="' + markerId + '"></script>'); + markerScript = $doc.getElementById(markerId); + thisScript = markerScript && markerScript.previousSibling; + while (thisScript && thisScript.tagName != 'SCRIPT') { + thisScript = thisScript.previousSibling; + } + if (markerScript) { + markerScript.parentNode.removeChild(markerScript); + } + if (thisScript && thisScript.src) { + return getDirectoryOfFile(thisScript.src); + } + } + return ''; + } + + function tryBaseTag() { var baseElements = $doc.getElementsByTagName('base'); if (baseElements.length > 0) { // It's always the last parsed base tag that will apply to this script. - tempBase = baseElements[baseElements.length - 1].href; - } else { - // No base tag; the base must be the same as the document location. - tempBase = getDirectoryOfFile($doc.location.href); + return baseElements[baseElements.length - 1].href; } - } else if ((tempBase.match(/^\w+:\/\//))) { - // If the URL is obviously absolute, do nothing. - } else { - // Probably a relative URL; use magic to make the browser absolutify it. - // I wish there were a better way to do this, but this seems the only - // sure way! (A side benefit is it preloads clear.cache.gif) - // Note: this trick is harmless if the URL was really already absolute. - var img = $doc.createElement("img"); - img.src = tempBase + 'clear.cache.gif'; - tempBase = getDirectoryOfFile(img.src); + return ''; } - - if (markerScript) { - // remove the marker element - markerScript.parentNode.removeChild(markerScript); + +// ================ Inline Code ============================================= + var tempBase = tryMetaTag(); + if (tempBase == '') { + tempBase = tryNocacheJsTag(); } - + if (tempBase == '') { + tempBase = tryMarkerScript(); + } + if (tempBase == '') { + tempBase = tryBaseTag(); + } + if (tempBase == '') { + // last resort + tempBase = getDirectoryOfFile($doc.location.href); + } + + tempBase = ensureAbsoluteUrl(tempBase); + + // Note: the base variable should not be defined in this function because in + // the older templates (like IFrameTemplate.js), base is defined outside this + // function, and they rely on the fact that calling computeScriptBase will set + // that base variable rather than using the return value. base = tempBase; return tempBase; }
diff --git a/dev/core/test/com/google/gwt/core/ext/linker/impl/SelectionScriptJavaScriptTest.java b/dev/core/test/com/google/gwt/core/ext/linker/impl/SelectionScriptJavaScriptTest.java index f3baebc..e6a392a 100644 --- a/dev/core/test/com/google/gwt/core/ext/linker/impl/SelectionScriptJavaScriptTest.java +++ b/dev/core/test/com/google/gwt/core/ext/linker/impl/SelectionScriptJavaScriptTest.java
@@ -52,7 +52,7 @@ + "return (value == null) ? null : value; }"); code.append(Utility.getFileFromClassPath(SelectionScriptLinker.COMPUTE_SCRIPT_BASE_JS)); code.append("computeScriptBase();\n"); - return code.toString().replaceAll("__MODULE_NAME__", TEST_MODULE_NAME); + return code.toString(); } /** @@ -133,11 +133,28 @@ } /** + * Test the default href + */ + public void testDefault() throws IOException { + StringBuffer testCode = new StringBuffer(); + testCode.append("var metaProps = { };\n"); + testCode.append("function isBodyLoaded() { return true; }\n"); + testCode.append(loadComputeScriptBase()); + testCode.append("alert('base='+base);\n"); + + List<String> alerts = loadPage(makeHostPage(""), testCode); + + assertEquals(1, alerts.size()); + assertEquals("base=http://foo.test/", alerts.get(0)); + } + + /** * Test the fully magic script base with no meta properties. */ public void testScriptBase() throws IOException { StringBuffer testCode = new StringBuffer(); testCode.append("var metaProps = { };\n"); + testCode.append("function isBodyLoaded() { return false; }\n"); testCode.append(loadComputeScriptBase()); testCode.append("alert('base='+base);\n"); @@ -146,7 +163,37 @@ assertEquals(1, alerts.size()); assertEquals("base=http://foo.test/foo/", alerts.get(0)); } + + /** + * Test getting the base URL from a meta property with an absolute URL + */ + public void testScriptBaseFromMetas() throws IOException { + StringBuffer testCode = new StringBuffer(); + testCode.append("var metaProps = { baseUrl : \"http://static.test/fromMetaTag/\" };\n"); + testCode.append(loadComputeScriptBase()); + testCode.append("alert('base='+base);\n"); + List<String> alerts = loadPage(makeHostPage(""), testCode); + + assertEquals(1, alerts.size()); + assertEquals("base=http://static.test/fromMetaTag/", alerts.get(0)); + } + + /** + * Test getting the base URL from a meta property with a relative URL + */ + public void testRelativeScriptBaseFromMetas() throws IOException { + StringBuffer testCode = new StringBuffer(); + testCode.append("var metaProps = { baseUrl : \"fromMeta/tag/\" };\n"); + testCode.append(loadComputeScriptBase()); + testCode.append("alert('base='+base);\n"); + + List<String> alerts = loadPage(makeHostPage(""), testCode); + + assertEquals(1, alerts.size()); + assertEquals("base=http://foo.test/fromMeta/tag/", alerts.get(0)); + } + /** * Test the script base logic for an inlined selection script. */ @@ -171,7 +218,7 @@ public void testScriptBaseFromBaseTag() throws IOException { StringBuffer hostPage = new StringBuffer(); hostPage.append("<html><head>\n"); - hostPage.append("<base href=\"http://static.test/foo/\">\n"); + hostPage.append("<base href=\"http://static.test/fromBaseTag/\">\n"); hostPage.append("<script lang=\"javascript\"><!--\n"); hostPage.append("var metaProps = { }\n"); hostPage.append(loadComputeScriptBase()); @@ -181,22 +228,27 @@ List<String> alerts = loadPage(hostPage.toString(), ""); assertEquals(1, alerts.size()); - assertEquals("base=http://static.test/foo/", alerts.get(0)); + assertEquals("base=http://static.test/fromBaseTag/", alerts.get(0)); } - + /** - * Test getting the base URL from a meta property + * Test the script base logic for an inlined selection script. */ - public void testScriptBaseFromMetas() throws IOException { - StringBuffer testCode = new StringBuffer(); - testCode.append("var metaProps = { baseUrl : \"http://static.test/foo/\" };\n"); - testCode.append(loadComputeScriptBase()); - testCode.append("alert('base='+base);\n"); + public void testNocacheJsTag() throws IOException { + StringBuffer hostPage = new StringBuffer(); + hostPage.append("<html><head>\n"); + hostPage.append("<script lang='javascript' type='application/javascript' "); + hostPage.append("src='from/nocache/__MODULE_NAME__.nocache.js'></script>\n"); + hostPage.append("<script lang=\"javascript\"><!--\n"); + hostPage.append("var metaProps = { }\n"); + hostPage.append(loadComputeScriptBase()); + hostPage.append("alert('base='+base);\n"); + hostPage.append("--></script>\n"); - List<String> alerts = loadPage(makeHostPage(""), testCode); + List<String> alerts = loadPage(hostPage.toString(), ""); assertEquals(1, alerts.size()); - assertEquals("base=http://static.test/foo/", alerts.get(0)); + assertEquals("base=http://foo.test/from/nocache/", alerts.get(0)); } /**