Commit 2bd86a07 authored by Camillo Bruni's avatar Camillo Bruni Committed by Commit Bot

[tools] Add link_click chrome extension

This extension imitates user-interaction on a page by randomly clicking on
links matching a given regexp pattern.

Change-Id: I210bebf36ce6e3a3c785953010ce21528093d1af
NOTRY=true

Change-Id: I210bebf36ce6e3a3c785953010ce21528093d1af
Reviewed-on: https://chromium-review.googlesource.com/500247
Commit-Queue: Camillo Bruni <cbruni@chromium.org>
Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#45201}
parent 5c66d6fc
This extension can be used to repro infrequent crashers on an unclear url-set
for a given domain. It follows a random link that matches a predefined pattern,
imitating something like real user interaction on a page.
Usage:
1. Open chrome://extensions
2. Enable developer mode
3. Click "Load unpacked extension"
4. Click the orange link-clicker extension button in the toolbar
5. Set the parameters and click "Enable" to start following links on all tabs
open in the current window. Beware, this extension will follow arbitrary
links. You probably don't want to be logged in with any important account.
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
(function linkClickerBackgroundScript() {
// time in ms.
let minInterval = 1*1000;
let maxInterval = 20*1000;
let pattern = /.*/;
let enabled = false;
let animateIconIntervalId;
// ===========================================================================
chrome.runtime.onMessage.addListener(function(msg, sender, response) {
let result;
if (msg.type == 'update') result = updateFromMessage(msg);
if (msg.type == 'get') result = getValues();
response(result);
});
// ===========================================================================
function updateFromMessage(msg) {
console.log(msg);
minInterval = Number(msg.minInterval)
maxInterval = Number(msg.maxInterval);
if (maxInterval < minInterval) {
let tmpMin = Math.min(minInterval, maxInterval);
maxInterval = Math.max(minInterval, maxInterval);
minInterval = tmpMin;
}
pattern = new RegExp(msg.pattern);
enabled = Boolean(msg.enabled);
updateTabs();
scheduleIconAnimation();
return getValues();
}
function getValues() {
return {
type: 'update',
minInterval: minInterval,
maxInterval: maxInterval,
pattern: pattern.source,
enabled: enabled
}
}
function updateTabs() {
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
let message = getValues();
for (let i = 0; i < tabs.length; ++i) {
chrome.tabs.sendMessage(tabs[i].id, message);
}
});
}
let animationIndex = 0;
function animateIcon() {
animationIndex = (animationIndex + 1) % 4;
chrome.browserAction.setBadgeText( { text: ".".repeat(animationIndex) } );
}
function scheduleIconAnimation() {
chrome.browserAction.setBadgeText( { text: "" } );
clearInterval(animateIconIntervalId);
if (enabled) {
animateIconIntervalId = setInterval(animateIcon, 500);
}
}
})();
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
(function linkClickerContentScript() {
// time in ms
let minInterval;
let maxInterval;
let pattern;
let enabled;
let timeoutId;
// Initialize variables.
chrome.runtime.sendMessage({type:'get'}, function(msg) {
if (msg.type == 'update') updateFromMessage(msg);
});
chrome.runtime.onMessage.addListener(
function(msg, sender, sendResponse) {
if (msg.type == 'update') updateFromMessage(msg);
});
function findAllLinks() {
let links = document.links;
let results = new Set();
for (let i = 0; i < links.length; i++) {
let href = links[i].href;
if (!href) continue;
if (href && href.match(pattern)) results.add(href);
}
return Array.from(results);
}
function updateFromMessage(msg) {
console.log(msg);
minInterval = Number(msg.minInterval)
maxInterval = Number(msg.maxInterval);
pattern = new RegExp(msg.pattern);
enabled = Boolean(msg.enabled);
if (enabled) schedule();
}
function followLink() {
if (!enabled) return;
let links = findAllLinks();
if (links.length <= 5) {
// navigate back if the page has not enough links
window.history.back()
console.log("navigate back");
} else {
let link = links[Math.round(Math.random() * (links.length-1))];
console.log(link);
window.location.href = link;
// Schedule in case we just followed an anchor.
schedule();
}
}
function schedule() {
clearTimeout(timeoutId);
let delta = maxInterval - minInterval;
let duration = minInterval + (Math.random() * delta);
console.log(duration);
timeoutId = setTimeout(followLink, duration);
}
})();
This diff was suppressed by a .gitattributes entry.
{
"name": "A browser action with a popup that automatically clicks links matching a regexp",
"description": "Follow links",
"version": "1.0",
"permissions": [
"tabs", "http://*/*", "https://*/*"
],
"background": { "scripts": ["background.js"] },
"browser_action": {
"default_title": "Follow links.",
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"content_scripts": [
{
"matches": ["http://*/*", "https://*/*"],
"js": ["content.js"]
}
],
"manifest_version": 2
}
<!doctype html>
<!--
Copyright 2017 the V8 project authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->
<html>
<head>
<style>
body {
overflow: hidden;
padding: 5px;
width: 310px;
}
input, textarea, select, button {
width : 300px;
margin: 0;
box-sizing: border-box;
}
label {
clear: both;
}
</style>
<script src="popup.js"></script>
</head>
<body>
<form>
<p>
<label>Min click-interval <span id="minIntervalValue"></span>:
<input type="range" id="minInterval" min="1000" max="60000">
</label>
</p>
<p>
<label> Max click-interval <span id="maxIntervalValue"></span>:
<input type="range" id="maxInterval" min="1000" max="60000">
</label>
</p>
<p>
<label>Link regexp:
<input type="input" id="pattern" >
</label>
</p>
<p>
<label>Enable:
<input type="checkbox" id="enabled" >
</label>
</p>
</form>
</body>
</html>
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
function $(id) {
return document.querySelector(id);
}
// ===========================================================================
document.addEventListener('DOMContentLoaded', function () {
installFormChangeHandler()
});
function installFormChangeHandler() {
initForm();
let inputs = document.getElementsByTagName("input");
for (let i = 0; i < inputs.length; i++){
inputs[i].onchange = onFormChange;
}
}
function initForm() {
chrome.runtime.sendMessage({type:'get'}, function(response) {
updateFromMessage(response);
});
}
// ===========================================================================
function updateFromMessage(msg) {
$("#minInterval").value = msg.minInterval;
$("#maxInterval").value = msg.maxInterval;
$("#pattern").value = msg.pattern;
$("#enabled").checked = msg.enabled;
$("#minIntervalValue").innerText = msg.minInterval+"ms";
$("#maxIntervalValue").innerText = msg.maxInterval+"ms";
}
function onFormChange() {
let minInterval = $("#minInterval").value;
let maxInterval = $("#maxInterval").value;
let message = {
type: 'update',
minInterval: minInterval,
maxInterval: maxInterval,
pattern: $("#pattern").value,
enabled: $("#enabled").checked
}
chrome.runtime.sendMessage(message, function(response) {
updateFromMessage(response);
});
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment