blob: 5e5bf47164cb299b66e463aa9326c2bf9f3a83fc [file] [log] [blame] [edit]
'use strict';
// Concept heavily borrowed from
// //depot/google3/wireless/android/tools/android_bug_tool/extension/listnr_content_script/listnr_content_script.ts
// WARNING: This function may not reference any non-globals outside this
// function as it is stringified below to be inserted into the page.
function setup() {
if (typeof angular !== 'undefined') {
angular.element(document.documentElement)['injector']().invoke(
($rootScope) => {
$rootScope.$on('$locationChangeSuccess', (e) => {
window.postMessage(
{source: '__shill_log_tool', message: 'LOCATION_UPDATED'},
'*');
});
$rootScope.$watch(() => {
window.postMessage(
{source: '__shill_log_tool', message: 'DIGEST'}, '*');
});
});
}
}
const INJECTED_ANGULAR_UPDATE_DETECTION_SCRIPT =
'(' + setup.toString() + ')();';
// Inject script into Listnr page.
const script = document.createElement('script');
script.textContent = INJECTED_ANGULAR_UPDATE_DETECTION_SCRIPT;
document.head.appendChild(script);
// Setup listener for events angular update events from Listnr page.
window.addEventListener('message', (e) => {
if (e.data.source === '__shill_log_tool') {
if (e.data.message === 'LOCATION_UPDATED' || e.data.message === 'DIGEST') {
delayedUpdate();
}
}
});
const UPDATE_DEBOUNCE_DELAY = 500;
let pendingTimer = null;
/**
* Schedule a delayed update. If an update is already scheduled then it is
* canceled and replaced with the new timer.
*/
function delayedUpdate() {
if (pendingTimer) {
clearTimeout(pendingTimer);
pendingTimer = null;
}
pendingTimer = window.setTimeout(() => {
pendingTimer = null;
update();
}, UPDATE_DEBOUNCE_DELAY);
}
function forEachUnprocessedAttachmentSectionsMarkAnd(callback) {
const attachmentSections = document.body.querySelectorAll(
'[section-title="Product Specific Binary Data"] > div.zipper > ng-transclude');
for (let i = 0; i < attachmentSections.length; ++i) {
const attachmentsSection =
attachmentSections[i];
if (attachmentsSection.__shill_log_tool) {
continue;
}
attachmentsSection.__shill_log_tool = true;
callback(attachmentsSection);
}
}
function createAttachmentLinkWithLoading(
text, addedClass, target) {
const link = document.createElement('a');
link.classList.add(addedClass);
link.style.cursor = 'pointer';
link.style.marginLeft = '1em';
link.onclick = (ev) => {
// Change the link to a loading stage.
link.style.pointerEvents = 'none';
if (link.lastChild == null) {
throw new Error('No element found in link');
} else {
link.lastChild.textContent = ' Opening...';
}
// Perform the action.
target(ev);
};
link.appendChild(document.createTextNode(' ' + text));
return link;
}
function removeLoadingState(element, originalText, addedClass) {
const link = element.querySelector('.' + addedClass);
if (!link) return;
link.style.pointerEvents = 'auto';
if (link.lastChild != null) {
link.lastChild.textContent = originalText;
}
}
function createOpenShillToolLink(downloadUrl, attachment) {
const className = 'open-shill-tool-link';
const magnifyingGlassEmoji = '\u{1F50D}';
const humanName = magnifyingGlassEmoji + ' Open Shill Log Tool';
return createAttachmentLinkWithLoading(
humanName, className, () => {
chrome.runtime.sendMessage(
{'action': 'open_shill_page', 'data': downloadUrl}, () => {
console.log('got fix link callback');
removeLoadingState(
attachment, humanName, className);
});
});
}
function getDownloadUrlFromAttachmentElement(attachment) {
const existingLinks = attachment.querySelectorAll('a');
for (let i = 0; i < existingLinks.length; ++i) {
const existingLink = existingLinks[i];
if (existingLink.textContent &&
existingLink.textContent.trim() === 'file_download') {
return existingLink.href;
}
}
return null;
}
function update() {
forEachUnprocessedAttachmentSectionsMarkAnd((attachmentsSection) => {
const attachments = attachmentsSection.querySelectorAll('div > div');
const downloadUrls = [];
for (let i = 0; i < attachments.length; ++i) {
const attachment = attachments[i];
const downloadUrl = getDownloadUrlFromAttachmentElement(attachment);
if (downloadUrl) {
if (downloadUrl.includes('system_logs.zip')) {
attachment.appendChild(
createOpenShillToolLink(downloadUrl, attachment));
}
}
}
});
}
delayedUpdate();