blob: 6d125e1e0a20ef9ee82fe263d2b282db2c47c048 [file]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Common js for prerender loaders; defines the helper functions that put
// event handlers on prerenders and track the events for browser tests.
// TODO(gavinp): Put more common loader logic in here.
// Currently only errors with the ordering of Prerender events are caught.
var hadPrerenderEventErrors = false;
var receivedPrerenderEvents = {
'webkitprerenderstart': [],
'webkitprerenderdomcontentloaded': [],
'webkitprerenderload': [],
'webkitprerenderstop': [],
}
// A list of callbacks to be called on every prerender event. Each callback
// returns true if it should never be called again, or false to remain in the
// list and be called on future events. These are used to implement
// WaitForPrerenderEventCount.
var prerenderEventCallbacks = [];
function GetPrerenderEventCount(index, type) {
return receivedPrerenderEvents[type][index] || 0;
}
function PrerenderEventHandler(index, ev) {
// Check for errors.
if (ev.type == 'webkitprerenderstart') {
// No event may preceed start.
if (GetPrerenderEventCount(index, 'webkitprerenderstart') ||
GetPrerenderEventCount(index, 'webkitprerenderdomcontentloaded') ||
GetPrerenderEventCount(index, 'webkitprerenderload') ||
GetPrerenderEventCount(index, 'webkitprerenderstop')) {
hadPrerenderEventErrors = true;
}
} else {
// There may be multiple load or domcontentloaded events, but they must not
// come after start and must come before stop. And there may be at most one
// start. Note that stop may be delivered without any load events.
if (!GetPrerenderEventCount(index, 'webkitprerenderstart') ||
GetPrerenderEventCount(index, 'webkitprerenderstop')) {
hadPrerenderEventErrors = true;
}
}
// Update count.
receivedPrerenderEvents[ev.type][index] =
(receivedPrerenderEvents[ev.type][index] || 0) + 1;
// Run all callbacks. Remove the ones that are done.
prerenderEventCallbacks = prerenderEventCallbacks.filter(function(callback) {
return !callback();
});
}
// Calls |callback| when at least |count| instances of event |type| have been
// observed for prerender |index|.
function WaitForPrerenderEventCount(index, type, count, callback) {
var checkCount = function() {
if (GetPrerenderEventCount(index, type) >= count) {
callback();
return true;
}
return false;
};
if (!checkCount())
prerenderEventCallbacks.push(checkCount);
}
function AddEventHandlersToLinkElement(link, index) {
link.addEventListener('webkitprerenderstart',
PrerenderEventHandler.bind(null, index), false);
link.addEventListener('webkitprerenderdomcontentloaded',
PrerenderEventHandler.bind(null, index), false);
link.addEventListener('webkitprerenderload',
PrerenderEventHandler.bind(null, index), false);
link.addEventListener('webkitprerenderstop',
PrerenderEventHandler.bind(null, index), false);
}
function AddPrerender(url, index) {
var link = document.createElement('link');
link.id = 'prerenderElement' + index;
link.rel = 'prerender';
link.href = url;
AddEventHandlersToLinkElement(link, index);
document.body.appendChild(link);
return link;
}
function RemoveLinkElement(index) {
var link = document.getElementById('prerenderElement' + index);
link.parentElement.removeChild(link);
}
function ExtractGetParameterBadlyAndInsecurely(param, defaultValue) {
var re = RegExp('[&?]' + param + '=([^&?#]*)');
var result = re.exec(document.location);
if (result)
return result[1];
return defaultValue;
}
function AddAnchor(href, target) {
var a = document.createElement('a');
a.href = href;
if (target)
a.target = target;
document.body.appendChild(a);
return a;
}
function Click(url) {
AddAnchor(url).dispatchEvent(new MouseEvent('click', {
view: window,
bubbles: true,
cancelable: true,
detail: 1
}));
}
function ClickTarget(url) {
var eventObject = new MouseEvent('click', {
view: window,
bubbles: true,
cancelable: true,
detail: 1
});
AddAnchor(url, '_blank').dispatchEvent(eventObject);
}
function ClickPing(url, pingUrl) {
var a = AddAnchor(url);
a.ping = pingUrl;
a.dispatchEvent(new MouseEvent('click', {
view: window,
bubbles: true,
cancelable: true,
detail: 1
}));
}
function ShiftClick(url) {
AddAnchor(url).dispatchEvent(new MouseEvent('click', {
view: window,
bubbles: true,
cancelable: true,
detail: 1,
shiftKey: true
}));
}
function CtrlClick(url) {
AddAnchor(url).dispatchEvent(new MouseEvent('click', {
view: window,
bubbles: true,
cancelable: true,
detail: 1,
ctrlKey: true
}));
}
function CtrlShiftClick(url) {
AddAnchor(url).dispatchEvent(new MouseEvent('click', {
view: window,
bubbles: true,
cancelable: true,
detail: 1,
ctrlKey: true,
shiftKey: true
}));
}
function MetaClick(url) {
AddAnchor(url).dispatchEvent(new MouseEvent('click', {
view: window,
bubbles: true,
cancelable: true,
detail: 1,
metaKey: true
}));
}
function MetaShiftClick(url) {
AddAnchor(url).dispatchEvent(new MouseEvent('click', {
view: window,
bubbles: true,
cancelable: true,
detail: 1,
metaKey: true,
shiftKey: true
}));
}
function WindowOpen(url) {
window.open(url);
}