Add vectortile branch
This commit is contained in:
@@ -0,0 +1,302 @@
|
||||
// Copyright 2006 The Closure Library Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS-IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/**
|
||||
* @fileoverview Utilities for window manipulation.
|
||||
*/
|
||||
|
||||
|
||||
goog.provide('goog.window');
|
||||
|
||||
goog.require('goog.dom.TagName');
|
||||
goog.require('goog.dom.safe');
|
||||
goog.require('goog.html.SafeUrl');
|
||||
goog.require('goog.html.uncheckedconversions');
|
||||
goog.require('goog.labs.userAgent.platform');
|
||||
goog.require('goog.string');
|
||||
goog.require('goog.string.Const');
|
||||
goog.require('goog.userAgent');
|
||||
|
||||
|
||||
/**
|
||||
* Default height for popup windows
|
||||
* @type {number}
|
||||
*/
|
||||
goog.window.DEFAULT_POPUP_HEIGHT = 500;
|
||||
|
||||
|
||||
/**
|
||||
* Default width for popup windows
|
||||
* @type {number}
|
||||
*/
|
||||
goog.window.DEFAULT_POPUP_WIDTH = 690;
|
||||
|
||||
|
||||
/**
|
||||
* Default target for popup windows
|
||||
* @type {string}
|
||||
*/
|
||||
goog.window.DEFAULT_POPUP_TARGET = 'google_popup';
|
||||
|
||||
|
||||
/**
|
||||
* Opens a new window.
|
||||
*
|
||||
* @param {goog.html.SafeUrl|string|Object} linkRef If an Object with an 'href'
|
||||
* attribute (such as HTMLAnchorElement) is passed then the value of 'href'
|
||||
* is used, otherwise otherwise its toString method is called. Note that
|
||||
* if a string|Object is used, an untrusted script execution might result
|
||||
* (e.g. from javascript: URLs).
|
||||
*
|
||||
* @param {Object=} opt_options supports the following options:
|
||||
* 'target': (string) target (window name). If null, linkRef.target will
|
||||
* be used.
|
||||
* 'width': (number) window width.
|
||||
* 'height': (number) window height.
|
||||
* 'top': (number) distance from top of screen
|
||||
* 'left': (number) distance from left of screen
|
||||
* 'toolbar': (boolean) show toolbar
|
||||
* 'scrollbars': (boolean) show scrollbars
|
||||
* 'location': (boolean) show location
|
||||
* 'statusbar': (boolean) show statusbar
|
||||
* 'menubar': (boolean) show menubar
|
||||
* 'resizable': (boolean) resizable
|
||||
* 'noreferrer': (boolean) whether to attempt to remove the referrer header
|
||||
* from the request headers. Does this by opening a blank window that
|
||||
* then redirects to the target url, so users may see some flickering.
|
||||
*
|
||||
* @param {Window=} opt_parentWin Parent window that should be used to open the
|
||||
* new window.
|
||||
*
|
||||
* @return {Window} Returns the window object that was opened. This returns
|
||||
* null if a popup blocker prevented the window from being
|
||||
* opened. In case when a new window is opened in a different
|
||||
* browser sandbox (such as iOS standalone mode), the returned
|
||||
* object is a emulated Window object that functions as if
|
||||
* a cross-origin window has been opened.
|
||||
*/
|
||||
goog.window.open = function(linkRef, opt_options, opt_parentWin) {
|
||||
if (!opt_options) {
|
||||
opt_options = {};
|
||||
}
|
||||
var parentWin = opt_parentWin || window;
|
||||
|
||||
var url;
|
||||
if (linkRef instanceof goog.html.SafeUrl) {
|
||||
url = goog.html.SafeUrl.unwrap(linkRef);
|
||||
} else {
|
||||
// HTMLAnchorElement has a toString() method with the same behavior as
|
||||
// goog.Uri in all browsers except for Safari, which returns
|
||||
// '[object HTMLAnchorElement]'. We check for the href first, then
|
||||
// assume that it's a goog.Uri or String otherwise.
|
||||
url = typeof linkRef.href != 'undefined' ? linkRef.href : String(linkRef);
|
||||
}
|
||||
|
||||
var target = opt_options.target || linkRef.target;
|
||||
|
||||
var sb = [];
|
||||
for (var option in opt_options) {
|
||||
switch (option) {
|
||||
case 'width':
|
||||
case 'height':
|
||||
case 'top':
|
||||
case 'left':
|
||||
sb.push(option + '=' + opt_options[option]);
|
||||
break;
|
||||
case 'target':
|
||||
case 'noreferrer':
|
||||
break;
|
||||
default:
|
||||
sb.push(option + '=' + (opt_options[option] ? 1 : 0));
|
||||
}
|
||||
}
|
||||
var optionString = sb.join(',');
|
||||
|
||||
var newWin;
|
||||
if (goog.labs.userAgent.platform.isIos() &&
|
||||
parentWin.navigator && parentWin.navigator['standalone'] &&
|
||||
target && target != '_self') {
|
||||
// iOS in standalone mode disregards "target" in window.open and always
|
||||
// opens new URL in the same window. The workout around is to create an "A"
|
||||
// element and send a click event to it.
|
||||
// Notice that the "A" tag does NOT have to be added to the DOM.
|
||||
var a = parentWin.document.createElement(goog.dom.TagName.A);
|
||||
// TODO(user): Sanitize URL. See cl/89965465 for code and test which
|
||||
// was reverted.
|
||||
a.setAttribute('href', url);
|
||||
a.setAttribute('target', target);
|
||||
if (opt_options['noreferrer']) {
|
||||
a.setAttribute('rel', 'noreferrer');
|
||||
}
|
||||
var click = document.createEvent('MouseEvent');
|
||||
click.initMouseEvent('click',
|
||||
true, // canBubble
|
||||
true, // cancelable
|
||||
parentWin,
|
||||
1); // detail = mousebutton
|
||||
a.dispatchEvent(click);
|
||||
// New window is not available in this case. Instead, a fake Window object
|
||||
// is returned. In particular, it will have window.document undefined. In
|
||||
// general, it will appear to most of clients as a Window for a different
|
||||
// origin. Since iOS standalone web apps are run in their own sandbox, this
|
||||
// is the most appropriate return value.
|
||||
newWin = /** @type {!Window} */ ({});
|
||||
} else if (opt_options['noreferrer']) {
|
||||
// Use a meta-refresh to stop the referrer from being included in the
|
||||
// request headers. This seems to be the only cross-browser way to
|
||||
// remove the referrer. It also allows for the opener to be set to null
|
||||
// in the new window, thus disallowing the opened window from navigating
|
||||
// its opener.
|
||||
//
|
||||
// Detecting user agent and then using a different strategy per browser
|
||||
// would allow the referrer to leak in case of an incorrect/missing user
|
||||
// agent.
|
||||
newWin = parentWin.open('', target, optionString);
|
||||
if (newWin) {
|
||||
if (goog.userAgent.IE) {
|
||||
// IE has problems parsing the content attribute if the url contains
|
||||
// a semicolon. We can fix this by adding quotes around the url, but
|
||||
// then we can't parse quotes in the URL correctly. We take a
|
||||
// best-effort approach.
|
||||
//
|
||||
// If the URL has semicolons, wrap it in single quotes to protect
|
||||
// the semicolons.
|
||||
// If the URL has semicolons and single quotes, url-encode the single
|
||||
// quotes as well.
|
||||
//
|
||||
// This is imperfect. Notice that both ' and ; are reserved characters
|
||||
// in URIs, so this could do the wrong thing, but at least it will
|
||||
// do the wrong thing in only rare cases.
|
||||
// ugh.
|
||||
if (goog.string.contains(url, ';')) {
|
||||
url = "'" + url.replace(/'/g, '%27') + "'";
|
||||
}
|
||||
}
|
||||
newWin.opener = null;
|
||||
var escapedUrl = goog.string.htmlEscape(url);
|
||||
var safeHtml = goog.html.uncheckedconversions
|
||||
.safeHtmlFromStringKnownToSatisfyTypeContract(
|
||||
goog.string.Const.from('b/12014412, meta tag with sanitized URL'),
|
||||
'<META HTTP-EQUIV="refresh" content="0; url=' +
|
||||
escapedUrl + '">');
|
||||
goog.dom.safe.documentWrite(newWin.document, safeHtml);
|
||||
newWin.document.close();
|
||||
}
|
||||
} else {
|
||||
newWin = parentWin.open(url, target, optionString);
|
||||
}
|
||||
// newWin is null if a popup blocker prevented the window open.
|
||||
return newWin;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Opens a new window without any real content in it.
|
||||
*
|
||||
* This can be used to get around popup blockers if you need to open a window
|
||||
* in response to a user event, but need to do asynchronous work to determine
|
||||
* the URL to open, and then set the URL later.
|
||||
*
|
||||
* Example usage:
|
||||
*
|
||||
* var newWin = goog.window.openBlank('Loading...');
|
||||
* setTimeout(
|
||||
* function() {
|
||||
* newWin.location.href = 'http://www.google.com';
|
||||
* }, 100);
|
||||
*
|
||||
* @param {string=} opt_message String to show in the new window. This string
|
||||
* will be HTML-escaped to avoid XSS issues.
|
||||
* @param {Object=} opt_options Options to open window with.
|
||||
* {@see goog.window.open for exact option semantics}.
|
||||
* @param {Window=} opt_parentWin Parent window that should be used to open the
|
||||
* new window.
|
||||
* @return {Window} Returns the window object that was opened. This returns
|
||||
* null if a popup blocker prevented the window from being
|
||||
* opened.
|
||||
*/
|
||||
goog.window.openBlank = function(opt_message, opt_options, opt_parentWin) {
|
||||
// Open up a window with the loading message and nothing else.
|
||||
// This will be interpreted as HTML content type with a missing doctype
|
||||
// and html/body tags, but is otherwise acceptable.
|
||||
//
|
||||
// IMPORTANT: The order of escaping is crucial here in order to avoid XSS.
|
||||
// First, HTML-escaping is needed because the result of the JS expression
|
||||
// is evaluated as HTML. Second, JS-string escaping is needed; this avoids
|
||||
// \u escaping from inserting HTML tags and \ from escaping the final ".
|
||||
// Finally, URL percent-encoding is done with encodeURI(); this
|
||||
// avoids percent-encoding from bypassing HTML and JS escaping.
|
||||
//
|
||||
// Note: There are other ways the same result could be achieved but the
|
||||
// current behavior was preserved when this code was refactored to use
|
||||
// SafeUrl, in order to avoid breakage.
|
||||
var loadingMessage;
|
||||
if (!opt_message) {
|
||||
loadingMessage = '';
|
||||
} else {
|
||||
loadingMessage =
|
||||
goog.string.escapeString(goog.string.htmlEscape(opt_message));
|
||||
}
|
||||
var url = goog.html.uncheckedconversions
|
||||
.safeUrlFromStringKnownToSatisfyTypeContract(
|
||||
goog.string.Const.from(
|
||||
'b/12014412, encoded string in javascript: URL'),
|
||||
'javascript:"' + encodeURI(loadingMessage) + '"');
|
||||
return /** @type {Window} */ (goog.window.open(
|
||||
url, opt_options, opt_parentWin));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Raise a help popup window, defaulting to "Google standard" size and name.
|
||||
*
|
||||
* (If your project is using GXPs, consider using {@link PopUpLink.gxp}.)
|
||||
*
|
||||
* @param {goog.html.SafeUrl|string|Object} linkRef If an Object with an 'href'
|
||||
* attribute (such as HTMLAnchorElement) is passed then the value of 'href'
|
||||
* is used, otherwise otherwise its toString method is called. Note that
|
||||
* if a string|Object is used, an untrusted script execution might result
|
||||
* (e.g. from javascript: URLs).
|
||||
*
|
||||
* @param {Object=} opt_options Options to open window with.
|
||||
* {@see goog.window.open for exact option semantics}
|
||||
* Additional wrinkles to the options:
|
||||
* - if 'target' field is null, linkRef.target will be used. If *that's*
|
||||
* null, the default is "google_popup".
|
||||
* - if 'width' field is not specified, the default is 690.
|
||||
* - if 'height' field is not specified, the default is 500.
|
||||
*
|
||||
* @return {boolean} true if the window was not popped up, false if it was.
|
||||
*/
|
||||
goog.window.popup = function(linkRef, opt_options) {
|
||||
if (!opt_options) {
|
||||
opt_options = {};
|
||||
}
|
||||
|
||||
// set default properties
|
||||
opt_options['target'] = opt_options['target'] ||
|
||||
linkRef['target'] || goog.window.DEFAULT_POPUP_TARGET;
|
||||
opt_options['width'] = opt_options['width'] ||
|
||||
goog.window.DEFAULT_POPUP_WIDTH;
|
||||
opt_options['height'] = opt_options['height'] ||
|
||||
goog.window.DEFAULT_POPUP_HEIGHT;
|
||||
|
||||
var newWin = goog.window.open(linkRef, opt_options);
|
||||
if (!newWin) {
|
||||
return true;
|
||||
}
|
||||
newWin.focus();
|
||||
|
||||
return false;
|
||||
};
|
||||
@@ -0,0 +1,44 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
Copyright 2009 The Closure Library Authors. All Rights Reserved.
|
||||
|
||||
Use of this source code is governed by the Apache License, Version 2.0.
|
||||
See the COPYING file for details.
|
||||
-->
|
||||
<!--
|
||||
|
||||
@author marcosalmeida@google.com (Marcos Almeida)
|
||||
-->
|
||||
<head>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<title>
|
||||
Closure Unit Tests - goog.window
|
||||
</title>
|
||||
<script src="../base.js">
|
||||
</script>
|
||||
<script>
|
||||
goog.require('goog.windowTest');
|
||||
</script>
|
||||
<style type="text/css">
|
||||
.goog-like-link {
|
||||
color: blue;
|
||||
text-decoration: underline;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h4>Some links for testing referrer stripping manually.</h4>
|
||||
<div class='goog-like-link'>http://www.google.com/search?q=;</div>
|
||||
<div class='goog-like-link'>http://www.google.com/search?q=x&lang=en</div>
|
||||
<div class='goog-like-link'>http://www.google.com/search?q=x;lang=en</div>
|
||||
<div class='goog-like-link'>http://www.google.com/search?q="</div>
|
||||
<div class='goog-like-link'>http://www.google.com/search?q='</div>
|
||||
<div class='goog-like-link'>http://www.google.com/search?q=<</div>
|
||||
<div class='goog-like-link'>http://www.google.com/search?q=></div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,365 @@
|
||||
// Copyright 2009 The Closure Library Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS-IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
goog.provide('goog.windowTest');
|
||||
goog.setTestOnly('goog.windowTest');
|
||||
|
||||
goog.require('goog.Promise');
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.dom.TagName');
|
||||
goog.require('goog.events');
|
||||
goog.require('goog.functions');
|
||||
goog.require('goog.labs.userAgent.browser');
|
||||
goog.require('goog.labs.userAgent.engine');
|
||||
goog.require('goog.labs.userAgent.platform');
|
||||
goog.require('goog.string');
|
||||
goog.require('goog.testing.PropertyReplacer');
|
||||
goog.require('goog.testing.jsunit');
|
||||
goog.require('goog.window');
|
||||
|
||||
var newWin;
|
||||
var REDIRECT_URL_PREFIX = 'window_test.html?runTests=';
|
||||
var WIN_LOAD_TRY_TIMEOUT = 100;
|
||||
var MAX_WIN_LOAD_TRIES = 50; // 50x100ms = 5s waiting for window to load.
|
||||
|
||||
var stubs = new goog.testing.PropertyReplacer();
|
||||
|
||||
|
||||
function setUpPage() {
|
||||
var anchors = goog.dom.getElementsByTagNameAndClass(
|
||||
goog.dom.TagName.DIV, 'goog-like-link');
|
||||
for (var i = 0; i < anchors.length; i++) {
|
||||
goog.events.listen(
|
||||
anchors[i], 'click',
|
||||
function(e) {
|
||||
goog.window.open(
|
||||
goog.dom.getTextContent(e.target), {'noreferrer': true});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// To test goog.window.open we open a new window with this file again. Once
|
||||
// the new window parses this file it sets this variable to true, indicating
|
||||
// that the parent test may check window properties like referrer and location.
|
||||
var newWinLoaded = true;
|
||||
|
||||
|
||||
function setUp() {
|
||||
newWin = undefined;
|
||||
}
|
||||
|
||||
|
||||
function tearDown() {
|
||||
if (newWin) {
|
||||
newWin.close();
|
||||
}
|
||||
stubs.reset();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Uses setTimeout to poll a new window for the "newWinLoaded" variable, which
|
||||
* is set once the JavaScript is evaluated in that window.
|
||||
*
|
||||
* @param {Window} win
|
||||
* @return {!goog.Promise<!Window>} Promise for a window that resolves once the
|
||||
* window has loaded.
|
||||
*/
|
||||
function waitForTestWindow(win) {
|
||||
return new goog.Promise(function(resolve, reject) {
|
||||
var checkWindow = function(numTries) {
|
||||
if (!win) {
|
||||
fail('Could not open new window. Check if popup blocker is enabled.');
|
||||
}
|
||||
if (numTries > MAX_WIN_LOAD_TRIES) {
|
||||
fail('Window did not load after maximum number of checks.');
|
||||
}
|
||||
|
||||
if (win.newWinLoaded) {
|
||||
resolve(win);
|
||||
} else {
|
||||
window.setTimeout(checkWindow, WIN_LOAD_TRY_TIMEOUT);
|
||||
}
|
||||
};
|
||||
checkWindow(0);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Opens a window and then verifies that the new window has the expected
|
||||
* properties.
|
||||
*
|
||||
* @param {boolean} noreferrer Whether to test the noreferrer option.
|
||||
* @param {string} urlParam Url param to append to the url being opened.
|
||||
* @param {boolean} encodeUrlParam_opt Whether to percent-encode urlParam. This
|
||||
* is needed because IE will not encode it automatically like other browsers
|
||||
* browser and the Closure test server will 400 on certain characters in
|
||||
* the URL (like '<' and '"').
|
||||
* @return {!goog.Promise} Promise that resolves once the test is complete.
|
||||
*/
|
||||
function doTestOpenWindow(noreferrer, urlParam, encodeUrlParam_opt) {
|
||||
if (encodeUrlParam_opt) {
|
||||
urlParam = encodeURIComponent(urlParam);
|
||||
}
|
||||
// TODO(user): target is set because goog.window.open() will currently
|
||||
// allow it to be undefined, which in IE seems to result in the same window
|
||||
// being reused, instead of a new one being created. If goog.window.open()
|
||||
// is fixed to use "_blank" by default then target can be removed here.
|
||||
newWin = goog.window.open(REDIRECT_URL_PREFIX + urlParam,
|
||||
{'noreferrer': noreferrer, 'target': '_blank'});
|
||||
|
||||
return waitForTestWindow(newWin).then(function(win) {
|
||||
verifyWindow(win, noreferrer, urlParam);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Asserts that a newly created window has the correct parameters.
|
||||
*
|
||||
* @param {Window} win
|
||||
* @param {boolean} noreferrer Whether the noreferrer option is being tested.
|
||||
* @param {string} urlParam Url param appended to the url being opened.
|
||||
*/
|
||||
function verifyWindow(win, noreferrer, urlParam) {
|
||||
if (noreferrer) {
|
||||
assertEquals('Referrer should have been stripped',
|
||||
'', win.document.referrer);
|
||||
}
|
||||
|
||||
var winUrl = decodeURI(win.location);
|
||||
var expectedUrlSuffix = decodeURI(urlParam);
|
||||
assertTrue('New window href should have ended with <' + expectedUrlSuffix +
|
||||
'> but was <' + winUrl + '>',
|
||||
goog.string.endsWith(winUrl, expectedUrlSuffix));
|
||||
}
|
||||
|
||||
|
||||
function testOpenNotEncoded() {
|
||||
return doTestOpenWindow(false, 'bogus~');
|
||||
}
|
||||
|
||||
|
||||
function testOpenEncoded() {
|
||||
return doTestOpenWindow(false, 'bogus%7E');
|
||||
}
|
||||
|
||||
|
||||
function testOpenEncodedPercent() {
|
||||
// Intent of url is to pass %7E to the server, so it was encoded to %257E .
|
||||
return doTestOpenWindow(false, 'bogus%257E');
|
||||
}
|
||||
|
||||
|
||||
function testOpenNotEncodedHidingReferrer() {
|
||||
return doTestOpenWindow(true, 'bogus~');
|
||||
}
|
||||
|
||||
|
||||
function testOpenEncodedHidingReferrer() {
|
||||
return doTestOpenWindow(true, 'bogus%7E');
|
||||
}
|
||||
|
||||
|
||||
function testOpenEncodedPercentHidingReferrer() {
|
||||
// Intent of url is to pass %7E to the server, so it was encoded to %257E .
|
||||
return doTestOpenWindow(true, 'bogus%257E');
|
||||
}
|
||||
|
||||
|
||||
function testOpenSemicolon() {
|
||||
return doTestOpenWindow(true, 'beforesemi;aftersemi');
|
||||
}
|
||||
|
||||
|
||||
function testTwoSemicolons() {
|
||||
return doTestOpenWindow(true, 'a;b;c');
|
||||
}
|
||||
|
||||
|
||||
function testOpenAmpersand() {
|
||||
return doTestOpenWindow(true, 'this&that');
|
||||
}
|
||||
|
||||
|
||||
function testOpenSingleQuote() {
|
||||
return doTestOpenWindow(true, "'");
|
||||
}
|
||||
|
||||
|
||||
function testOpenDoubleQuote() {
|
||||
return doTestOpenWindow(true, '"', goog.labs.userAgent.browser.isIE());
|
||||
}
|
||||
|
||||
|
||||
function testOpenTag() {
|
||||
return doTestOpenWindow(true, '<', goog.labs.userAgent.browser.isIE());
|
||||
}
|
||||
|
||||
|
||||
function testOpenBlank() {
|
||||
newWin = goog.window.openBlank('Loading...');
|
||||
var urlParam = 'bogus~';
|
||||
newWin.location.href = REDIRECT_URL_PREFIX + urlParam;
|
||||
return waitForTestWindow(newWin).then(function() {
|
||||
verifyWindow(newWin, false, urlParam);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function testOpenBlankReturnsNullPopupBlocker() {
|
||||
var mockWin = {
|
||||
// emulate popup-blocker by returning a null window on open().
|
||||
open: function() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
var win = goog.window.openBlank('', {noreferrer: true}, mockWin);
|
||||
assertNull(win);
|
||||
}
|
||||
|
||||
|
||||
function testOpenBlankEscapesSafely() {
|
||||
// Opening a window with javascript: and then reading from its document.body
|
||||
// is problematic because in some browsers the document.body won't have been
|
||||
// updated yet, and in some IE versions the parent window does not have
|
||||
// access to document.body in new blank window.
|
||||
var navigatedUrl;
|
||||
var mockWin = {
|
||||
open: function(url) {
|
||||
navigatedUrl = url;
|
||||
}
|
||||
};
|
||||
|
||||
// Test string determines that all necessary escaping transformations happen,
|
||||
// and that they happen in the right order (HTML->JS->URI).
|
||||
// - " which would be escaped by HTML escaping and JS string escaping. It
|
||||
// should be HTML escaped.
|
||||
// - \ which would be escaped by JS string escaping and percent-encoded
|
||||
// by encodeURI(). It gets JS string escaped first (to two '\') and then
|
||||
// percent-encoded.
|
||||
var win = goog.window.openBlank('"\\', {}, mockWin);
|
||||
assertEquals('javascript:""%5C%5C"', navigatedUrl);
|
||||
}
|
||||
|
||||
|
||||
function testOpenIosBlank() {
|
||||
if (!goog.labs.userAgent.engine.isWebKit() || !window.navigator) {
|
||||
// Don't even try this on IE8!
|
||||
return;
|
||||
}
|
||||
var attrs = {};
|
||||
var dispatchedEvent = null;
|
||||
var element = {
|
||||
setAttribute: function(name, value) {
|
||||
attrs[name] = value;
|
||||
},
|
||||
dispatchEvent: function(event) {
|
||||
dispatchedEvent = event;
|
||||
}
|
||||
};
|
||||
stubs.replace(window.document, 'createElement', function(name) {
|
||||
if (name == goog.dom.TagName.A) {
|
||||
return element;
|
||||
}
|
||||
return null;
|
||||
});
|
||||
stubs.set(window.navigator, 'standalone', true);
|
||||
stubs.replace(goog.labs.userAgent.platform, 'isIos', goog.functions.TRUE);
|
||||
|
||||
var newWin = goog.window.open('http://google.com', {
|
||||
target: '_blank'
|
||||
});
|
||||
|
||||
// This mode cannot return a new window.
|
||||
assertNotNull(newWin);
|
||||
assertUndefined(newWin.document);
|
||||
|
||||
// Attributes.
|
||||
assertEquals('http://google.com', attrs['href']);
|
||||
assertEquals('_blank', attrs['target']);
|
||||
assertEquals('', attrs['rel'] || '');
|
||||
|
||||
// Click event.
|
||||
assertNotNull(dispatchedEvent);
|
||||
assertEquals('click', dispatchedEvent.type);
|
||||
}
|
||||
|
||||
|
||||
function testOpenIosBlankNoreferrer() {
|
||||
if (!goog.labs.userAgent.engine.isWebKit() || !window.navigator) {
|
||||
// Don't even try this on IE8!
|
||||
return;
|
||||
}
|
||||
var attrs = {};
|
||||
var dispatchedEvent = null;
|
||||
var element = {
|
||||
setAttribute: function(name, value) {
|
||||
attrs[name] = value;
|
||||
},
|
||||
dispatchEvent: function(event) {
|
||||
dispatchedEvent = event;
|
||||
}
|
||||
};
|
||||
stubs.replace(window.document, 'createElement', function(name) {
|
||||
if (name == goog.dom.TagName.A) {
|
||||
return element;
|
||||
}
|
||||
return null;
|
||||
});
|
||||
stubs.set(window.navigator, 'standalone', true);
|
||||
stubs.replace(goog.labs.userAgent.platform, 'isIos', goog.functions.TRUE);
|
||||
|
||||
var newWin = goog.window.open('http://google.com', {
|
||||
target: '_blank',
|
||||
noreferrer: true
|
||||
});
|
||||
|
||||
// This mode cannot return a new window.
|
||||
assertNotNull(newWin);
|
||||
assertUndefined(newWin.document);
|
||||
|
||||
// Attributes.
|
||||
assertEquals('http://google.com', attrs['href']);
|
||||
assertEquals('_blank', attrs['target']);
|
||||
assertEquals('noreferrer', attrs['rel']);
|
||||
|
||||
// Click event.
|
||||
assertNotNull(dispatchedEvent);
|
||||
assertEquals('click', dispatchedEvent.type);
|
||||
}
|
||||
|
||||
|
||||
function testOpenNoReferrerEscapesUrl() {
|
||||
var documentWriteHtml;
|
||||
var mockNewWin = {};
|
||||
mockNewWin.document = {
|
||||
write: function(html) {
|
||||
documentWriteHtml = html;
|
||||
},
|
||||
close: function() {}
|
||||
};
|
||||
var mockWin = {
|
||||
open: function() {
|
||||
return mockNewWin;
|
||||
}
|
||||
};
|
||||
goog.window.open('https://hello&world', {noreferrer: true}, mockWin);
|
||||
assertRegExp(
|
||||
'Does not contain expected HTML-escaped string: ' + documentWriteHtml,
|
||||
/hello&world/,
|
||||
documentWriteHtml);
|
||||
}
|
||||
Reference in New Issue
Block a user